diff --git a/README.md b/README.md
index ab43264..28187fb 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ The Xenon View Java SDK is the Java SDK to interact with [XenonView](https://xen
## What"s New
+* v0.1.8 - On socket timeout, close all cached connections and start new see #185024471.
* v0.1.7 - Add options for term/price for all subscription related calls.
* v0.1.6 - Add initial subscriptions options for term/price.
* v0.1.5 - Fix typo
diff --git a/lib/build.gradle b/lib/build.gradle
index 9bbc047..b2539ab 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -29,7 +29,7 @@ repositories {
mavenCentral()
}
-project.version = "0.1.7"
+project.version = "0.1.8"
project.description = 'The Xenon View Java SDK is the Java SDK to interact with https://xenonview.com.'
project.group = "io.github.xenonview-com"
project.archivesBaseName = 'xenon-view-sdk'
diff --git a/lib/src/main/java/xenon/view/sdk/api/fetch/JsonFetcher.java b/lib/src/main/java/xenon/view/sdk/api/fetch/JsonFetcher.java
index dede3f7..4e420c7 100644
--- a/lib/src/main/java/xenon/view/sdk/api/fetch/JsonFetcher.java
+++ b/lib/src/main/java/xenon/view/sdk/api/fetch/JsonFetcher.java
@@ -24,16 +24,25 @@
public class JsonFetcher implements Fetchable {
private OkHttpClient client;
private OkHttpClient.Builder builder = new OkHttpClient.Builder();
+ public interface NewHttpClientPointer {
+ OkHttpClient newClient();
+ }
+ private static OkHttpClient newClient(){
+ return new OkHttpClient();
+ }
+ private NewHttpClientPointer httpClientMaker = JsonFetcher::newClient;
+
public JsonFetcher(){
- client = new OkHttpClient();
+ client = JsonFetcher.newClient();
}
- public JsonFetcher(OkHttpClient _client){
- client = _client;
+ public JsonFetcher(NewHttpClientPointer _clientMaker){
+ httpClientMaker = _clientMaker;
+ client = httpClientMaker.newClient();
}
- public JsonFetcher(OkHttpClient.Builder _builder, OkHttpClient _client){
- this(_client);
+ public JsonFetcher(OkHttpClient.Builder _builder, NewHttpClientPointer _clientMaker){
+ this(_clientMaker);
builder = _builder;
}
@@ -79,6 +88,9 @@ public CompletableFuture fetch(JSONObject data) throws JSONException{
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
//HTTP request exception
+ client.dispatcher().executorService().shutdown();
+ client.connectionPool().evictAll();
+ client = httpClientMaker.newClient();
completableFuture.completeExceptionally(e);
}
diff --git a/lib/src/test/java/xenon/view/sdk/api/fetch/JsonFetcherTest.java b/lib/src/test/java/xenon/view/sdk/api/fetch/JsonFetcherTest.java
index 4275da1..af8d865 100644
--- a/lib/src/test/java/xenon/view/sdk/api/fetch/JsonFetcherTest.java
+++ b/lib/src/test/java/xenon/view/sdk/api/fetch/JsonFetcherTest.java
@@ -27,6 +27,7 @@
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.*;
@@ -58,7 +59,7 @@ public class JsonFetcherTest {
AtomicReference> completableFuture = new AtomicReference<>();
BeforeEach(() -> {
data.get().put("method", "GET");
- unit.set(new JsonFetcher(client));
+ unit.set(new JsonFetcher(()->{return client;}));
when(client.newCall(any())).thenAnswer(invocation -> {
request.set((Request) invocation.getArguments()[0]);
return enqueuer;
@@ -112,9 +113,15 @@ public class JsonFetcherTest {
});
});
Describe("when the request is not successful", () -> {
+ Dispatcher theDispatcher = mock(Dispatcher.class);
+ ExecutorService theService = mock(ExecutorService.class);
+ ConnectionPool thePool = mock(ConnectionPool.class);
BeforeEach(() -> {
Call theCall = mock(Call.class);
when(theCall.request()).thenReturn(request.get());
+ when(client.dispatcher()).thenReturn(theDispatcher);
+ when(theDispatcher.executorService()).thenReturn(theService);
+ when(client.connectionPool()).thenReturn(thePool);
callback.get().onFailure(theCall, new IOException("{\"response\":\"failed\"}"));
});
@@ -124,6 +131,10 @@ public class JsonFetcherTest {
return new Json(err.getMessage());
});
});
+ It("closes connection pool", () -> {
+ verify(theService).shutdown();
+ verify(thePool).evictAll();
+ });
});
Describe("when the request unauthorized", () -> {
final Response response = mock(Response.class);
@@ -158,9 +169,15 @@ public class JsonFetcherTest {
});
});
Describe("when the request errors", () -> {
+ Dispatcher theDispatcher = mock(Dispatcher.class);
+ ExecutorService theService = mock(ExecutorService.class);
+ ConnectionPool thePool = mock(ConnectionPool.class);
BeforeEach(() -> {
Call theCall = mock(Call.class);
when(theCall.request()).thenReturn(request.get());
+ when(client.dispatcher()).thenReturn(theDispatcher);
+ when(theDispatcher.executorService()).thenReturn(theService);
+ when(client.connectionPool()).thenReturn(thePool);
callback.get().onFailure(theCall, new IOException("No Internet Connection"));
});
It("rejects the promise", () -> {
@@ -169,6 +186,10 @@ public class JsonFetcherTest {
return new Json(err.getMessage());
});
});
+ It("closes connection pool", () -> {
+ verify(theService).shutdown();
+ verify(thePool).evictAll();
+ });
});
Describe("when the request generally errors", () -> {
final Response response = mock(Response.class);
@@ -233,7 +254,7 @@ public class JsonFetcherTest {
data.get().put("body", new JSONObject() {{
put("test", "body");
}});
- unit.set(new JsonFetcher(client));
+ unit.set(new JsonFetcher(()->{return client;}));
when(client.newCall(any())).thenAnswer(invocation -> {
request.set((Request) invocation.getArguments()[0]);
return enqueuer;
@@ -269,7 +290,7 @@ public class JsonFetcherTest {
JSONObject headers = new JSONObject();
headers.put("authorization", "Bearer ");
data.get().put("requestHeaders", headers);
- unit.set(new JsonFetcher(client));
+ unit.set(new JsonFetcher(()->{return client;}));
when(client.newCall(any())).thenAnswer(invocation -> {
request.set((Request) invocation.getArguments()[0]);
return enqueuer;
@@ -304,7 +325,7 @@ public class JsonFetcherTest {
headers.put("authorization", "Bearer ");
data.get().put("requestHeaders", headers);
data.get().put("ignore-certificate-errors", true);
- unit.set(new JsonFetcher(builder, client));
+ unit.set(new JsonFetcher(builder, ()->{return client;}));
when(builder.sslSocketFactory(any(), any())).thenReturn(builder);
when(builder.hostnameVerifier(any())).thenReturn(builder);
when(builder.build()).thenReturn(client);