From 89b106cb03288050e05ee12fbb5ec28a94269375 Mon Sep 17 00:00:00 2001 From: Sasha Bogolii <87649992+sbogolii-sift@users.noreply.github.com> Date: Tue, 28 May 2024 12:04:40 +0300 Subject: [PATCH] API-7698: Fix possible issue with connection becoming stalled after interrupt during call.execute (#107) * API-7698: Added workaround to fix SocketTimeException in okHttp * API-7698: Fixed error handling * API-7698: Added overloaded constructor with both baseUrl and okHttpClient * API-7698: Made enqueue requests optional * API-7698: Don't interrupt * API-7698: Added test --- CHANGES.MD | 4 ++ README.md | 4 +- build.gradle | 2 +- .../com/siftscience/ApplyDecisionRequest.java | 8 ++- src/main/java/com/siftscience/Constants.java | 2 +- .../siftscience/CreateMerchantRequest.java | 11 ++-- .../siftscience/DecisionStatusRequest.java | 12 ++-- .../java/com/siftscience/EventRequest.java | 4 +- .../com/siftscience/GetDecisionsRequest.java | 9 ++- .../com/siftscience/GetMerchantRequest.java | 13 +++-- .../com/siftscience/GetMerchantsRequest.java | 13 +++-- src/main/java/com/siftscience/HttpClient.java | 31 ++++++++++ .../java/com/siftscience/LabelRequest.java | 9 ++- .../java/com/siftscience/ScoreRequest.java | 5 +- src/main/java/com/siftscience/SiftClient.java | 45 ++++++++------ .../com/siftscience/SiftMerchantRequest.java | 14 +++-- .../java/com/siftscience/SiftRequest.java | 24 +++++--- .../java/com/siftscience/UnlabelRequest.java | 4 +- .../siftscience/UpdateMerchantRequest.java | 4 +- .../com/siftscience/UserScoreRequest.java | 9 ++- .../siftscience/VerificationCheckRequest.java | 15 +++-- .../VerificationResendRequest.java | 15 +++-- .../siftscience/VerificationSendRequest.java | 15 +++-- .../siftscience/WorkflowStatusRequest.java | 14 +++-- .../com/siftscience/utils/OkHttpUtils.java | 58 +++++++++++++++++++ .../java/com/siftscience/SiftRequestTest.java | 29 +++++++++- 26 files changed, 259 insertions(+), 114 deletions(-) create mode 100644 src/main/java/com/siftscience/HttpClient.java create mode 100644 src/main/java/com/siftscience/utils/OkHttpUtils.java diff --git a/CHANGES.MD b/CHANGES.MD index a630f59..807284a 100644 --- a/CHANGES.MD +++ b/CHANGES.MD @@ -1,3 +1,7 @@ +3.14.2 (2024-05-20) +================= +- Fixed bug with okHttp causing SocketTimeoutException + 3.14.1 (2024-05-16) ================= - Added support for warnings in Events API diff --git a/README.md b/README.md index 410e822..850d5bb 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Java 1.7 or later. com.siftscience sift-java - 3.14.1 + 3.14.2 ``` ### Gradle ``` dependencies { - compile 'com.siftscience:sift-java:3.14.1' + compile 'com.siftscience:sift-java:3.14.2' } ``` ### Other diff --git a/build.gradle b/build.gradle index 3848753..a8f1db6 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'signing' apply plugin: 'java-library-distribution' group = 'com.siftscience' -version = '3.14.1' +version = '3.14.2' repositories { mavenCentral() diff --git a/src/main/java/com/siftscience/ApplyDecisionRequest.java b/src/main/java/com/siftscience/ApplyDecisionRequest.java index df3c647..b6cfa2d 100644 --- a/src/main/java/com/siftscience/ApplyDecisionRequest.java +++ b/src/main/java/com/siftscience/ApplyDecisionRequest.java @@ -3,12 +3,14 @@ import java.io.IOException; import com.siftscience.model.ApplyDecisionFieldSet; -import okhttp3.*; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Request; public class ApplyDecisionRequest extends SiftRequest{ - ApplyDecisionRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, ApplyDecisionFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + ApplyDecisionRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, ApplyDecisionFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/Constants.java b/src/main/java/com/siftscience/Constants.java index d955fe0..6e37b7e 100644 --- a/src/main/java/com/siftscience/Constants.java +++ b/src/main/java/com/siftscience/Constants.java @@ -3,6 +3,6 @@ public class Constants { public static final String API_VERSION = "v205"; - public static final String LIB_VERSION = "3.14.1"; + public static final String LIB_VERSION = "3.14.2"; public static final String USER_AGENT_HEADER = String.format("SiftScience/%s sift-java/%s", API_VERSION, LIB_VERSION); } diff --git a/src/main/java/com/siftscience/CreateMerchantRequest.java b/src/main/java/com/siftscience/CreateMerchantRequest.java index 05e8cfc..78525c0 100644 --- a/src/main/java/com/siftscience/CreateMerchantRequest.java +++ b/src/main/java/com/siftscience/CreateMerchantRequest.java @@ -1,18 +1,17 @@ package com.siftscience; +import java.io.IOException; + +import okhttp3.Credentials; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import okhttp3.Credentials; - -import java.io.IOException; public class CreateMerchantRequest extends SiftMerchantRequest { - CreateMerchantRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + CreateMerchantRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/DecisionStatusRequest.java b/src/main/java/com/siftscience/DecisionStatusRequest.java index 130e111..daab859 100644 --- a/src/main/java/com/siftscience/DecisionStatusRequest.java +++ b/src/main/java/com/siftscience/DecisionStatusRequest.java @@ -1,16 +1,18 @@ package com.siftscience; -import com.siftscience.model.DecisionStatusFieldSet; -import okhttp3.*; - import java.io.IOException; import static com.siftscience.model.DecisionStatusFieldSet.ENTITY_CONTENT; import static com.siftscience.model.DecisionStatusFieldSet.ENTITY_SESSIONS; +import com.siftscience.model.DecisionStatusFieldSet; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; public class DecisionStatusRequest extends SiftRequest { - DecisionStatusRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, DecisionStatusFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + DecisionStatusRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, DecisionStatusFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/EventRequest.java b/src/main/java/com/siftscience/EventRequest.java index a18ac49..e94a746 100644 --- a/src/main/java/com/siftscience/EventRequest.java +++ b/src/main/java/com/siftscience/EventRequest.java @@ -22,8 +22,8 @@ public class EventRequest extends SiftRequest { private boolean returnScorePercentiles = false; private boolean returnWarnings = false; - EventRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + EventRequest(HttpUrl baseUrl, String accountId, HttpClient client, FieldSet fields) { + super(baseUrl, accountId, client, fields); abuseTypes = null; } diff --git a/src/main/java/com/siftscience/GetDecisionsRequest.java b/src/main/java/com/siftscience/GetDecisionsRequest.java index 2fa9436..7b83a54 100644 --- a/src/main/java/com/siftscience/GetDecisionsRequest.java +++ b/src/main/java/com/siftscience/GetDecisionsRequest.java @@ -1,19 +1,18 @@ package com.siftscience; -import com.siftscience.model.GetDecisionFieldSet; - import java.io.IOException; + +import com.siftscience.model.GetDecisionFieldSet; import okhttp3.Credentials; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class GetDecisionsRequest extends SiftRequest { - GetDecisionsRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + GetDecisionsRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } public enum Query { diff --git a/src/main/java/com/siftscience/GetMerchantRequest.java b/src/main/java/com/siftscience/GetMerchantRequest.java index c5cd708..e7d36b0 100644 --- a/src/main/java/com/siftscience/GetMerchantRequest.java +++ b/src/main/java/com/siftscience/GetMerchantRequest.java @@ -1,15 +1,18 @@ package com.siftscience; -import com.siftscience.model.GetMerchantFieldSet; -import okhttp3.*; - import java.io.IOException; +import com.siftscience.model.GetMerchantFieldSet; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + public class GetMerchantRequest extends SiftMerchantRequest { - GetMerchantRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + GetMerchantRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/GetMerchantsRequest.java b/src/main/java/com/siftscience/GetMerchantsRequest.java index ac4ec76..1361f48 100644 --- a/src/main/java/com/siftscience/GetMerchantsRequest.java +++ b/src/main/java/com/siftscience/GetMerchantsRequest.java @@ -1,15 +1,18 @@ package com.siftscience; -import com.siftscience.model.GetMerchantsFieldSet; -import okhttp3.*; - import java.io.IOException; +import com.siftscience.model.GetMerchantsFieldSet; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + public class GetMerchantsRequest extends SiftMerchantRequest { - GetMerchantsRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + GetMerchantsRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } private static String DEFAULT_BATCH_SIZE = "1000"; diff --git a/src/main/java/com/siftscience/HttpClient.java b/src/main/java/com/siftscience/HttpClient.java new file mode 100644 index 0000000..3bcdd9a --- /dev/null +++ b/src/main/java/com/siftscience/HttpClient.java @@ -0,0 +1,31 @@ +package com.siftscience; + +import java.io.IOException; + +import com.siftscience.utils.OkHttpUtils; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class HttpClient { + + private final OkHttpClient okClient; + private boolean enqueueRequests; + + public HttpClient(OkHttpClient okHttpClient) { + this.okClient = okHttpClient; + } + + public OkHttpClient getOkClient() { + return okClient; + } + + public Response execute(Request request) throws IOException { + return enqueueRequests ? OkHttpUtils.execute(request, okClient) : + okClient.newCall(request).execute(); + } + + public void enqueueRequests() { + this.enqueueRequests = true; + } +} diff --git a/src/main/java/com/siftscience/LabelRequest.java b/src/main/java/com/siftscience/LabelRequest.java index bc44e56..6a0a439 100644 --- a/src/main/java/com/siftscience/LabelRequest.java +++ b/src/main/java/com/siftscience/LabelRequest.java @@ -1,19 +1,18 @@ package com.siftscience; +import java.io.IOException; + import com.siftscience.model.LabelFieldSet; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import okhttp3.Response; -import java.io.IOException; - /** * LabelRequest is the request type for the Sift Labels API. * https://siftscience.com/developers/docs/curl/labels-api */ public class LabelRequest extends SiftRequest { - LabelRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, LabelFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + LabelRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, LabelFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/ScoreRequest.java b/src/main/java/com/siftscience/ScoreRequest.java index 89735c2..b499f7b 100644 --- a/src/main/java/com/siftscience/ScoreRequest.java +++ b/src/main/java/com/siftscience/ScoreRequest.java @@ -4,7 +4,6 @@ import com.siftscience.model.ScoreFieldSet; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; @@ -13,8 +12,8 @@ * https://siftscience.com/developers/docs/curl/score-api */ public class ScoreRequest extends SiftRequest { - ScoreRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, ScoreFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + ScoreRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, ScoreFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } /** diff --git a/src/main/java/com/siftscience/SiftClient.java b/src/main/java/com/siftscience/SiftClient.java index f69a236..5b3e471 100644 --- a/src/main/java/com/siftscience/SiftClient.java +++ b/src/main/java/com/siftscience/SiftClient.java @@ -48,7 +48,7 @@ public class SiftClient { private final String accountId; private final String apiKey; - private final OkHttpClient okClient; + private final HttpClient httpClient; private HttpUrl baseUrl = HttpUrl.parse("https://api.sift.com"); public SiftClient(String apiKey, String accountId) { @@ -58,7 +58,7 @@ public SiftClient(String apiKey, String accountId) { public SiftClient(String apiKey, String accountId, OkHttpClient okHttpClient) { this.apiKey = apiKey; this.accountId = accountId; - this.okClient = okHttpClient; + this.httpClient = new HttpClient(okHttpClient); } /** @@ -72,6 +72,11 @@ public SiftClient(String apiKey, String accountId, HttpUrl baseUrl) { this.baseUrl = baseUrl; } + public SiftClient(String apiKey, String accountId, HttpUrl baseUrl, OkHttpClient okHttpClient) { + this(apiKey, accountId, okHttpClient); + this.baseUrl = baseUrl; + } + public String getApiKey() { return apiKey; } @@ -80,84 +85,88 @@ public String getAccountId() { return accountId; } + public void enqueueRequests() { + httpClient.enqueueRequests(); + } + public EventRequest buildRequest(FieldSet fields) { setupApiKey(fields); - return new EventRequest(baseUrl, getAccountId(), okClient, fields); + return new EventRequest(baseUrl, getAccountId(), httpClient, fields); } public ApplyDecisionRequest buildRequest(ApplyDecisionFieldSet fields) { setupApiKey(fields); - return new ApplyDecisionRequest(baseUrl, getAccountId(), okClient, fields); + return new ApplyDecisionRequest(baseUrl, getAccountId(), httpClient, fields); } public GetDecisionsRequest buildRequest(GetDecisionFieldSet fields) { setupApiKey(fields); - return new GetDecisionsRequest(baseUrl, getAccountId(), okClient, fields); + return new GetDecisionsRequest(baseUrl, getAccountId(), httpClient, fields); } public DecisionStatusRequest buildRequest(DecisionStatusFieldSet fields) { setupApiKey(fields); - return new DecisionStatusRequest(baseUrl, getAccountId(), okClient, fields); + return new DecisionStatusRequest(baseUrl, getAccountId(), httpClient, fields); } public LabelRequest buildRequest(LabelFieldSet fields) { setupApiKey(fields); - return new LabelRequest(baseUrl, getAccountId(), okClient, fields); + return new LabelRequest(baseUrl, getAccountId(), httpClient, fields); } public UnlabelRequest buildRequest(UnlabelFieldSet fields) { setupApiKey(fields); - return new UnlabelRequest(baseUrl, getAccountId(), okClient, fields); + return new UnlabelRequest(baseUrl, getAccountId(), httpClient, fields); } public ScoreRequest buildRequest(ScoreFieldSet fields) { setupApiKey(fields); - return new ScoreRequest(baseUrl, getAccountId(), okClient, fields); + return new ScoreRequest(baseUrl, getAccountId(), httpClient, fields); } public UserScoreRequest buildRequest(UserScoreFieldSet fields) { setupApiKey(fields); - return new UserScoreRequest(baseUrl, getAccountId(), okClient, fields); + return new UserScoreRequest(baseUrl, getAccountId(), httpClient, fields); } public WorkflowStatusRequest buildRequest(WorkflowStatusFieldSet fields) { setupApiKey(fields); - return new WorkflowStatusRequest(baseUrl, getAccountId(), okClient, fields); + return new WorkflowStatusRequest(baseUrl, getAccountId(), httpClient, fields); } public GetMerchantsRequest buildRequest(GetMerchantsFieldSet fields) { setupApiKey(fields); - return new GetMerchantsRequest(baseUrl, getAccountId(), okClient, fields); + return new GetMerchantsRequest(baseUrl, getAccountId(), httpClient, fields); } public GetMerchantRequest buildRequest(GetMerchantFieldSet fields) { setupApiKey(fields); - return new GetMerchantRequest(baseUrl, getAccountId(), okClient, fields); + return new GetMerchantRequest(baseUrl, getAccountId(), httpClient, fields); } public CreateMerchantRequest buildRequest(CreateMerchantFieldSet fields) { setupApiKey(fields); - return new CreateMerchantRequest(baseUrl, getAccountId(), okClient, fields); + return new CreateMerchantRequest(baseUrl, getAccountId(), httpClient, fields); } public UpdateMerchantRequest buildRequest(UpdateMerchantFieldSet fields, String merchantId) { setupApiKey(fields); - return new UpdateMerchantRequest(baseUrl, getAccountId(), okClient, fields, merchantId); + return new UpdateMerchantRequest(baseUrl, getAccountId(), httpClient, fields, merchantId); } public VerificationSendRequest buildRequest(VerificationSendFieldSet fields) { setupApiKey(fields); - return new VerificationSendRequest(baseUrl, getAccountId(), okClient, fields); + return new VerificationSendRequest(baseUrl, getAccountId(), httpClient, fields); } public VerificationResendRequest buildRequest(VerificationResendFieldSet fields) { setupApiKey(fields); - return new VerificationResendRequest(baseUrl, getAccountId(), okClient, fields); + return new VerificationResendRequest(baseUrl, getAccountId(), httpClient, fields); } public VerificationCheckRequest buildRequest(VerificationCheckFieldSet fields) { setupApiKey(fields); - return new VerificationCheckRequest(baseUrl, getAccountId(), okClient, fields); + return new VerificationCheckRequest(baseUrl, getAccountId(), httpClient, fields); } private void setupApiKey(FieldSet fields) { diff --git a/src/main/java/com/siftscience/SiftMerchantRequest.java b/src/main/java/com/siftscience/SiftMerchantRequest.java index 5f08055..7183486 100644 --- a/src/main/java/com/siftscience/SiftMerchantRequest.java +++ b/src/main/java/com/siftscience/SiftMerchantRequest.java @@ -1,6 +1,7 @@ package com.siftscience; import com.siftscience.exception.MerchantAPIException; +import com.siftscience.utils.OkHttpUtils; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -16,7 +17,7 @@ public abstract class SiftMerchantRequest { private final String accountId; FieldSet fieldSet; - private OkHttpClient okClient; + private HttpClient httpClient; private HttpUrl baseUrl; protected abstract HttpUrl path(HttpUrl baseUrl); @@ -25,10 +26,10 @@ public HttpUrl url() { return path(baseUrl); } - SiftMerchantRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { + SiftMerchantRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { this.baseUrl = baseUrl; this.accountId = accountId; - this.okClient = okClient; + this.httpClient = httpClient; this.fieldSet = fields; } @@ -45,13 +46,14 @@ protected void modifyRequestBuilder(Request.Builder builder) { public T send() throws IOException { fieldSet.validate(); - Request.Builder okRequestBuilder = new Request.Builder().addHeader("User-Agent", USER_AGENT_HEADER).url(this.url()); + Request.Builder okRequestBuilder = + new Request.Builder().addHeader("User-Agent", USER_AGENT_HEADER).url(this.url()); modifyRequestBuilder(okRequestBuilder); Request request = okRequestBuilder.build(); - T response = buildResponse(okClient.newCall(request).execute(), fieldSet); + T response = buildResponse(httpClient.execute(request), fieldSet); if (!response.isOk()) { - throw new MerchantAPIException(response.getApiErrorMessage()); + throw new MerchantAPIException(response.getApiErrorMessage()); } return response; diff --git a/src/main/java/com/siftscience/SiftRequest.java b/src/main/java/com/siftscience/SiftRequest.java index 1bb4d65..a3cc05e 100644 --- a/src/main/java/com/siftscience/SiftRequest.java +++ b/src/main/java/com/siftscience/SiftRequest.java @@ -1,11 +1,21 @@ package com.siftscience; -import com.siftscience.exception.*; -import okhttp3.*; - import java.io.IOException; import static com.siftscience.Constants.USER_AGENT_HEADER; +import com.siftscience.exception.InvalidApiKeyException; +import com.siftscience.exception.InvalidFieldException; +import com.siftscience.exception.InvalidRequestException; +import com.siftscience.exception.MissingFieldException; +import com.siftscience.exception.RateLimitException; +import com.siftscience.exception.ServerException; +import com.siftscience.exception.SiftException; +import com.siftscience.utils.OkHttpUtils; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; /** * SiftRequest is the base class for all Sift API requests. It implements the `send` method which @@ -14,7 +24,7 @@ public abstract class SiftRequest { private final String accountId; FieldSet fieldSet; - private OkHttpClient okClient; + private HttpClient httpClient; private HttpUrl baseUrl; protected abstract HttpUrl path(HttpUrl baseUrl); @@ -23,10 +33,10 @@ public HttpUrl url() { return path(baseUrl); } - SiftRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { + SiftRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { this.baseUrl = baseUrl; this.accountId = accountId; - this.okClient = okClient; + this.httpClient = httpClient; this.fieldSet = fields; } @@ -46,7 +56,7 @@ public T send() throws IOException { Request.Builder okRequestBuilder = new Request.Builder().addHeader("User-Agent", USER_AGENT_HEADER).url(this.url()); modifyRequestBuilder(okRequestBuilder); Request request = okRequestBuilder.build(); - T response = buildResponse(okClient.newCall(request).execute(), fieldSet); + T response = buildResponse(httpClient.execute(request), fieldSet); // If not successful but no exception happened yet, dig deeper into the response so we // can manually throw an appropriate exception. diff --git a/src/main/java/com/siftscience/UnlabelRequest.java b/src/main/java/com/siftscience/UnlabelRequest.java index bf273ce..2939bc8 100644 --- a/src/main/java/com/siftscience/UnlabelRequest.java +++ b/src/main/java/com/siftscience/UnlabelRequest.java @@ -10,9 +10,9 @@ * https://siftscience.com/developers/docs/curl/labels-api/unlabel-user */ public class UnlabelRequest extends SiftRequest { - UnlabelRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, + UnlabelRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, UnlabelFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + super(baseUrl, accountId, httpClient, fields); } /** diff --git a/src/main/java/com/siftscience/UpdateMerchantRequest.java b/src/main/java/com/siftscience/UpdateMerchantRequest.java index dd1803b..24a7c83 100644 --- a/src/main/java/com/siftscience/UpdateMerchantRequest.java +++ b/src/main/java/com/siftscience/UpdateMerchantRequest.java @@ -16,8 +16,8 @@ public class UpdateMerchantRequest extends SiftMerchantRequest { - UserScoreRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, + UserScoreRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, UserScoreFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + super(baseUrl, accountId, httpClient, fields); } /** diff --git a/src/main/java/com/siftscience/VerificationCheckRequest.java b/src/main/java/com/siftscience/VerificationCheckRequest.java index b2b296d..fa021bb 100644 --- a/src/main/java/com/siftscience/VerificationCheckRequest.java +++ b/src/main/java/com/siftscience/VerificationCheckRequest.java @@ -1,15 +1,14 @@ package com.siftscience; +import java.io.IOException; + import com.siftscience.model.VerificationCheckFieldSet; -import okhttp3.OkHttpClient; -import okhttp3.HttpUrl; -import okhttp3.Response; -import okhttp3.Request; import okhttp3.Credentials; +import okhttp3.HttpUrl; import okhttp3.MediaType; +import okhttp3.Request; import okhttp3.RequestBody; - -import java.io.IOException; +import okhttp3.Response; /** @@ -18,8 +17,8 @@ */ public class VerificationCheckRequest extends SiftRequest { - VerificationCheckRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, VerificationCheckFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + VerificationCheckRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, VerificationCheckFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/VerificationResendRequest.java b/src/main/java/com/siftscience/VerificationResendRequest.java index 2b0ad81..074c2c6 100644 --- a/src/main/java/com/siftscience/VerificationResendRequest.java +++ b/src/main/java/com/siftscience/VerificationResendRequest.java @@ -1,15 +1,14 @@ package com.siftscience; +import java.io.IOException; + import com.siftscience.model.VerificationResendFieldSet; -import okhttp3.OkHttpClient; -import okhttp3.HttpUrl; -import okhttp3.Response; -import okhttp3.Request; import okhttp3.Credentials; +import okhttp3.HttpUrl; import okhttp3.MediaType; +import okhttp3.Request; import okhttp3.RequestBody; - -import java.io.IOException; +import okhttp3.Response; /** * The resend call generates a new OTP and sends it to the original recipient with the same settings. @@ -17,8 +16,8 @@ * */ public class VerificationResendRequest extends SiftRequest { - VerificationResendRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, VerificationResendFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + VerificationResendRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, VerificationResendFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/VerificationSendRequest.java b/src/main/java/com/siftscience/VerificationSendRequest.java index 89bc063..ec81afc 100644 --- a/src/main/java/com/siftscience/VerificationSendRequest.java +++ b/src/main/java/com/siftscience/VerificationSendRequest.java @@ -1,15 +1,14 @@ package com.siftscience; +import java.io.IOException; + import com.siftscience.model.VerificationSendFieldSet; -import okhttp3.OkHttpClient; -import okhttp3.HttpUrl; -import okhttp3.Response; -import okhttp3.Request; import okhttp3.Credentials; +import okhttp3.HttpUrl; import okhttp3.MediaType; +import okhttp3.Request; import okhttp3.RequestBody; - -import java.io.IOException; +import okhttp3.Response; /** *The send call triggers the generation of an OTP code that is stored by Sift @@ -18,8 +17,8 @@ * */ public class VerificationSendRequest extends SiftRequest { - VerificationSendRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, VerificationSendFieldSet fields) { - super(baseUrl, accountId, okClient, fields); + VerificationSendRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, VerificationSendFieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/WorkflowStatusRequest.java b/src/main/java/com/siftscience/WorkflowStatusRequest.java index 2b921e0..a747078 100644 --- a/src/main/java/com/siftscience/WorkflowStatusRequest.java +++ b/src/main/java/com/siftscience/WorkflowStatusRequest.java @@ -1,14 +1,16 @@ package com.siftscience; -import com.siftscience.model.WorkflowStatus; -import com.siftscience.model.WorkflowStatusFieldSet; -import okhttp3.*; - import java.io.IOException; +import com.siftscience.model.WorkflowStatusFieldSet; +import okhttp3.Credentials; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + public class WorkflowStatusRequest extends SiftRequest { - WorkflowStatusRequest(HttpUrl baseUrl, String accountId, OkHttpClient okClient, FieldSet fields) { - super(baseUrl, accountId, okClient, fields); + WorkflowStatusRequest(HttpUrl baseUrl, String accountId, HttpClient httpClient, FieldSet fields) { + super(baseUrl, accountId, httpClient, fields); } @Override diff --git a/src/main/java/com/siftscience/utils/OkHttpUtils.java b/src/main/java/com/siftscience/utils/OkHttpUtils.java new file mode 100644 index 0000000..7d9fd84 --- /dev/null +++ b/src/main/java/com/siftscience/utils/OkHttpUtils.java @@ -0,0 +1,58 @@ +package com.siftscience.utils; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.jetbrains.annotations.NotNull; + +public class OkHttpUtils { + private OkHttpUtils() { + + } + + /** + * There is a bug on okHttp library, + * which causes java.net.SocketTimeoutException from HTTP/2 connection to leave dead okhttp + * clients in pool. + * This utility method is used as a + * + * workaround + * to enqueue and sync wait for response + * + * @param request - request to send + * @param okClient - client library + * @return - response + */ + public static Response execute(Request request, OkHttpClient okClient) throws IOException { + CompletableFuture result = new CompletableFuture<>(); + okClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + result.completeExceptionally(e); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response httpResponse) { + result.complete(httpResponse); + } + }); + try { + return result.get(); + } catch (InterruptedException e) { + // Intentionally don't interrupt, as it causes okHHtp fail as described + // in the link in javadoc + // Thread.currentThread().interrupt(); + result.cancel(true); + throw new InterruptedIOException("Interrupted while waiting for reply from Sift"); + } catch (ExecutionException e) { + throw new IOException(e); + } + } +} diff --git a/src/test/java/com/siftscience/SiftRequestTest.java b/src/test/java/com/siftscience/SiftRequestTest.java index 91ad1a9..f6ef2cb 100644 --- a/src/test/java/com/siftscience/SiftRequestTest.java +++ b/src/test/java/com/siftscience/SiftRequestTest.java @@ -37,7 +37,34 @@ public void testUserAgentHeader() throws Exception { // Verify the request. RecordedRequest recordedRequest = server.takeRequest(); - Assert.assertEquals("SiftScience/v205 sift-java/3.14.1", recordedRequest.getHeader("User-Agent")); + Assert.assertEquals("SiftScience/v205 sift-java/3.14.2", recordedRequest.getHeader("User-Agent")); } + @Test + public void testEnqueueRequests() throws Exception { + MockWebServer server = new MockWebServer(); + MockResponse response = new MockResponse(); + response.setResponseCode(HTTP_OK); + + server.enqueue(response); + server.start(); + + // Create a new client and link it to the mock server. + SiftClient client = new SiftClient("YOUR_API_KEY", "YOUR_ACCOUNT_ID", + new OkHttpClient.Builder() + .addInterceptor(OkHttpUtils.urlRewritingInterceptor(server)) + .build()); + client.enqueueRequests(); + + // Build and execute the request against the mock server. + ApplyDecisionRequest request = client.buildRequest( + new ApplyDecisionFieldSet() + .setUserId("a_user_id") + .setTime(System.currentTimeMillis())); + + ApplyDecisionResponse receivedResponse = request.send(); + + // verify + Assert.assertNotNull(receivedResponse); + } }