Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .fern/metadata.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"cliVersion": "4.29.0",
"cliVersion": "4.90.0",
"generatorName": "fernapi/fern-java-sdk",
"generatorVersion": "3.44.1",
"generatorVersion": "4.4.1",
"generatorConfig": {
"publish-to": "central"
},
"originGitCommit": "bbd2054c67ad246b017399f96faf58cf6737bf01",
"sdkVersion": "2.0.0"
"originGitCommit": "3707beee5d0e236f2469e89f7b19c3a08efb6f95",
"originGitCommitIsDirty": true,
"invokedBy": "ci",
"requestedVersion": "AUTO",
"ciProvider": "unknown",
"sdkVersion": "2.1.0"
}
1 change: 1 addition & 0 deletions .fernignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
LICENSE

# README.md
changelog.md
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Add the dependency in your `build.gradle` file:

```groovy
dependencies {
implementation 'com.newscatcherapi:newscatcher-sdk'
implementation 'com.newscatcherapi:newscatcher-sdk:2.1.0'
}
```

Expand All @@ -55,7 +55,7 @@ Add the dependency in your `pom.xml` file:
<dependency>
<groupId>com.newscatcherapi</groupId>
<artifactId>newscatcher-sdk</artifactId>
<version>2.0.0</version>
<version>2.1.0</version>
</dependency>
```

Expand Down Expand Up @@ -334,7 +334,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
PostHttpResponse response = client.search().withRawResponse().post(...);
NewscatcherApiHttpResponse response = client.search().withRawResponse().post(...);

System.out.println(response.body());
System.out.println(response.headers().get("X-My-Header"));
Expand All @@ -353,3 +353,4 @@ On the other hand, contributions to the README are always very welcome!

For release notes and changelog, visit our [GitHub releases page](https://github.com/Newscatcher/newscatcher-java/releases).


4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ java {

group = 'com.newscatcherapi'

version = '2.0.0'
version = '2.1.0'

jar {
dependsOn(":generatePomFileForMavenPublication")
Expand Down Expand Up @@ -78,7 +78,7 @@ publishing {
maven(MavenPublication) {
groupId = 'com.newscatcherapi'
artifactId = 'newscatcher-sdk'
version = '2.0.0'
version = '2.1.0'
from components.java
pom {
name = 'newscatcher'
Expand Down
10 changes: 10 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 2.1.0 - 2026-04-23
* ## [2.1.0] - 2025-07-10
### Added
* **`NlpDataEntity.getQwenEmbedding()`** — new `Optional<List<Float>>` field exposing a 1024-dimensional Qwen3-Embedding-0.6B vector for articles indexed from January 1, 2026 onward (requires the `v3_nlp_embeddings` plan).
### Changed
* **`ObjectMappers`** — now registers a custom `DoubleSerializer` that writes integer-valued doubles (e.g. `24000.0`) as plain integers (`24000`) in all serialized output.
### Fixed
* **`GetAggregationCountRequest`**, **`GetAuthorsRequest`**, and **`GetSourcesRequest`** — getter methods are now annotated with `@JsonIgnore` instead of `@JsonProperty`, preventing query-parameter-only fields from being incorrectly serialized into the JSON request body.
* **`RetryInterceptor`** — `ExponentialBackoff` is now instantiated fresh per retry cycle, eliminating shared mutable state across concurrent requests.

20 changes: 10 additions & 10 deletions reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ client.search().get(
.notCountries("UK,FR")
.notAuthorName("John Doe, Jane Doe")
.from(
From.of(OffsetDateTime.parse("2024-07-01T00:00:00Z"))
From.of(OffsetDateTime.parse("1 day ago"))
)
.to(
To.of(OffsetDateTime.parse("2024-01-01T00:00:00Z"))
To.of(OffsetDateTime.parse("1 day ago"))
)
.publishedDatePrecision("full")
.byParseDate(true)
Expand All @@ -68,7 +68,7 @@ client.search().get(
.page(2)
.pageSize(50)
.clusteringEnabled(true)
.clusteringThreshold(0.6f)
.clusteringThreshold(0.7f)
.includeNlpData(true)
.hasNlp(true)
.theme("Finance,Tech")
Expand Down Expand Up @@ -1202,7 +1202,7 @@ client.latestHeadlines().get(
.page(2)
.pageSize(50)
.clusteringEnabled(true)
.clusteringThreshold(0.6f)
.clusteringThreshold(0.7f)
.includeTranslationFields(true)
.includeNlpData(true)
.hasNlp(true)
Expand Down Expand Up @@ -2558,10 +2558,10 @@ client.authors().get(
.countries("US,CA")
.notCountries("UK,FR")
.from(
From.of(OffsetDateTime.parse("2024-07-01T00:00:00Z"))
From.of(OffsetDateTime.parse("1 day ago"))
)
.to(
To.of(OffsetDateTime.parse("2024-01-01T00:00:00Z"))
To.of(OffsetDateTime.parse("1 day ago"))
)
.publishedDatePrecision("full")
.byParseDate(true)
Expand Down Expand Up @@ -3472,10 +3472,10 @@ client.searchByLink().get(
.ids("5f8d0d55b6e45e00179c6e7e")
.links("https://nytimes.com/article1,https://bbc.com/article2")
.from(
From.of(OffsetDateTime.parse("2024-07-01T00:00:00Z"))
From.of(OffsetDateTime.parse("1 day ago"))
)
.to(
To.of(OffsetDateTime.parse("2024-01-01T00:00:00Z"))
To.of(OffsetDateTime.parse("1 day ago"))
)
.page(2)
.pageSize(50)
Expand Down Expand Up @@ -4050,10 +4050,10 @@ client.aggregationCount().get(
.notCountries("UK,FR")
.notAuthorName("John Doe, Jane Doe")
.from(
From.of(OffsetDateTime.parse("2024-07-01T00:00:00Z"))
From.of(OffsetDateTime.parse("1 day ago"))
)
.to(
To.of(OffsetDateTime.parse("2024-01-01T00:00:00Z"))
To.of(OffsetDateTime.parse("1 day ago"))
)
.publishedDatePrecision("full")
.byParseDate(true)
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/newscatcher/api/core/ClientOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ private ClientOptions(
this.headers.putAll(headers);
this.headers.putAll(new HashMap<String, String>() {
{
put("User-Agent", "com.newscatcherapi:newscatcher-sdk/2.0.0");
put("User-Agent", "com.newscatcherapi:newscatcher-sdk/2.1.0");
put("X-Fern-Language", "JAVA");
put("X-Fern-SDK-Name", "com.newscatcher.fern:api-sdk");
put("X-Fern-SDK-Version", "2.0.0");
put("X-Fern-SDK-Version", "2.1.0");
}
});
this.headerSuppliers = headerSuppliers;
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/com/newscatcher/api/core/DoubleSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* This file was auto-generated by Fern from our API Definition.
*/
package com.newscatcher.api.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<Double> {
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);
}
}
}
1 change: 1 addition & 0 deletions src/main/java/com/newscatcher/api/core/ObjectMappers.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/com/newscatcher/api/core/RetryInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -38,7 +38,8 @@ public Response intercept(Chain chain) throws IOException {
}

private Response retryChain(Response response, Chain chain) throws IOException {
Optional<Duration> nextBackoff = this.backoff.nextBackoff(response);
ExponentialBackoff backoff = new ExponentialBackoff(this.maxRetries);
Optional<Duration> nextBackoff = backoff.nextBackoff(response);
while (nextBackoff.isPresent()) {
try {
Thread.sleep(nextBackoff.get().toMillis());
Expand All @@ -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;
}
Expand Down
Loading
Loading