From 36d6e3bde9f7b5c95cf490af26cd36703a394e82 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:54:42 -0700 Subject: [PATCH 1/2] SDK Generation --- .fern/metadata.json | 8 ++-- README.md | 33 ++++++-------- build.gradle | 4 +- .../java/com/anduril/core/ClientOptions.java | 4 +- .../com/anduril/core/DoubleSerializer.java | 43 +++++++++++++++++++ .../java/com/anduril/core/ObjectMappers.java | 1 + .../com/anduril/core/RetryInterceptor.java | 9 ++-- .../types/StreamEntitiesResponse.java | 2 + .../objects/requests/ListObjectsRequest.java | 12 +++--- .../tasks/types/StreamAsAgentResponse.java | 2 + .../tasks/types/StreamTasksResponse.java | 2 + 11 files changed, 81 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/anduril/core/DoubleSerializer.java diff --git a/.fern/metadata.json b/.fern/metadata.json index 03b76697..aaff6eaf 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,11 +1,11 @@ { - "cliVersion": "4.23.1", + "cliVersion": "4.53.1", "generatorName": "fernapi/fern-java-sdk", - "generatorVersion": "3.44.1", + "generatorVersion": "4.0.9", "generatorConfig": { "client-class-name": "Lattice", "package-prefix": "com.anduril" }, - "originGitCommit": "887ddd18a6134482bc1a576d66a5adb5e722aefa", - "sdkVersion": "5.3.1" + "originGitCommit": "d139ec85d28b73d9598251516d91b3f51152cb46", + "sdkVersion": "5.4.0" } \ No newline at end of file diff --git a/README.md b/README.md index d1d88a22..b5e22b0c 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Add the dependency in your `build.gradle` file: ```groovy dependencies { - implementation 'com.anduril:lattice-sdk' + implementation 'com.anduril:lattice-sdk:5.4.0' } ``` @@ -53,7 +53,7 @@ Add the dependency in your `pom.xml` file: com.anduril lattice-sdk - 5.3.1 + 5.4.0 ``` @@ -69,22 +69,13 @@ Instantiate and use the client with the following: package com.example.usage; import com.anduril.Lattice; -import com.anduril.resources.entities.requests.EntityEventRequest; - -public class Example { - public static void main(String[] args) { - Lattice client = Lattice.withCredentials("", "") - .build() - ; - - client.entities().longPollEntityEvents( - EntityEventRequest - .builder() - .sessionToken("sessionToken") - .build() - ); - } -} + +Lattice client = Lattice + .builder() + .server("YOUR_SERVER") + .build(); + +client.entities().longPollEntityEvents(...); ``` ## Authentication @@ -145,11 +136,11 @@ Lattice client = Lattice When the API returns a non-success status code (4xx or 5xx response), an API exception will be thrown. ```java -import com.anduril.core.AndurilApiApiException; +import com.anduril.core.LatticeApiException; try{ client.entities().longPollEntityEvents(...); -} catch (AndurilApiApiException e){ +} catch (LatticeApiException e){ // Do something with the API exception... } ``` @@ -254,7 +245,7 @@ The `withRawResponse()` method returns a raw client that wraps all responses wit (A normal client's `response` is identical to a raw client's `response.body()`.) ```java -LongPollEntityEventsHttpResponse response = client.entities().withRawResponse().longPollEntityEvents(...); +LatticeHttpResponse response = client.entities().withRawResponse().longPollEntityEvents(...); System.out.println(response.body()); System.out.println(response.headers().get("X-My-Header")); diff --git a/build.gradle b/build.gradle index f4532e62..b0fe1894 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ java { group = 'com.anduril' -version = '5.3.1' +version = '5.4.0' jar { dependsOn(":generatePomFileForMavenPublication") @@ -78,7 +78,7 @@ publishing { maven(MavenPublication) { groupId = 'com.anduril' artifactId = 'lattice-sdk' - version = '5.3.1' + version = '5.4.0' from components.java pom { name = 'Anduril Industries, Inc.' diff --git a/src/main/java/com/anduril/core/ClientOptions.java b/src/main/java/com/anduril/core/ClientOptions.java index 2e1c144c..05c4a825 100644 --- a/src/main/java/com/anduril/core/ClientOptions.java +++ b/src/main/java/com/anduril/core/ClientOptions.java @@ -38,10 +38,10 @@ private ClientOptions( this.headers.putAll(headers); this.headers.putAll(new HashMap() { { - put("User-Agent", "com.anduril:lattice-sdk/5.3.1"); + put("User-Agent", "com.anduril:lattice-sdk/5.4.0"); put("X-Fern-Language", "JAVA"); put("X-Fern-SDK-Name", "com.anduril:lattice-sdk"); - put("X-Fern-SDK-Version", "5.3.1"); + put("X-Fern-SDK-Version", "5.4.0"); } }); this.headerSuppliers = headerSuppliers; diff --git a/src/main/java/com/anduril/core/DoubleSerializer.java b/src/main/java/com/anduril/core/DoubleSerializer.java new file mode 100644 index 00000000..96061728 --- /dev/null +++ b/src/main/java/com/anduril/core/DoubleSerializer.java @@ -0,0 +1,43 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.anduril.core; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import java.io.IOException; + +/** + * Custom serializer that writes integer-valued doubles without a decimal point. + * For example, {@code 24000.0} is serialized as {@code 24000} instead of {@code 24000.0}. + * Non-integer values like {@code 3.14} are serialized normally. + */ +class DoubleSerializer extends JsonSerializer { + private static final SimpleModule MODULE; + + static { + MODULE = new SimpleModule() + .addSerializer(Double.class, new DoubleSerializer()) + .addSerializer(double.class, new DoubleSerializer()); + } + + /** + * Gets a module wrapping this serializer as an adapter for the Jackson ObjectMapper. + * + * @return A {@link SimpleModule} to be plugged onto Jackson ObjectMapper. + */ + public static SimpleModule getModule() { + return MODULE; + } + + @Override + public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value != null && value == Math.floor(value) && !Double.isInfinite(value) && !Double.isNaN(value)) { + gen.writeNumber(value.longValue()); + } else { + gen.writeNumber(value); + } + } +} diff --git a/src/main/java/com/anduril/core/ObjectMappers.java b/src/main/java/com/anduril/core/ObjectMappers.java index 4955159d..0b8f6f29 100644 --- a/src/main/java/com/anduril/core/ObjectMappers.java +++ b/src/main/java/com/anduril/core/ObjectMappers.java @@ -18,6 +18,7 @@ public final class ObjectMappers { .addModule(new Jdk8Module()) .addModule(new JavaTimeModule()) .addModule(DateTimeDeserializer.getModule()) + .addModule(DoubleSerializer.getModule()) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .build(); diff --git a/src/main/java/com/anduril/core/RetryInterceptor.java b/src/main/java/com/anduril/core/RetryInterceptor.java index 27bccd1f..3aa2d7ac 100644 --- a/src/main/java/com/anduril/core/RetryInterceptor.java +++ b/src/main/java/com/anduril/core/RetryInterceptor.java @@ -19,11 +19,11 @@ public class RetryInterceptor implements Interceptor { private static final Duration MAX_RETRY_DELAY = Duration.ofMillis(60000); private static final double JITTER_FACTOR = 0.2; - private final ExponentialBackoff backoff; + private final int maxRetries; private final Random random = new Random(); public RetryInterceptor(int maxRetries) { - this.backoff = new ExponentialBackoff(maxRetries); + this.maxRetries = maxRetries; } @Override @@ -38,7 +38,8 @@ public Response intercept(Chain chain) throws IOException { } private Response retryChain(Response response, Chain chain) throws IOException { - Optional nextBackoff = this.backoff.nextBackoff(response); + ExponentialBackoff backoff = new ExponentialBackoff(this.maxRetries); + Optional nextBackoff = backoff.nextBackoff(response); while (nextBackoff.isPresent()) { try { Thread.sleep(nextBackoff.get().toMillis()); @@ -48,7 +49,7 @@ private Response retryChain(Response response, Chain chain) throws IOException { response.close(); response = chain.proceed(chain.request()); if (shouldRetry(response.code())) { - nextBackoff = this.backoff.nextBackoff(response); + nextBackoff = backoff.nextBackoff(response); } else { return response; } diff --git a/src/main/java/com/anduril/resources/entities/types/StreamEntitiesResponse.java b/src/main/java/com/anduril/resources/entities/types/StreamEntitiesResponse.java index 01f26357..19aa86a5 100644 --- a/src/main/java/com/anduril/resources/entities/types/StreamEntitiesResponse.java +++ b/src/main/java/com/anduril/resources/entities/types/StreamEntitiesResponse.java @@ -109,6 +109,7 @@ private interface Value { @JsonIgnoreProperties("event") private static final class HeartbeatValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private EntityStreamHeartbeat value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) @@ -148,6 +149,7 @@ public String toString() { @JsonIgnoreProperties("event") private static final class EntityValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private EntityStreamEvent value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) diff --git a/src/main/java/com/anduril/resources/objects/requests/ListObjectsRequest.java b/src/main/java/com/anduril/resources/objects/requests/ListObjectsRequest.java index 8c42a3a6..22325b8e 100644 --- a/src/main/java/com/anduril/resources/objects/requests/ListObjectsRequest.java +++ b/src/main/java/com/anduril/resources/objects/requests/ListObjectsRequest.java @@ -6,9 +6,9 @@ import com.anduril.core.ObjectMappers; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -51,7 +51,7 @@ private ListObjectsRequest( /** * @return Filters the objects based on the specified prefix path. If no path is specified, all objects are returned. */ - @JsonProperty("prefix") + @JsonIgnore public Optional getPrefix() { return prefix; } @@ -59,7 +59,7 @@ public Optional getPrefix() { /** * @return Sets the age for the oldest objects to query across the environment. */ - @JsonProperty("sinceTimestamp") + @JsonIgnore public Optional getSinceTimestamp() { return sinceTimestamp; } @@ -67,7 +67,7 @@ public Optional getSinceTimestamp() { /** * @return Base64 and URL-encoded cursor returned by the service to continue paging. */ - @JsonProperty("pageToken") + @JsonIgnore public Optional getPageToken() { return pageToken; } @@ -75,7 +75,7 @@ public Optional getPageToken() { /** * @return Lists objects across all environment nodes in a Lattice Mesh. */ - @JsonProperty("allObjectsInMesh") + @JsonIgnore public Optional getAllObjectsInMesh() { return allObjectsInMesh; } @@ -83,7 +83,7 @@ public Optional getAllObjectsInMesh() { /** * @return Sets the maximum number of items that should be returned on a single page. */ - @JsonProperty("maxPageSize") + @JsonIgnore public Optional getMaxPageSize() { return maxPageSize; } diff --git a/src/main/java/com/anduril/resources/tasks/types/StreamAsAgentResponse.java b/src/main/java/com/anduril/resources/tasks/types/StreamAsAgentResponse.java index 2c581bde..0aeb69b6 100644 --- a/src/main/java/com/anduril/resources/tasks/types/StreamAsAgentResponse.java +++ b/src/main/java/com/anduril/resources/tasks/types/StreamAsAgentResponse.java @@ -109,6 +109,7 @@ private interface Value { @JsonIgnoreProperties("event") private static final class HeartbeatValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private StreamHeartbeat value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) @@ -148,6 +149,7 @@ public String toString() { @JsonIgnoreProperties("event") private static final class AgentRequestValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private AgentStreamEvent value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) diff --git a/src/main/java/com/anduril/resources/tasks/types/StreamTasksResponse.java b/src/main/java/com/anduril/resources/tasks/types/StreamTasksResponse.java index 952002c3..7e872a83 100644 --- a/src/main/java/com/anduril/resources/tasks/types/StreamTasksResponse.java +++ b/src/main/java/com/anduril/resources/tasks/types/StreamTasksResponse.java @@ -109,6 +109,7 @@ private interface Value { @JsonIgnoreProperties("event") private static final class HeartbeatValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private StreamHeartbeat value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) @@ -148,6 +149,7 @@ public String toString() { @JsonIgnoreProperties("event") private static final class TaskEventValue implements Value { @JsonUnwrapped + @JsonIgnoreProperties(value = "event", allowSetters = true) private TaskStreamEvent value; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) From 2b24ad1b92b897625cc5a043cb6a4f0fa337ffc4 Mon Sep 17 00:00:00 2001 From: asomera Date: Wed, 1 Apr 2026 15:09:10 -0700 Subject: [PATCH 2/2] chore: fix README.md --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b5e22b0c..71c60343 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,22 @@ Instantiate and use the client with the following: package com.example.usage; import com.anduril.Lattice; - -Lattice client = Lattice - .builder() - .server("YOUR_SERVER") - .build(); - -client.entities().longPollEntityEvents(...); +import com.anduril.resources.entities.requests.EntityEventRequest; + +public class Example { + public static void main(String[] args) { + Lattice client = Lattice.withCredentials("", "") + .build() + ; + + client.entities().longPollEntityEvents( + EntityEventRequest + .builder() + .sessionToken("sessionToken") + .build() + ); + } +} ``` ## Authentication