Skip to content

Commit 2768102

Browse files
committed
Added fix for multithreading using factory
1 parent cb1e5ae commit 2768102

5 files changed

Lines changed: 52 additions & 286 deletions

File tree

generator/cybersource-java-template/libraries/okhttp-gson/ApiClient.mustache

Lines changed: 24 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ package Invokers;
1414

1515
import java.io.*;
1616
import java.lang.reflect.Type;
17-
import java.net.HttpRetryException;
1817
import java.net.InetSocketAddress;
1918
import java.net.Proxy;
2019
import java.net.URLConnection;
@@ -29,7 +28,6 @@ import java.text.ParseException;
2928
import java.text.SimpleDateFormat;
3029
import java.util.*;
3130
import java.util.Map.Entry;
32-
import java.util.concurrent.TimeUnit;
3331
import java.util.regex.Matcher;
3432
import java.util.regex.Pattern;
3533
import javax.net.ssl.*;
@@ -43,7 +41,6 @@ import org.apache.logging.log4j.Logger;
4341
import okhttp3.Authenticator;
4442
import okhttp3.Call;
4543
import okhttp3.Callback;
46-
import okhttp3.ConnectionPool;
4744
import okhttp3.Credentials;
4845
import okhttp3.FormBody;
4946
import okhttp3.Headers;
@@ -127,12 +124,11 @@ public class ApiClient {
127124
private KeyManager[] keyManagers;
128125
private String acceptHeader = "";
129126

130-
private static OkHttpClient httpClient;
131-
private final OkHttpClient classHttpClient = initializeFinalVariables();
127+
private OkHttpClient httpClient;
128+
private HttpClientFactoryAdditionalSettings additionalSettings = new HttpClientFactoryAdditionalSettings();
132129

133130
private JSON json;
134131
private String versionInfo;
135-
private static ConnectionPool connectionPool = new ConnectionPool(5, 10, TimeUnit.SECONDS);
136132
private HttpLoggingInterceptor loggingInterceptor;
137133
private long computationStartTime;
138134
private static Logger logger = LogManager.getLogger(ApiClient.class);
@@ -158,44 +154,14 @@ public class ApiClient {
158154
public MerchantConfig merchantConfig;
159155
public RequestTransactionMetrics apiRequestMetrics = new RequestTransactionMetrics();
160156

161-
public static OkHttpClient initializeFinalVariables() {
162-
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
163-
logging.setLevel(Level.NONE);
164-
// connectionPool = new ConnectionPool(5, 10, TimeUnit.SECONDS);
165-
166-
try {
167-
return new OkHttpClient.Builder()
168-
.connectTimeout(1, TimeUnit.SECONDS)
169-
.writeTimeout(60, TimeUnit.SECONDS)
170-
.readTimeout(60, TimeUnit.SECONDS)
171-
.connectionPool(ApiClient.connectionPool)
172-
.addInterceptor(logging)
173-
.build();
174-
}
175-
catch (Exception ex)
176-
{
177-
logger.error("Error in creating HTTP Client");
178-
return null;
179-
}
180-
}
181-
182157
/*
183158
* Constructor for ApiClient
184159
*/
185160
public ApiClient() {
186161
versionInfo = getClientID();
187-
188-
try {
189-
httpClient = classHttpClient.newBuilder()
190-
.retryOnConnectionFailure(true)
191-
.addInterceptor(new RetryInterceptor(this.apiRequestMetrics))
192-
.eventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()))
193-
.build();
194-
}
195-
catch (Exception ex)
196-
{
197-
logger.error("Error in creating HTTP Client");
198-
}
162+
additionalSettings.setCustomRetryOnConnectionFailure(true);
163+
additionalSettings.setCustomRetryInterceptor(new RetryInterceptor(this.apiRequestMetrics));
164+
additionalSettings.setCustomNetworkEventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()));
199165
200166
verifyingSsl = true;
201167
@@ -243,32 +209,13 @@ public class ApiClient {
243209
int proxyPort = merchantConfig.getProxyPort();
244210
String proxyHost = merchantConfig.getProxyAddress();
245211
246-
// User Defined Timeout for HTTP Client
247-
int connectionTimeout = Math.max(merchantConfig.getUserDefinedConnectionTimeout(), 1);
248-
int readTimeout = Math.max(merchantConfig.getUserDefinedReadTimeout(), 60);
249-
int writeTimeout = Math.max(merchantConfig.getUserDefinedWriteTimeout(), 60);
250-
int keepAliveDuration = Math.max(merchantConfig.getUserDefinedKeepAliveDuration(), 10);
251-
connectionPool = new ConnectionPool(5, keepAliveDuration, TimeUnit.SECONDS);
252-
253212
Authenticator proxyAuthenticator;
254213
255214
if (useProxy && (proxyHost != null && !proxyHost.isEmpty())) {
256215
if ((username != null && !username.isEmpty()) && (password != null && !password.isEmpty())) {
257216
proxyAuthenticator = new Authenticator() {
258-
// private int proxyCounter = 0;
259-
260217
@Override
261218
public Request authenticate(Route route, Response response) throws IOException {
262-
// if (proxyCounter++ > 0) {
263-
// if (response.code() == 407) {
264-
// logger.error("HttpRetryException : 407 Proxy Authentication Missing or Incorrect");
265-
// throw new HttpRetryException("Proxy Authentication Missing or Incorrect.", 407);
266-
// } else {
267-
// logger.error("IOException : " + response.message());
268-
// throw new IOException(response.message());
269-
// }
270-
// }
271-
272219
String credential = Credentials.basic(username, password);
273220
return response.request().newBuilder().header("Proxy-Authorization", credential).build();
274221
}
@@ -282,51 +229,15 @@ public class ApiClient {
282229
};
283230
}
284231

285-
try {
286-
httpClient = classHttpClient.newBuilder()
287-
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)))
288-
.proxyAuthenticator(proxyAuthenticator)
289-
.connectTimeout(connectionTimeout, TimeUnit.SECONDS)
290-
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
291-
.readTimeout(readTimeout, TimeUnit.SECONDS)
292-
.retryOnConnectionFailure(true)
293-
.addInterceptor(new RetryInterceptor(this.apiRequestMetrics))
294-
.connectionPool(ApiClient.connectionPool)
295-
.eventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()))
296-
.build();
297-
}
298-
catch (Exception ex)
299-
{
300-
logger.error("Error in creating HTTP Client");
301-
}
302-
303-
this.setHttpClient(httpClient);
232+
additionalSettings.setCustomProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
233+
additionalSettings.setCustomProxyAuthenticator(proxyAuthenticator);
304234
}
305-
else
306-
{
307-
// override the custom timeout in HTTPClient
308-
try {
309-
httpClient = classHttpClient.newBuilder()
310-
.connectTimeout(connectionTimeout, TimeUnit.SECONDS)
311-
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
312-
.readTimeout(readTimeout, TimeUnit.SECONDS)
313-
.connectionPool(ApiClient.connectionPool)
314-
.retryOnConnectionFailure(true)
315-
.addInterceptor(new RetryInterceptor(this.apiRequestMetrics))
316-
.eventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()))
317-
.build();
318-
}
319-
catch (Exception ex)
320-
{
321-
logger.error("Error in creating HTTP Client");
322-
}
323235

