I am migrating an application from using MongoDB Java driver v. 3.6.4 to v. 4.1.1
In 3.6.4 configuration is passed via MongoClientOptions
@Bean
public MongoClientOptions mongoOptions() {
return MongoClientOptions.builder()
.connectTimeout(...)
.serverSelectionTimeout(..)
.socketTimeout(...)
.build();
}
In 4.1.1 MongoClientOptions has been deprecated, and I am utilizing MongoClientSettings class http://mongodb.github.io/mongo-java-driver/4.1/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.Builder.html
@Bean
public MongoClientSettings mongoOptions() {
return MongoClientSettings.builder()
.applyToSocketSettings(builder ->
builder.applySettings(builder()
.connectTimeout(config.getConnectTimeout(), MILLISECONDS).build()))
.applyToClusterSettings(builder ->
builder.serverSelectionTimeout(config.getServerSelectionTimeout(), MILLISECONDS).build())
.build();
}
However I can't find setting to configure connectTimeout (apart from supplying connection string via applyConnectionString method.
-
Have you tried this? mongodb.github.io/mongo-java-driver/4.1/apidocs/…Robert Gardziński– Robert Gardziński2020年12月07日 21:30:35 +00:00Commented Dec 7, 2020 at 21:30
-
Yes, you can see it in my example.fg78nc– fg78nc2020年12月23日 22:53:42 +00:00Commented Dec 23, 2020 at 22:53
2 Answers 2
Yeah, took me a while to figure this out.
The connection timeout and socket timeout are now both in SocketSettings (with the latter renamed as readTimeout).
So it would look something like the following (where you can replace the 1's with your inputs):
@Bean
public MongoClientSettings mongoSetting() {
return MongoClientSettings.builder()
.applyToSocketSettings(builder -> {
builder.connectTimeout(1, MILLISECONDS);
builder.readTimeout(1, MILLISECONDS);
})
.applyToClusterSettings( builder -> builder.serverSelectionTimeout(1, MILLISECONDS))
.applyConnectionString(new ConnectionString("<your-connection-string>"))
.build();
}
I found the need to set the connection string here (in addition to having it set via spring.data.mongodb.uri). Go figure.
Comments
In the example below I have set the mongoClient with SSLContext using JKS Keystore connecting to a Cluster with three nodes:
@Configuration
@Slf4j
@Profile("qa")
public class MongoDBConfigurationQA extends AbstractMongoClientConfiguration {
@Value("${spring.data.mongodb.database}")
String database;
@Value("${spring.data.mongodb.user}")
String user;
@Value("${spring.data.mongodb.keystore}")
String keystore;
@Value("${spring.data.mongodb.truststore}")
String truststore;
@Value("${spring.data.mongodb.keystorePwd}")
String keystorePwd;
@Value("${spring.data.mongodb.truststorePwd}")
String truststorePwd;
@Value("${spring.data.mongodb.hosts}")
String hosts;
@Value("${spring.data.mongodb.port}")
Integer port;
@Override
protected String getDatabaseName() {
return database;
}
@Override
public MongoClient mongoClient() {
List<ServerAddress> listServerAddress = getServerAddresses();
MongoCredential mongoCredential = MongoCredential.createMongoX509Credential(user);
SSLContext sslContext = getSSLContext();
MongoClientSettings settings = MongoClientSettings.builder()
.retryWrites(true)
.retryReads(true)
.applyToConnectionPoolSettings((ConnectionPoolSettings.Builder builder) -> {
builder.maxSize(300) //connections count
.minSize(1)
.maxConnectionLifeTime(0, TimeUnit.MILLISECONDS)
.maxConnectionIdleTime(0, TimeUnit.MILLISECONDS)
.maxWaitTime(180000, TimeUnit.MILLISECONDS);
})
.applyToSocketSettings(builder -> {
builder.readTimeout(30000, TimeUnit.MILLISECONDS)
.connectTimeout(30000, TimeUnit.MILLISECONDS);
})
.applyToSslSettings(builder -> {
builder.enabled(true)
.invalidHostNameAllowed(true)
.context(sslContext);
SslSettings.builder().enabled(true);
})
.applyToClusterSettings(builder -> builder.hosts(listServerAddress))
.credential(mongoCredential)
.build();
return MongoClients.create(settings);
}
private List<ServerAddress> getServerAddresses() {
List<ServerAddress> listServerAddress = new ArrayList<>();
String[] parts = hosts.split(";");
int i;
for (i = 0; i < parts.length; i++){
listServerAddress.add(new ServerAddress(parts[i], port));
}
return listServerAddress;
}
private SSLContext getSSLContext() {
SSLContext sslContext = null;
try (FileInputStream fis = new FileInputStream(truststore)) {
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(fis, truststorePwd.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
FileInputStream fKS = new FileInputStream(keystore);
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(fKS, keystorePwd.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keystorePwd.toCharArray());
sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
log.error(e.toString(), e);
} catch (UnrecoverableKeyException e) {
log.error(e.toString(), e);
}
return sslContext;
}
}