I am using spring boot web application which connects to mongo db which is working out of the box. I just use the following properties:
spring.data.mongodb.h
MongoClientOptions is a class which has the required properties.
Programmatically If you have configured your MongoDB programmatically, then below is the code snippet to help you out.
DB mongoDb;
MongoClient mongoClient = new MongoClient(new ServerAddress(url, port),
MongoClientOptions.builder()
.socketTimeout(3000)
.minHeartbeatFrequency(25)
.heartbeatSocketTimeout(3000)
.build());
mongoDb = mongoClient.getDB(dbname);
XML Configuration - Advanced
<beans>
<mongo:mongo host="localhost" port="27017">
<mongo:options connections-per-host="8"
threads-allowed-to-block-for-connection-multiplier="4"
connect-timeout="1000"
max-wait-time="1500}"
auto-connect-retry="true"
socket-keep-alive="true"
socket-timeout="1500"
slave-ok="true"
write-number="1"
write-timeout="0"
write-fsync="true"/>
</mongo:mongo/>
</beans>
Also refer here for complete documentation.
The question is old but for all those who have problems with Mongo DB JAVA driver timeouts : set the maxConnectionIdleTime property.
Example Spring Boot :
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.annotation.PreDestroy;
import java.net.UnknownHostException;
@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
@Autowired
private MongoProperties properties;
@Autowired(required = false)
private MongoClientOptions options;
@Autowired
private Environment environment;
private MongoClient mongo;
@PreDestroy
public void close() {
if (this.mongo != null) {
this.mongo.close();
}
}
@Bean
@ConditionalOnMissingBean
public MongoClient mongo() throws UnknownHostException {
this.options = options.builder().maxConnectionIdleTime(1000 * 60 * 4).build();
this.mongo = this.properties.createMongoClient(this.options, this.environment);
return this.mongo;
}
}
A very useful link here : Java DriverJAVA-2535 com.mongodb.MongoSocketWriteException ......
For Spring Data with Reactive MongoDb:
My case was a bit different (I had closing connections - which throws "Caused by: java.lang.IllegalStateException: state should be: open")
But You can use this with your case.
application.yml:
spring.data.mongodb:
host: localhost
database: myDb
port: 27017
username: admin
password: test
If Your implementation use MongoReactiveAutoConfiguration for bean creation, then You can configure it with this bean:
@Bean
public MongoClientSettings mongoClientSettings() {
final MongoClientSettings clientSettings = MongoClientSettings.builder()
.retryWrites(true)
.applyToConnectionPoolSettings((ConnectionPoolSettings.Builder builder) -> {
builder.maxSize(300) //connections count
.minSize(100)
.maxConnectionLifeTime(0, TimeUnit.MILLISECONDS)
.maxConnectionIdleTime(0, TimeUnit.MILLISECONDS)
.maxWaitTime(5000, TimeUnit.MILLISECONDS)
.maxWaitQueueSize(5000);
})
.applyToSocketSettings(builder -> {
builder.connectTimeout(2000, TimeUnit.MILLISECONDS);
})
.applicationName("app")
.build();
return clientSettings;
}
To follow your theme, this would be the best to answer your question. Looks like you would like to set a timeout in your application.properties file.
In order to do so:
Instead of
spring.data.mongodb.host=myHost
spring.data.mongodb.port=27017
spring.data.mongodb.database=myDatabase
spring.data.mongodb.username=myUser
spring.data.mongodb.password=myPassword
Try this
spring.data.mongodb.uri=mongodb://myUser:myPassword@myHost:27017,myHost:27017/myDatabase?serverSelectionTimeoutMS=2000&connectTimeoutMS=2000
spring.data.mongodb.database=myDatabase
spring.data.mongo.repositories.enabled=true
Modify time in milliseconds to desired time.
The question was specifically for Spring boot. I am using the following approach which works well, please suggest if there is a way not to use new and use Spring for configuring it.
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
@Configuration
@EnableMongoRepositories("com.myapp.repository")
public class SpringMongoConfig extends AbstractMongoConfiguration {
@Value("${myapp.mongodb.host}")
private String host;
@Value("${myapp.mongodb.port}")
private int port;
@Value("${myapp.mongodb.database}")
private String mongoDB;
@Value("${myapp.mongodb.userName}")
private String userName;
@Value("${myapp.mongodb.password}")
private String password;
@Value("${myapp.mongodb.socketTimeoutMS}")
private int socketTimeout;
@Value("${myapp.mongodb.connectionTimeoutMS}")
private int connectionTimeout;
@Override
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
return super.mongoMappingContext();
}
@Override
@Bean
public Mongo mongo() throws Exception {
List<ServerAddress> servers = new ArrayList<ServerAddress>();
servers.add(new ServerAddress(host, port));
List<MongoCredential> creds = new ArrayList<MongoCredential>();
creds.add(MongoCredential.createCredential(userName, mongoDB, password.toCharArray()));
MongoClientOptions builder = MongoClientOptions.builder().socketTimeout(socketTimeout).connectTimeout(connectionTimeout).build();
return new MongoClient(servers, creds, builder);
}
@Override
protected String getDatabaseName() {
return mongoDB;
}
}
I found the following document with a possible solution.
https://www.programmersought.com/article/1927319190/
It mentions the following:
spring.data.mongodb.address=172.16.250.234:27017,172.16.250.239:27017,172.16.250.240:27017
spring.data.mongodb.replica-set=rs0
spring.data.mongodb.database=test
spring.data.mongodb.username=admin
spring.data.mongodb.password=admin
# Configure spring.data.mongodbDB Pool
spring.data.mongodb.min-connections-per-host=10
spring.data.mongodb.max-connections-per-host=100
spring.data.mongodb.threads-allowed-to-block-for-connection-multiplier=5
spring.data.mongodb.server-selection-timeout=30000
spring.data.mongodb.max-wait-time=120000
spring.data.mongodb.max-connection-idel-time=0
spring.data.mongodb.max-connection-life-time=0
spring.data.mongodb.connect-timeout=10000
spring.data.mongodb.socket-timeout=0
spring.data.mongodb.socket-keep-alive=false
spring.data.mongodb.ssl-enabled=false
spring.data.mongodb.ssl-invalid-host-name-allowed=false
spring.data.mongodb.always-use-m-beans=false
spring.data.mongodb.heartbeat-socket-timeout=20000
spring.data.mongodb.heartbeat-connect-timeout=20000
spring.data.mongodb.min-heartbeat-frequency=500
spring.data.mongodb.heartbeat-frequency=10000
spring.data.mongodb.local-threshold=15
spring.data.mongodb.authentication-database=auth_dev
I'm trying to test this now to make sure it is working, but it at least seems plausible.