324-
this.setHttpClient(httpClient);
325-
}
236+
additionalSettings.setCustomRetryOnConnectionFailure(true);
237+
additionalSettings.setCustomRetryInterceptor(new RetryInterceptor(this.apiRequestMetrics));
238+
additionalSettings.setCustomNetworkEventListener(new NetworkEventListener(this.getNewRandomId(), System.nanoTime()));
326239

327240
this.merchantConfig = merchantConfig;
328-
// RetryInterceptor.retryDelay = merchantConfig.getRetryDelay();
329-
// RetryInterceptor.retryEnabled = merchantConfig.isRetryEnabled();
330241
}
331242

332243
/**
@@ -365,17 +276,6 @@ public class ApiClient {
365276
return httpClient;
366277
}
367278

368-
/**
369-
* Set HTTP client
370-
*
371-
* @param httpClient An instance of OkHttpClient
372-
* @return Api Client
373-
*/
374-
public ApiClient setHttpClient(OkHttpClient httpClient) {
375-
ApiClient.httpClient = httpClient;
376-
return this;
377-
}
378-
379279
/**
380280
* Get JSON
381281
*
@@ -780,9 +680,9 @@ public class ApiClient {
780680
if (debugging) {
781681
loggingInterceptor = new HttpLoggingInterceptor();
782682
loggingInterceptor.setLevel(Level.BODY);
783-
httpClient.interceptors().add(loggingInterceptor);
683+
additionalSettings.setCustomLoggingInterceptor(loggingInterceptor);
784684
} else {
785-
httpClient.interceptors().remove(loggingInterceptor);
685+
additionalSettings.setCustomLoggingInterceptor(null);
786686
loggingInterceptor = null;
787687
}
788688
}
@@ -814,27 +714,6 @@ public class ApiClient {
814714
return this;
815715
}
816716

817-
// /**
818-
// * Get connection timeout (in milliseconds).
819-
// *
820-
// * @return Timeout in milliseconds
821-
// */
822-
// public int getConnectTimeout() {
823-
// return httpClient.connectTimeoutMillis();
824-
// }
825-
826-
// /**
827-
// * Sets the connect timeout (in milliseconds). A value of 0 means no timeout,
828-
// * otherwise values must be between 1 and
829-
// *
830-
// * @param connectionTimeout connection timeout in milliseconds
831-
// * @return Api client
832-
// */
833-
// public ApiClient setConnectTimeout(int connectionTimeout) {
834-
// ApiClient.httpClient = ApiClient.httpClient.newBuilder().connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build();
835-
// return this;
836-
// }
837-
838717
/**
839718
* @return the computationStartTime
840719
*/
@@ -1071,8 +950,7 @@ public class ApiClient {
1071950
// Expecting string, return the raw response body.
1072951
return (T) respBody;
1073952
} else {
1074-
logger.error(
1075-
"ApiException : Content type \"" + contentType + "\" is not supported for type: " + returnType);
953+
logger.error("ApiException : Content type \"" + contentType + "\" is not supported for type: " + returnType);
1076954
throw new ApiException("Content type \"" + contentType + "\" is not supported for type: " + returnType,
1077955
response.code(), response.headers().toMultimap(), respBody);
1078956
}
@@ -1366,7 +1244,12 @@ public class ApiClient {
13661244
logger.info("Request Header Parameters:\n{}", new PrettyPrintingMap<String, String>(headerParams));
13671245
Request request = buildRequest(path, method, queryParams, requestbody, headerParams, formParams, authNames,
13681246
progressRequestListener);
1369-
return httpClient.newCall(request);
1247+
try {
1248+
httpClient = HttpClientFactory.getHttpClient(this.merchantConfig, this.additionalSettings);
1249+
} catch (ConfigException e) {
1250+
throw e;
1251+
}
1252+
return httpClient.newCall(request);
13701253
}
13711254

