Skip to content

Commit 48ea79c

Browse files
committed
Lazily initializing and reuse a single shared instance
1 parent 1adde8e commit 48ea79c

4 files changed

Lines changed: 70 additions & 14 deletions

File tree

src/main/java/com/adyen/Client.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import com.adyen.enums.Region;
55
import com.adyen.httpclient.AdyenHttpClient;
66
import com.adyen.httpclient.ClientInterface;
7+
import java.io.Closeable;
8+
import java.io.IOException;
79
import javax.net.ssl.SSLContext;
810

9-
public class Client {
11+
public class Client implements Closeable {
1012
private ClientInterface httpClient;
1113
private Config config;
1214
public static final String LIB_NAME = "adyen-java-api-library";
@@ -157,13 +159,23 @@ public String toString() {
157159
}
158160

159161
public ClientInterface getHttpClient() {
160-
return this.httpClient == null ? new AdyenHttpClient() : this.httpClient;
162+
if (this.httpClient == null) {
163+
this.httpClient = new AdyenHttpClient();
164+
}
165+
return this.httpClient;
161166
}
162167

163168
public void setHttpClient(ClientInterface httpClient) {
164169
this.httpClient = httpClient;
165170
}
166171

172+
@Override
173+
public void close() throws IOException {
174+
if (this.httpClient != null) {
175+
this.httpClient.close();
176+
}
177+
}
178+
167179
public Config getConfig() {
168180
return config;
169181
}

src/main/java/com/adyen/httpclient/AdyenHttpClient.java

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public class AdyenHttpClient implements ClientInterface {
6969

7070
private static final String CHARSET = "UTF-8";
7171
private Proxy proxy;
72+
private volatile CloseableHttpClient sharedHttpClient;
73+
private final Object lock = new Object();
7274

7375
public Proxy getProxy() {
7476
return proxy;
@@ -78,6 +80,29 @@ public void setProxy(Proxy proxy) {
7880
this.proxy = proxy;
7981
}
8082

83+
@Override
84+
public void close() throws IOException {
85+
synchronized (lock) {
86+
if (sharedHttpClient != null) {
87+
sharedHttpClient.close();
88+
sharedHttpClient = null;
89+
}
90+
}
91+
}
92+
93+
private CloseableHttpClient getOrCreateHttpClient(Config config) {
94+
CloseableHttpClient client = sharedHttpClient;
95+
if (client != null) {
96+
return client;
97+
}
98+
synchronized (lock) {
99+
if (sharedHttpClient == null) {
100+
sharedHttpClient = createCloseableHttpClient(config);
101+
}
102+
return sharedHttpClient;
103+
}
104+
}
105+
81106
@Override
82107
public String request(String endpoint, String requestBody, Config config)
83108
throws IOException, HTTPClientException {
@@ -125,20 +150,19 @@ public String request(
125150
ApiConstants.HttpMethod httpMethod,
126151
Map<String, String> params)
127152
throws IOException, HTTPClientException {
128-
try (CloseableHttpClient httpclient = createCloseableHttpClient(config)) {
129-
HttpUriRequestBase httpRequest =
130-
createRequest(
131-
endpoint, requestBody, config, isApiKeyRequired, requestOptions, httpMethod, params);
153+
CloseableHttpClient httpclient = getOrCreateHttpClient(config);
154+
HttpUriRequestBase httpRequest =
155+
createRequest(
156+
endpoint, requestBody, config, isApiKeyRequired, requestOptions, httpMethod, params);
132157

133-
// Execute request with a custom response handler
134-
AdyenResponse response = httpclient.execute(httpRequest, new AdyenResponseHandler());
158+
// Execute request with a custom response handler
159+
AdyenResponse response = httpclient.execute(httpRequest, new AdyenResponseHandler());
135160

136-
if (response.getStatus() < 200 || response.getStatus() >= 300) {
137-
throw new HTTPClientException(
138-
response.getStatus(), "HTTP Exception", response.getHeaders(), response.getBody());
139-
}
140-
return response.getBody();
161+
if (response.getStatus() < 200 || response.getStatus() >= 300) {
162+
throw new HTTPClientException(
163+
response.getStatus(), "HTTP Exception", response.getHeaders(), response.getBody());
141164
}
165+
return response.getBody();
142166
}
143167

144168
HttpUriRequestBase createRequest(

src/main/java/com/adyen/httpclient/ClientInterface.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@
2323
import com.adyen.Config;
2424
import com.adyen.constants.ApiConstants;
2525
import com.adyen.model.RequestOptions;
26+
import java.io.Closeable;
2627
import java.io.IOException;
2728
import java.util.Map;
2829

29-
public interface ClientInterface {
30+
public interface ClientInterface extends Closeable {
31+
32+
@Override
33+
default void close() throws IOException {}
3034

3135
String request(String endpoint, String requestBody, Config config)
3236
throws IOException, HTTPClientException;

src/test/java/com/adyen/httpclient/ClientTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,20 @@ public void testRequestWithHttpHeaders() throws Exception {
285285
assertNotNull(wwwAuthenticate);
286286
assertEquals("www-authenticate-header", wwwAuthenticate.getValue());
287287
}
288+
289+
@Test
290+
public void testGetHttpClientReturnsSameInstance() {
291+
Client client = new Client("apiKey", Environment.TEST);
292+
ClientInterface first = client.getHttpClient();
293+
ClientInterface second = client.getHttpClient();
294+
assertSame(first, second);
295+
}
296+
297+
@Test
298+
public void testClientCloseIsIdempotent() throws Exception {
299+
Client client = new Client("apiKey", Environment.TEST);
300+
client.getHttpClient();
301+
client.close();
302+
client.close();
303+
}
288304
}

0 commit comments

Comments
 (0)