From 3edc3ccd24d6502a88cea50973bbbcab91203165 Mon Sep 17 00:00:00 2001 From: Scott Kruyswyk Date: Fri, 2 May 2025 11:39:25 -0600 Subject: [PATCH 1/4] Add ClientCredentialsTokenProvider --- lib/build.gradle | 3 + .../auth/AuthTokenResponse.java | 9 + .../auth/ClientCredentialsTokenProvider.java | 186 ++++++++++++++++++ .../ClientCredentialsTokenProviderTest.java | 105 ++++++++++ versions.lock | 23 ++- versions.props | 2 + 6 files changed, 319 insertions(+), 9 deletions(-) create mode 100644 lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java create mode 100644 lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java create mode 100644 lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java diff --git a/lib/build.gradle b/lib/build.gradle index bbcd825..74a0701 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -4,5 +4,8 @@ dependencies { implementation 'com.palantir.safe-logging:logger' implementation 'com.palantir.safe-logging:preconditions' + testImplementation 'org.assertj:assertj-core' testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.mockito:mockito-core' + testImplementation 'org.mockito:mockito-junit-jupiter' } diff --git a/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java b/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java new file mode 100644 index 0000000..53db965 --- /dev/null +++ b/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java @@ -0,0 +1,9 @@ +package com.palantir.computemodules.auth; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record AuthTokenResponse( + @JsonProperty("access_token") String accessToken, + @JsonProperty("scope") String scope, + @JsonProperty("expires_in") Integer expiresIn, + @JsonProperty("token_type") String tokenType) {} diff --git a/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java b/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java new file mode 100644 index 0000000..bdf9f93 --- /dev/null +++ b/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java @@ -0,0 +1,186 @@ +package com.palantir.computemodules.auth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palantir.logsafe.SafeArg; +import com.palantir.logsafe.exceptions.SafeIllegalArgumentException; +import com.palantir.logsafe.logger.SafeLogger; +import com.palantir.logsafe.logger.SafeLoggerFactory; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.StringJoiner; +import java.util.function.Supplier; +import javax.annotation.Nullable; + + +public final class ClientCredentialsTokenProvider implements Supplier { + private static final SafeLogger log = SafeLoggerFactory.get(ClientCredentialsTokenProvider.class); + private static final Duration refreshInterval = Duration.ofHours(1); + private static final String oauthTokenPath = "/multipass/api/oauth2/token"; + private static final ObjectMapper mapper = new ObjectMapper(); + + private final HttpClient client; + private Instant lastRefreshed; + private Optional maybeTokenResponse; + + private final String hostname; + private final String clientId; + private final String clientSecret; + private final List scopes; + + private ClientCredentialsTokenProvider( + String hostname, String clientId, String clientSecret, List scopes, HttpClient client) { + this.hostname = extractHost(hostname); + this.clientId = clientId; + this.clientSecret = clientSecret; + this.scopes = scopes; + this.client = client; + lastRefreshed = Instant.now(); + maybeTokenResponse = Optional.empty(); + } + + public static ClientCredentialsTokenProviderBuilder builder() { + return new ClientCredentialsTokenProviderBuilder(); + } + + @Override + public synchronized String get() { + if (shouldRefreshToken()) { + refreshToken(); + } + return maybeTokenResponse.map(AuthTokenResponse::accessToken).orElseThrow(); + } + + public static Optional getClientId() { + String clientId = System.getenv("CLIENT_ID"); + return Optional.ofNullable(clientId); + } + + public static Optional getClientSecret() { + String clientSecret = System.getenv("CLIENT_SECRET"); + return Optional.ofNullable(clientSecret); + } + + private static String extractHost(String host) { + try { + URL url = new URL(host); + return url.getHost(); + } catch (MalformedURLException e) { + return host; + } + } + + private boolean shouldRefreshToken() { + if (maybeTokenResponse.isEmpty()) { + return true; + } + Instant now = Instant.now(); + Duration timeSinceLastRefresh = Duration.between(lastRefreshed, now); + return timeSinceLastRefresh.compareTo(refreshInterval) > 0; + } + + private String buildFormParams() { + StringJoiner joiner = new StringJoiner("&"); + joiner.add("grant_type=" + URLEncoder.encode("client_credentials", StandardCharsets.UTF_8)); + joiner.add("client_id=" + URLEncoder.encode(clientId, StandardCharsets.UTF_8)); + joiner.add("client_secret=" + URLEncoder.encode(clientSecret, StandardCharsets.UTF_8)); + joiner.add("scope=" + URLEncoder.encode(String.join(" ", scopes), StandardCharsets.UTF_8)); + + return joiner.toString(); + } + + private void refreshToken() { + // TODO(sk): might want to retry + try { + lastRefreshed = Instant.now(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https", hostname, oauthTokenPath, null)) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(buildFormParams())) + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + maybeTokenResponse = deserialize(response.body()); + return; + } + log.warn("Non-200 status code returned from token endpoint", SafeArg.of("response", response)); + } catch (URISyntaxException | IOException | InterruptedException e) { + log.error("Exception raised trying to refresh token", e); + } + } + + private Optional deserialize(String raw) { + try { + AuthTokenResponse response = mapper.readValue(raw, AuthTokenResponse.class); + return Optional.of(response); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static final class ClientCredentialsTokenProviderBuilder { + private @Nullable String hostname = null; + private @Nullable String clientId; + private @Nullable String clientSecret; + private final List scopes; + private HttpClient client = HttpClient.newBuilder().build(); + + private ClientCredentialsTokenProviderBuilder() { + clientId = getClientId().orElse(null); + clientSecret = getClientSecret().orElse(null); + scopes = new ArrayList<>(); + } + + public ClientCredentialsTokenProviderBuilder hostname(String value) { + hostname = value; + return this; + } + + public ClientCredentialsTokenProviderBuilder clientId(String value) { + clientId = value; + return this; + } + + public ClientCredentialsTokenProviderBuilder clientSecret(String value) { + clientSecret = value; + return this; + } + + public ClientCredentialsTokenProviderBuilder scopes(String... values) { + Collections.addAll(scopes, values); + return this; + } + + public ClientCredentialsTokenProviderBuilder client(HttpClient value) { + client = value; + return this; + } + + public ClientCredentialsTokenProvider build() { + if (hostname == null) { + throw new SafeIllegalArgumentException("hostname must be set"); + } + if (clientId == null) { + throw new SafeIllegalArgumentException("clientId must be set"); + } + if (clientSecret == null) { + throw new SafeIllegalArgumentException("clientSecret must be set"); + } + return new ClientCredentialsTokenProvider(hostname, clientId, clientSecret, scopes, client); + } + } +} diff --git a/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java b/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java new file mode 100644 index 0000000..eeced95 --- /dev/null +++ b/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java @@ -0,0 +1,105 @@ +package com.palantir.computemodules; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palantir.computemodules.auth.AuthTokenResponse; +import com.palantir.computemodules.auth.ClientCredentialsTokenProvider; +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.NoSuchElementException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class ClientCredentialsTokenProviderTest { + private static final String CLIENT_ID = "client_id"; + private static final String CLIENT_SECRET = "client_secret"; + private static final String hostname = "foundry.stack.com"; + private static final String hostnameWithScheme = "https://" + hostname; + private static final String expectedTokenUrl = hostnameWithScheme + "/multipass/api/oauth2/token"; + private static final String scope1 = "my-app:view"; + private static final String scope2 = "my-app:write"; + private static final AuthTokenResponse mockOkTokenResponse = + new AuthTokenResponse("dummy_token", scope1 + " " + scope2, 3600, "Bearer"); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Mock + private HttpClient client; + + @Mock + private HttpResponse response; + + private ClientCredentialsTokenProvider fixture; + + @Test + void get_provides_access_token() throws IOException, InterruptedException { + fixture = ClientCredentialsTokenProvider.builder() + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .hostname(hostname) + .scopes(scope1, scope2) + .client(client) + .build(); + + when(client.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))) + .thenReturn(response); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn(objectMapper.writeValueAsString(mockOkTokenResponse)); + String token = fixture.get(); + assertNotNull(token); + assertEquals(token, "dummy_token"); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); + Mockito.verify(client).send(requestCaptor.capture(), any(HttpResponse.BodyHandler.class)); + HttpRequest capturedRequest = requestCaptor.getValue(); + assertEquals(capturedRequest.uri().toString(), expectedTokenUrl); + } + + @Test + void provider_works_with_scheme_in_hostname() throws IOException, InterruptedException { + fixture = ClientCredentialsTokenProvider.builder() + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .hostname(hostnameWithScheme) + .scopes(scope1, scope2) + .client(client) + .build(); + + when(client.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))) + .thenReturn(response); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn(objectMapper.writeValueAsString(mockOkTokenResponse)); + String token = fixture.get(); + assertNotNull(token); + assertEquals(token, "dummy_token"); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); + Mockito.verify(client).send(requestCaptor.capture(), any(HttpResponse.BodyHandler.class)); + HttpRequest capturedRequest = requestCaptor.getValue(); + assertEquals(capturedRequest.uri().toString(), expectedTokenUrl); + } + + @Test + void throws_when_token_response_non_200() throws IOException, InterruptedException { + fixture = ClientCredentialsTokenProvider.builder() + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .hostname(hostname) + .scopes(scope1, scope2) + .client(client) + .build(); + when(client.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))) + .thenReturn(response); + when(response.statusCode()).thenReturn(400); + assertThatThrownBy(() -> fixture.get()).isInstanceOf(NoSuchElementException.class); + } +} diff --git a/versions.lock b/versions.lock index 40d323e..a1d6de0 100644 --- a/versions.lock +++ b/versions.lock @@ -14,18 +14,23 @@ com.palantir.safe-logging:logger-slf4j:3.7.0 (1 constraints: 050e6842) com.palantir.safe-logging:logger-spi:3.7.0 (2 constraints: 191ea27b) com.palantir.safe-logging:preconditions:3.7.0 (1 constraints: 0c050f36) com.palantir.safe-logging:safe-logging:3.7.0 (3 constraints: 872e9986) -net.bytebuddy:byte-buddy:1.14.9 (1 constraints: 8f123b21) +net.bytebuddy:byte-buddy:1.15.11 (3 constraints: 7f293f9b) org.checkerframework:checker-qual:3.43.0 (1 constraints: 4c0a4abf) org.jetbrains:annotations:24.1.0 (1 constraints: 331166d1) org.slf4j:slf4j-api:1.7.36 (1 constraints: 471091b6) [Test dependencies] -org.junit:junit-bom:5.11.2 (7 constraints: c6758106) -org.junit.jupiter:junit-jupiter:5.11.2 (2 constraints: b91096ee) -org.junit.jupiter:junit-jupiter-api:5.11.2 (4 constraints: 333963e3) -org.junit.jupiter:junit-jupiter-engine:5.11.2 (2 constraints: 7517f163) -org.junit.jupiter:junit-jupiter-params:5.11.2 (2 constraints: 7517f163) -org.junit.platform:junit-platform-commons:1.11.2 (3 constraints: 6c2a7c8f) -org.junit.platform:junit-platform-engine:1.11.2 (3 constraints: 842ce87e) -org.junit.platform:junit-platform-launcher:1.11.2 (2 constraints: 720efd70) +net.bytebuddy:byte-buddy-agent:1.15.11 (1 constraints: 730bb5e9) +org.assertj:assertj-core:3.27.3 (1 constraints: 4105513b) +org.junit:junit-bom:5.11.4 (7 constraints: d475c50e) +org.junit.jupiter:junit-jupiter:5.11.4 (2 constraints: bb1098ee) +org.junit.jupiter:junit-jupiter-api:5.11.4 (5 constraints: 304871ed) +org.junit.jupiter:junit-jupiter-engine:5.11.4 (2 constraints: 79174764) +org.junit.jupiter:junit-jupiter-params:5.11.4 (2 constraints: 79174764) +org.junit.platform:junit-platform-commons:1.11.4 (3 constraints: 722aa490) +org.junit.platform:junit-platform-engine:1.11.4 (3 constraints: 8a2c1e80) +org.junit.platform:junit-platform-launcher:1.11.4 (2 constraints: 740eff70) +org.mockito:mockito-core:5.16.1 (2 constraints: 36145987) +org.mockito:mockito-junit-jupiter:5.16.1 (1 constraints: 3f05543b) +org.objenesis:objenesis:3.3 (1 constraints: b20a14bd) org.opentest4j:opentest4j:1.3.0 (2 constraints: cf209249) diff --git a/versions.props b/versions.props index e22c788..7368f90 100644 --- a/versions.props +++ b/versions.props @@ -4,3 +4,5 @@ org.junit.jupiter:* = 5.11.2 org.junit.platform:* = 1.11.2 org.slf4j:* = 1.7.36 com.palantir.safe-logging:* = 3.7.0 +org.mockito:* = 5.16.1 +org.assertj:assertj-core = 3.27.3 From 621f6964d26e176a3099409d1be9b72e85459001 Mon Sep 17 00:00:00 2001 From: Scott Kruyswyk Date: Fri, 2 May 2025 12:36:41 -0600 Subject: [PATCH 2/4] spotlessApply --- .../computemodules/auth/AuthTokenResponse.java | 15 +++++++++++++++ .../auth/ClientCredentialsTokenProvider.java | 16 +++++++++++++++- .../ClientCredentialsTokenProviderTest.java | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java b/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java index 53db965..15716af 100644 --- a/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java +++ b/lib/src/main/java/com/palantir/computemodules/auth/AuthTokenResponse.java @@ -1,3 +1,18 @@ +/* + * (c) Copyright 2025 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.palantir.computemodules.auth; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java b/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java index bdf9f93..1287c1c 100644 --- a/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java +++ b/lib/src/main/java/com/palantir/computemodules/auth/ClientCredentialsTokenProvider.java @@ -1,3 +1,18 @@ +/* + * (c) Copyright 2025 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.palantir.computemodules.auth; import com.fasterxml.jackson.core.JsonProcessingException; @@ -26,7 +41,6 @@ import java.util.function.Supplier; import javax.annotation.Nullable; - public final class ClientCredentialsTokenProvider implements Supplier { private static final SafeLogger log = SafeLoggerFactory.get(ClientCredentialsTokenProvider.class); private static final Duration refreshInterval = Duration.ofHours(1); diff --git a/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java b/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java index eeced95..c0561c1 100644 --- a/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java +++ b/lib/src/test/java/com/palantir/computemodules/ClientCredentialsTokenProviderTest.java @@ -1,3 +1,18 @@ +/* + * (c) Copyright 2025 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.palantir.computemodules; import static org.assertj.core.api.Assertions.assertThatThrownBy; From 8dabdbd2b3f06ecdd8cf5ed21128bcbfc2ba1214 Mon Sep 17 00:00:00 2001 From: Scott Kruyswyk Date: Fri, 2 May 2025 12:37:52 -0600 Subject: [PATCH 3/4] ./gradlew classes testClasses -PerrorProneApply=SafeLoggingPropagation --- .../main/java/com/palantir/computemodules/ComputeModule.java | 3 ++- .../com/palantir/computemodules/functions/FunctionRunner.java | 3 ++- .../com/palantir/computemodules/functions/results/Result.java | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/src/main/java/com/palantir/computemodules/ComputeModule.java b/lib/src/main/java/com/palantir/computemodules/ComputeModule.java index 859099c..a5d9a49 100644 --- a/lib/src/main/java/com/palantir/computemodules/ComputeModule.java +++ b/lib/src/main/java/com/palantir/computemodules/ComputeModule.java @@ -32,6 +32,7 @@ import com.palantir.computemodules.functions.serde.DefaultDeserializer; import com.palantir.computemodules.functions.serde.DefaultSerializer; import com.palantir.logsafe.SafeArg; +import com.palantir.logsafe.Unsafe; import com.palantir.logsafe.exceptions.SafeRuntimeException; import com.palantir.logsafe.logger.SafeLogger; import com.palantir.logsafe.logger.SafeLoggerFactory; @@ -90,7 +91,7 @@ public void onFailure(Throwable throwable) { } } - private Result execute(ComputeModuleJob job) { + @Unsafe private Result execute(ComputeModuleJob job) { if (functions.containsKey(job.queryType())) { return functions.get(job.queryType()).run(new Context(job.jobId()), job.query()); } else { diff --git a/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java b/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java index ad5df46..1e93020 100644 --- a/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java +++ b/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java @@ -20,6 +20,7 @@ import com.palantir.computemodules.functions.results.Result; import com.palantir.computemodules.functions.serde.Deserializer; import com.palantir.computemodules.functions.serde.Serializer; +import com.palantir.logsafe.Unsafe; import java.io.InputStream; public final class FunctionRunner { @@ -42,7 +43,7 @@ public FunctionRunner( this.serializer = serializer; } - public Result run(Context context, Object input) { + @Unsafe public Result run(Context context, Object input) { I deserializedInput = deserializer.deserialize(input, inputType); try { O result = function.run(context, deserializedInput); diff --git a/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java b/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java index 7b9d5ba..732462a 100644 --- a/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java +++ b/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java @@ -15,4 +15,6 @@ */ package com.palantir.computemodules.functions.results; -public sealed interface Result permits Ok, Failed {} +import com.palantir.logsafe.Unsafe; + +@Unsafe public sealed interface Result permits Ok, Failed {} From d92bac963ec31e5eb5ac467634139f30b3685dfc Mon Sep 17 00:00:00 2001 From: Scott Kruyswyk Date: Fri, 2 May 2025 12:41:23 -0600 Subject: [PATCH 4/4] spotlessApply --- .../main/java/com/palantir/computemodules/ComputeModule.java | 3 ++- .../com/palantir/computemodules/functions/FunctionRunner.java | 3 ++- .../com/palantir/computemodules/functions/results/Result.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/src/main/java/com/palantir/computemodules/ComputeModule.java b/lib/src/main/java/com/palantir/computemodules/ComputeModule.java index a5d9a49..e236072 100644 --- a/lib/src/main/java/com/palantir/computemodules/ComputeModule.java +++ b/lib/src/main/java/com/palantir/computemodules/ComputeModule.java @@ -91,7 +91,8 @@ public void onFailure(Throwable throwable) { } } - @Unsafe private Result execute(ComputeModuleJob job) { + @Unsafe + private Result execute(ComputeModuleJob job) { if (functions.containsKey(job.queryType())) { return functions.get(job.queryType()).run(new Context(job.jobId()), job.query()); } else { diff --git a/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java b/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java index 1e93020..958635a 100644 --- a/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java +++ b/lib/src/main/java/com/palantir/computemodules/functions/FunctionRunner.java @@ -43,7 +43,8 @@ public FunctionRunner( this.serializer = serializer; } - @Unsafe public Result run(Context context, Object input) { + @Unsafe + public Result run(Context context, Object input) { I deserializedInput = deserializer.deserialize(input, inputType); try { O result = function.run(context, deserializedInput); diff --git a/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java b/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java index 732462a..8952c61 100644 --- a/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java +++ b/lib/src/main/java/com/palantir/computemodules/functions/results/Result.java @@ -17,4 +17,5 @@ import com.palantir.logsafe.Unsafe; -@Unsafe public sealed interface Result permits Ok, Failed {} +@Unsafe +public sealed interface Result permits Ok, Failed {}