Skip to content

Commit 0034359

Browse files
committed
MLE-24405 Cleaned up RESTServices API
This internal API had several unused methods. In addition, application of the client configurators happens in OkHttpServices now. That removes as much OkHttp stuff as possible from DatabaseClientFactory. This will greatly simplify shifting to the JDK HTTP client some time in the future.
1 parent 9e70443 commit 0034359

File tree

6 files changed

+61
-100
lines changed

6 files changed

+61
-100
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/DatabaseClientFactory.java

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.marklogic.client.impl.*;
88
import com.marklogic.client.io.marker.ContentHandle;
99
import com.marklogic.client.io.marker.ContentHandleFactory;
10-
import okhttp3.OkHttpClient;
1110

1211
import javax.naming.InvalidNameException;
1312
import javax.naming.ldap.LdapName;
@@ -31,7 +30,7 @@
3130
*/
3231
public class DatabaseClientFactory {
3332

34-
static private List<ClientConfigurator<?>> clientConfigurators = Collections.synchronizedList(new ArrayList<>());
33+
static private List<OkHttpClientConfigurator> clientConfigurators = Collections.synchronizedList(new ArrayList<>());
3534

3635
static private HandleFactoryRegistry handleRegistry =
3736
HandleFactoryRegistryImpl.newDefault();
@@ -1329,33 +1328,17 @@ static public DatabaseClient newClient(String host, int port, String database,
13291328
static public DatabaseClient newClient(String host, int port, String basePath, String database,
13301329
SecurityContext securityContext,
13311330
DatabaseClient.ConnectionType connectionType) {
1332-
RESTServices services = new OkHttpServices();
13331331
// As of 6.1.0, the following optimization is made as it's guaranteed that if the user is connecting to a
13341332
// Progress Data Cloud instance, then port 443 will be used. Every path for constructing a DatabaseClient goes through
13351333
// this method, ensuring that this optimization will always be applied, and thus freeing the user from having to
13361334
// worry about what port to configure when using Progress Data Cloud.
13371335
if (securityContext instanceof MarkLogicCloudAuthContext || securityContext instanceof ProgressDataCloudAuthContext) {
13381336
port = 443;
13391337
}
1340-
services.connect(host, port, basePath, database, securityContext);
1341-
1342-
if (clientConfigurators != null) {
1343-
clientConfigurators.forEach(configurator -> {
1344-
if (configurator instanceof OkHttpClientConfigurator) {
1345-
OkHttpClient okHttpClient = (OkHttpClient) services.getClientImplementation();
1346-
Objects.requireNonNull(okHttpClient);
1347-
OkHttpClient.Builder clientBuilder = okHttpClient.newBuilder();
1348-
((OkHttpClientConfigurator) configurator).configure(clientBuilder);
1349-
((OkHttpServices) services).setClientImplementation(clientBuilder.build());
1350-
} else {
1351-
throw new IllegalArgumentException("A ClientConfigurator must implement OkHttpClientConfigurator");
1352-
}
1353-
});
1354-
}
13551338

1356-
DatabaseClientImpl client = new DatabaseClientImpl(
1357-
services, host, port, basePath, database, securityContext, connectionType
1358-
);
1339+
OkHttpServices.ConnectionConfig config = new OkHttpServices.ConnectionConfig(host, port, basePath, database, securityContext, clientConfigurators);
1340+
RESTServices services = new OkHttpServices(config);
1341+
DatabaseClientImpl client = new DatabaseClientImpl(services, host, port, basePath, database, securityContext, connectionType);
13591342
client.setHandleRegistry(getHandleRegistry().copy());
13601343
return client;
13611344
}
@@ -1397,13 +1380,13 @@ static public void registerDefaultHandles() {
13971380
* @param configurator the listener for configuring the communication library
13981381
*/
13991382
static public void addConfigurator(ClientConfigurator<?> configurator) {
1400-
if (!OkHttpClientConfigurator.class.isInstance(configurator)) {
1401-
throw new IllegalArgumentException(
1402-
"Configurator must implement OkHttpClientConfigurator"
1403-
);
1404-
}
1383+
if (!OkHttpClientConfigurator.class.isInstance(configurator)) {
1384+
throw new IllegalArgumentException(
1385+
"Configurator must implement OkHttpClientConfigurator"
1386+
);
1387+
}
14051388

1406-
clientConfigurators.add(configurator);
1389+
clientConfigurators.add((OkHttpClientConfigurator) configurator);
14071390
}
14081391

14091392
/**

marklogic-client-api/src/main/java/com/marklogic/client/extra/okhttpclient/OkHttpClientBuilderFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import com.marklogic.client.impl.okhttp.OkHttpUtil;
88
import okhttp3.OkHttpClient;
99

10+
import java.util.ArrayList;
11+
1012
/**
1113
* Exposes the mechanism for constructing an {@code OkHttpClient.Builder} in the same fashion as when a
1214
* {@code DatabaseClient} is constructed. Primarily intended for reuse in the ml-app-deployer library. If the
@@ -17,6 +19,6 @@
1719
public interface OkHttpClientBuilderFactory {
1820

1921
static OkHttpClient.Builder newOkHttpClientBuilder(String host, DatabaseClientFactory.SecurityContext securityContext) {
20-
return OkHttpUtil.newOkHttpClientBuilder(host, securityContext);
22+
return OkHttpUtil.newOkHttpClientBuilder(host, securityContext, new ArrayList<>());
2123
}
2224
}

marklogic-client-api/src/main/java/com/marklogic/client/impl/DatabaseClientImpl.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ public DatabaseClientImpl(RESTServices services, String host, int port, String b
6060
this.database = database;
6161
this.securityContext = securityContext;
6262
this.connectionType = connectionType;
63-
64-
services.setDatabaseClient(this);
6563
}
6664

6765
public long getServerVersion() {

marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java

Lines changed: 39 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.marklogic.client.document.DocumentManager.Metadata;
1919
import com.marklogic.client.eval.EvalResult;
2020
import com.marklogic.client.eval.EvalResultIterator;
21+
import com.marklogic.client.extra.okhttpclient.OkHttpClientConfigurator;
2122
import com.marklogic.client.impl.okhttp.HttpUrlBuilder;
2223
import com.marklogic.client.impl.okhttp.OkHttpUtil;
2324
import com.marklogic.client.impl.okhttp.PartIterator;
@@ -74,10 +75,10 @@ public class OkHttpServices implements RESTServices {
7475

7576
static final private Logger logger = LoggerFactory.getLogger(OkHttpServices.class);
7677

77-
static final public String OKHTTP_LOGGINGINTERCEPTOR_LEVEL = "com.marklogic.client.okhttp.httplogginginterceptor.level";
78-
static final public String OKHTTP_LOGGINGINTERCEPTOR_OUTPUT = "com.marklogic.client.okhttp.httplogginginterceptor.output";
78+
private static final String OKHTTP_LOGGINGINTERCEPTOR_LEVEL = "com.marklogic.client.okhttp.httplogginginterceptor.level";
79+
private static final String OKHTTP_LOGGINGINTERCEPTOR_OUTPUT = "com.marklogic.client.okhttp.httplogginginterceptor.output";
7980

80-
static final private String DOCUMENT_URI_PREFIX = "/documents?uri=";
81+
private static final String DOCUMENT_URI_PREFIX = "/documents?uri=";
8182

8283
static final private int DELAY_FLOOR = 125;
8384
static final private int DELAY_CEILING = 2000;
@@ -88,10 +89,14 @@ public class OkHttpServices implements RESTServices {
8889
private final static MediaType URLENCODED_MIME_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
8990
private final static String UTF8_ID = StandardCharsets.UTF_8.toString();
9091

91-
private DatabaseClient databaseClient;
9292
private String database = null;
9393
private HttpUrl baseUri;
94-
private OkHttpClient client;
94+
95+
// This should really be final, but given the history of this class and the former "connect()" method that meant
96+
// the client was created in the constructor, this is being kept as non-final so it can be assigned a value of null
97+
// on release.
98+
private OkHttpClient okHttpClient;
99+
95100
private boolean released = false;
96101

97102
private final Random randRetry = new Random();
@@ -114,25 +119,16 @@ static protected class ThreadState {
114119
private final ThreadLocal<ThreadState> threadState =
115120
ThreadLocal.withInitial(() -> new ThreadState(checkFirstRequest));
116121

117-
public OkHttpServices() {
122+
public record ConnectionConfig(String host, int port, String basePath, String database,
123+
SecurityContext securityContext, List<OkHttpClientConfigurator> clientConfigurators) {
124+
}
125+
126+
public OkHttpServices(ConnectionConfig connectionConfig) {
118127
retryStatus.add(STATUS_BAD_GATEWAY);
119128
retryStatus.add(STATUS_SERVICE_UNAVAILABLE);
120129
retryStatus.add(STATUS_GATEWAY_TIMEOUT);
121-
}
122130

123-
@Override
124-
public Set<Integer> getRetryStatus() {
125-
return retryStatus;
126-
}
127-
128-
@Override
129-
public int getMaxDelay() {
130-
return maxDelay;
131-
}
132-
133-
@Override
134-
public void setMaxDelay(int maxDelay) {
135-
this.maxDelay = maxDelay;
131+
this.okHttpClient = connect(connectionConfig);
136132
}
137133

138134
private FailedRequest extractErrorFields(Response response) {
@@ -176,26 +172,27 @@ private FailedRequest extractErrorFields(Response response) {
176172
}
177173
}
178174

179-
@Override
180-
public void connect(String host, int port, String basePath, String database, SecurityContext securityContext) {
181-
if (host == null)
175+
private OkHttpClient connect(ConnectionConfig config) {
176+
if (config.host == null) {
182177
throw new IllegalArgumentException("No host provided");
183-
if (securityContext == null)
178+
}
179+
if (config.securityContext == null) {
184180
throw new IllegalArgumentException("No security context provided");
181+
}
185182

186-
this.checkFirstRequest = securityContext instanceof DigestAuthContext;
187-
this.database = database;
188-
this.baseUri = HttpUrlBuilder.newBaseUrl(host, port, basePath, securityContext.getSSLContext());
183+
this.checkFirstRequest = config.securityContext instanceof DigestAuthContext;
184+
this.database = config.database;
185+
this.baseUri = HttpUrlBuilder.newBaseUrl(config.host, config.port, config.basePath, config.securityContext.getSSLContext());
189186

190-
OkHttpClient.Builder clientBuilder = OkHttpUtil.newOkHttpClientBuilder(host, securityContext);
187+
OkHttpClient.Builder clientBuilder = OkHttpUtil.newOkHttpClientBuilder(config.host, config.securityContext, config.clientConfigurators);
191188

192189
Properties props = System.getProperties();
193190
if (props.containsKey(OKHTTP_LOGGINGINTERCEPTOR_LEVEL)) {
194191
configureOkHttpLogging(clientBuilder, props);
195192
}
196193
this.configureDelayAndRetry(props);
197194

198-
this.client = clientBuilder.build();
195+
return clientBuilder.build();
199196
}
200197

201198
/**
@@ -244,40 +241,21 @@ private void configureDelayAndRetry(Properties props) {
244241
}
245242
}
246243

247-
@Override
248-
public DatabaseClient getDatabaseClient() {
249-
return databaseClient;
250-
}
251-
252-
@Override
253-
public void setDatabaseClient(DatabaseClient client) {
254-
this.databaseClient = client;
255-
}
256-
257-
private OkHttpClient getConnection() {
258-
if (client != null) {
259-
return client;
260-
} else if (released) {
261-
throw new IllegalStateException(
262-
"You cannot use this connected object anymore--connection has already been released");
263-
} else {
264-
throw new MarkLogicInternalException("Cannot proceed--connection is null for unknown reason");
265-
}
266-
}
267-
268244
@Override
269245
public void release() {
270-
if (client == null) return;
246+
if (released || okHttpClient == null) {
247+
return;
248+
}
271249
try {
272250
released = true;
273-
client.dispatcher().executorService().shutdownNow();
251+
okHttpClient.dispatcher().executorService().shutdownNow();
274252
} finally {
275253
try {
276-
if (client.cache() != null) client.cache().close();
254+
if (okHttpClient.cache() != null) okHttpClient.cache().close();
277255
} catch (IOException e) {
278256
throw new MarkLogicIOException(e);
279257
} finally {
280-
client = null;
258+
okHttpClient = null;
281259
logger.debug("Releasing connection");
282260
}
283261
}
@@ -491,8 +469,13 @@ private Response sendRequestOnce(Request.Builder requestBldr) {
491469
}
492470

493471
private Response sendRequestOnce(Request request) {
472+
if (released) {
473+
throw new IllegalStateException(
474+
"You cannot use this connected object anymore--connection has already been released");
475+
}
476+
494477
try {
495-
return getConnection().newCall(request).execute();
478+
return okHttpClient.newCall(request).execute();
496479
} catch (IOException e) {
497480
if (e instanceof SSLException) {
498481
String message = e.getMessage();
@@ -4843,12 +4826,7 @@ public <T> T getContentAs(Class<T> as) {
48434826

48444827
@Override
48454828
public OkHttpClient getClientImplementation() {
4846-
if (client == null) return null;
4847-
return client;
4848-
}
4849-
4850-
public void setClientImplementation(OkHttpClient client) {
4851-
this.client = client;
4829+
return okHttpClient;
48524830
}
48534831

48544832
@Override

marklogic-client-api/src/main/java/com/marklogic/client/impl/RESTServices.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ public interface RESTServices {
7878
String MIMETYPE_APPLICATION_JSON = "application/json";
7979
String MIMETYPE_APPLICATION_XML = "application/xml";
8080
String MIMETYPE_MULTIPART_MIXED = "multipart/mixed";
81-
String MIMETYPE_MULTIPART_FORM = "multipart/form-data";
8281

8382
int STATUS_OK = 200;
8483
int STATUS_CREATED = 201;
@@ -98,13 +97,6 @@ public interface RESTServices {
9897
String MAX_DELAY_PROP = "com.marklogic.client.maximumRetrySeconds";
9998
String MIN_RETRY_PROP = "com.marklogic.client.minimumRetries";
10099

101-
Set<Integer> getRetryStatus();
102-
int getMaxDelay();
103-
void setMaxDelay(int maxDelay);
104-
105-
void connect(String host, int port, String basePath, String database, SecurityContext securityContext);
106-
DatabaseClient getDatabaseClient();
107-
void setDatabaseClient(DatabaseClient client);
108100
void release();
109101

110102
TemporalDescriptor deleteDocument(RequestLogger logger, DocumentDescriptor desc, Transaction transaction,

marklogic-client-api/src/main/java/com/marklogic/client/impl/okhttp/OkHttpUtil.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
package com.marklogic.client.impl.okhttp;
55

66
import com.marklogic.client.DatabaseClientFactory;
7+
import com.marklogic.client.extra.okhttpclient.OkHttpClientConfigurator;
78
import com.marklogic.client.impl.HTTPKerberosAuthInterceptor;
89
import com.marklogic.client.impl.HTTPSamlAuthInterceptor;
10+
import com.marklogic.client.impl.OkHttpServices;
911
import com.marklogic.client.impl.SSLUtil;
1012
import okhttp3.*;
1113

@@ -21,6 +23,7 @@
2123
import java.util.ArrayList;
2224
import java.util.List;
2325
import java.util.Map;
26+
import java.util.Objects;
2427
import java.util.concurrent.TimeUnit;
2528

2629
/**
@@ -35,7 +38,8 @@ public abstract class OkHttpUtil {
3538
final private static ConnectionPool connectionPool = new ConnectionPool();
3639

3740
@SuppressWarnings({"unchecked", "deprecation"})
38-
public static OkHttpClient.Builder newOkHttpClientBuilder(String host, DatabaseClientFactory.SecurityContext securityContext) {
41+
public static OkHttpClient.Builder newOkHttpClientBuilder(String host, DatabaseClientFactory.SecurityContext securityContext,
42+
List<OkHttpClientConfigurator> clientConfigurators) {
3943
OkHttpClient.Builder clientBuilder = OkHttpUtil.newClientBuilder();
4044
AuthenticationConfigurer authenticationConfigurer = null;
4145

@@ -78,6 +82,10 @@ public static OkHttpClient.Builder newOkHttpClientBuilder(String host, DatabaseC
7882
OkHttpUtil.configureSocketFactory(clientBuilder, sslContext, trustManager);
7983
OkHttpUtil.configureHostnameVerifier(clientBuilder, sslVerifier);
8084

85+
if (clientConfigurators != null) {
86+
clientConfigurators.forEach(configurator -> configurator.configure(clientBuilder));
87+
}
88+
8189
return clientBuilder;
8290
}
8391

0 commit comments

Comments
 (0)