13721255
private String getRequestContentSendOverNetwork(RequestBody requestBody) throws IOException {
@@ -1727,9 +1610,8 @@ public class ApiClient {
17271610
17281611
SSLContext sslContext = SSLContext.getInstance("TLS");
17291612
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new SecureRandom());
1730-
httpClient = httpClient.newBuilder()
1731-
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]).build();
1732-
1613+
additionalSettings.setCustomSSLSocketFactory(sslContext.getSocketFactory());
1614+
additionalSettings.setCustomX509TrustManager((X509TrustManager) trustAllCerts[0]);
17331615
} catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException
17341616
| KeyManagementException | UnrecoverableKeyException ex) {
17351617
@@ -1792,11 +1674,11 @@ public class ApiClient {
17921674
if (keyManagers != null || trustManagers != null) {
17931675
SSLContext sslContext = SSLContext.getInstance("TLS");
17941676
sslContext.init(keyManagers, trustManagers, new SecureRandom());
1795-
httpClient = httpClient.newBuilder().sslSocketFactory(sslContext.getSocketFactory()).build();
1677+
additionalSettings.setCustomSSLSocketFactory(sslContext.getSocketFactory());
17961678
} else {
1797-
httpClient = httpClient.newBuilder().sslSocketFactory(null).build();
1679+
additionalSettings.setCustomSSLSocketFactory(null);
17981680
}
1799-
httpClient = httpClient.newBuilder().hostnameVerifier(hostnameVerifier).build();
1681+
additionalSettings.setCustomHostnameVerifier(hostnameVerifier);
18001682
} catch (GeneralSecurityException e) {
18011683
logger.error("RuntimeException : " + e);
18021684
throw new RuntimeException(e);

generator/cybersource-java-template/libraries/okhttp-gson/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public class {{classname}} {
8080
* @return Call to execute
8181
* @throws ApiException If fail to serialize the request body object
8282
*/
83-
public okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
83+
public okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException, ConfigException {
8484
SdkTracker sdkTracker = new SdkTracker();
8585
Object localVarPostBody = {{#bodyParam}}sdkTracker.insertDeveloperIdTracker({{paramName}}, {{{dataType}}}.class.getSimpleName(), apiClient.merchantConfig.getRunEnvironment(), apiClient.merchantConfig.getDefaultDeveloperId()){{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
8686
{{^bodyParam}}

generator/cybersource_java_sdk_gen.bat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ git checkout ..\src\main\java\Api\OAuthApi.java
2525
git checkout ..\src\main\java\Api\BatchUploadwithMTLSApi.java
2626
git checkout ..\src\main\java\Model\AccessTokenResponse.java
2727
git checkout ..\src\main\java\Model\CreateAccessTokenRequest.java
28+
git checkout ..\src\main\java\Invokers\HttpClientFactory.java
29+
git checkout ..\src\main\java\Invokers\HttpClientFactoryAdditionalSettings.java
2830

2931
git checkout ..\pom.xml
3032
git checkout ..\README.md

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@
304304
<dependency>
305305
<groupId>com.cybersource</groupId>
306306
<artifactId>AuthenticationSdk</artifactId>
307-
<version>0.0.38</version>
307+
<version>0.0.39-SNAPSHOT</version>
308308
</dependency>
309309

310310
<dependency>

0 commit comments

Comments
 (0)