Add username/password and MongoClientOptions to Mongo config
The username/password option stil lonly works for a single host (to connect to a cluster I suspect you need to set the URI). Also added a MongoClientOptions (if a bean of that type exists it will be used to populate the options that aren't in the URI). Fixed gh-536
This commit is contained in:
parent
6cf946ea3f
commit
6ac85c1759
|
@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
|
import com.mongodb.MongoClientOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for Mongo.
|
* {@link EnableAutoConfiguration Auto-configuration} for Mongo.
|
||||||
|
@ -45,6 +46,9 @@ public class MongoAutoConfiguration {
|
||||||
@Autowired
|
@Autowired
|
||||||
private MongoProperties properties;
|
private MongoProperties properties;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private MongoClientOptions options;
|
||||||
|
|
||||||
private Mongo mongo;
|
private Mongo mongo;
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
|
@ -57,7 +61,7 @@ public class MongoAutoConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Mongo mongo() throws UnknownHostException {
|
public Mongo mongo() throws UnknownHostException {
|
||||||
this.mongo = this.properties.createMongoClient();
|
this.mongo = this.properties.createMongoClient(this.options);
|
||||||
return this.mongo;
|
return this.mongo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,13 @@ public class MongoDataAutoConfiguration {
|
||||||
@Autowired
|
@Autowired
|
||||||
private MongoProperties properties;
|
private MongoProperties properties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public MongoDbFactory mongoDbFactory(Mongo mongo) throws Exception {
|
||||||
|
String db = this.properties.getMongoClientDatabase();
|
||||||
|
return new SimpleMongoDbFactory(mongo, db);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory)
|
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory)
|
||||||
|
@ -61,18 +68,11 @@ public class MongoDataAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public MongoDbFactory mongoDbFactory(Mongo mongo) throws Exception {
|
public GridFsTemplate gridFsTemplate(Mongo mongo, MongoTemplate mongoTemplate) {
|
||||||
String db = StringUtils.hasText(this.properties.getGridFsDatabase()) ? this.properties
|
String db = StringUtils.hasText(this.properties.getGridFsDatabase()) ? this.properties
|
||||||
.getGridFsDatabase() : this.properties.getMongoClientDatabase();
|
.getGridFsDatabase() : this.properties.getMongoClientDatabase();
|
||||||
|
return new GridFsTemplate(new SimpleMongoDbFactory(mongo, db),
|
||||||
return new SimpleMongoDbFactory(mongo, db);
|
mongoTemplate.getConverter());
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public GridFsTemplate gridFsTemplate(MongoDbFactory mongoDbFactory,
|
|
||||||
MongoTemplate mongoTemplate) {
|
|
||||||
return new GridFsTemplate(mongoDbFactory, mongoTemplate.getConverter());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,18 @@
|
||||||
package org.springframework.boot.autoconfigure.mongo;
|
package org.springframework.boot.autoconfigure.mongo;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
import com.mongodb.DBPort;
|
import com.mongodb.DBPort;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
|
import com.mongodb.MongoClientOptions;
|
||||||
|
import com.mongodb.MongoClientOptions.Builder;
|
||||||
import com.mongodb.MongoClientURI;
|
import com.mongodb.MongoClientURI;
|
||||||
|
import com.mongodb.MongoCredential;
|
||||||
|
import com.mongodb.ServerAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties for Mongo.
|
* Configuration properties for Mongo.
|
||||||
|
@ -44,6 +50,10 @@ public class MongoProperties {
|
||||||
|
|
||||||
private String gridFsDatabase;
|
private String gridFsDatabase;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private char[] password;
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return this.host;
|
return this.host;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +70,31 @@ public class MongoProperties {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return this.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(char[] password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPassword() {
|
||||||
|
if (this.password == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < this.password.length; i++) {
|
||||||
|
this.password[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
return this.uri;
|
return this.uri;
|
||||||
}
|
}
|
||||||
|
@ -91,11 +126,51 @@ public class MongoProperties {
|
||||||
return new MongoClientURI(this.uri).getDatabase();
|
return new MongoClientURI(this.uri).getDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MongoClient createMongoClient() throws UnknownHostException {
|
public MongoClient createMongoClient(MongoClientOptions options)
|
||||||
if (this.host != null) {
|
throws UnknownHostException {
|
||||||
return new MongoClient(this.host, this.port);
|
try {
|
||||||
|
if (this.host != null) {
|
||||||
|
if (options == null) {
|
||||||
|
options = MongoClientOptions.builder().build();
|
||||||
|
}
|
||||||
|
List<MongoCredential> credentials = null;
|
||||||
|
if (this.password != null && this.username != null) {
|
||||||
|
credentials = Arrays.asList(MongoCredential.createMongoCRCredential(
|
||||||
|
this.username, getMongoClientDatabase(), this.password));
|
||||||
|
}
|
||||||
|
return new MongoClient(Arrays.asList(new ServerAddress(this.host,
|
||||||
|
this.port)), credentials, options);
|
||||||
|
}
|
||||||
|
// The options and credentials are in the URI
|
||||||
|
return new MongoClient(new MongoClientURI(this.uri, builder(options)));
|
||||||
}
|
}
|
||||||
return new MongoClient(new MongoClientURI(this.uri));
|
finally {
|
||||||
|
clearPassword();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builder builder(MongoClientOptions options) {
|
||||||
|
Builder builder = MongoClientOptions.builder();
|
||||||
|
if (options != null) {
|
||||||
|
builder.alwaysUseMBeans(options.isAlwaysUseMBeans());
|
||||||
|
builder.autoConnectRetry(options.isAutoConnectRetry());
|
||||||
|
builder.connectionsPerHost(options.getConnectionsPerHost());
|
||||||
|
builder.connectTimeout(options.getConnectTimeout());
|
||||||
|
builder.cursorFinalizerEnabled(options.isCursorFinalizerEnabled());
|
||||||
|
builder.dbDecoderFactory(options.getDbDecoderFactory());
|
||||||
|
builder.dbEncoderFactory(options.getDbEncoderFactory());
|
||||||
|
builder.description(options.getDescription());
|
||||||
|
builder.maxAutoConnectRetryTime(options.getMaxAutoConnectRetryTime());
|
||||||
|
builder.maxWaitTime(options.getMaxWaitTime());
|
||||||
|
builder.readPreference(options.getReadPreference());
|
||||||
|
builder.socketFactory(options.getSocketFactory());
|
||||||
|
builder.socketKeepAlive(options.isSocketKeepAlive());
|
||||||
|
builder.socketTimeout(options.getSocketTimeout());
|
||||||
|
builder.threadsAllowedToBlockForConnectionMultiplier(options
|
||||||
|
.getThreadsAllowedToBlockForConnectionMultiplier());
|
||||||
|
builder.writeConcern(options.getWriteConcern());
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,13 @@ package org.springframework.boot.autoconfigure.mongo;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.mongodb.Mongo;
|
||||||
|
import com.mongodb.MongoClientOptions;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@ -41,11 +46,44 @@ public class MongoAutoConfigurationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void templateExists() {
|
public void clientExists() {
|
||||||
this.context = new AnnotationConfigApplicationContext(
|
this.context = new AnnotationConfigApplicationContext(
|
||||||
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class,
|
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class);
|
||||||
MongoDataAutoConfiguration.class);
|
assertEquals(1, this.context.getBeanNamesForType(Mongo.class).length);
|
||||||
assertEquals(1, this.context.getBeanNamesForType(MongoTemplate.class).length);
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void optionsAdded() {
|
||||||
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.data.mongodb.host:localhost");
|
||||||
|
this.context.register(OptionsConfig.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
assertEquals(300, this.context.getBean(Mongo.class).getMongoOptions()
|
||||||
|
.getSocketTimeout());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void optionsAddedButNoHost() {
|
||||||
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.data.mongodb.uri:mongodb://localhost/test");
|
||||||
|
this.context.register(OptionsConfig.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
assertEquals(300, this.context.getBean(Mongo.class).getMongoOptions()
|
||||||
|
.getSocketTimeout());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class OptionsConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MongoClientOptions mongoOptions() {
|
||||||
|
return MongoClientOptions.builder().socketTimeout(300).build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,9 @@ package org.springframework.boot.autoconfigure.mongo;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -45,6 +47,18 @@ public class MongoDataAutoConfigurationTests {
|
||||||
this.context = new AnnotationConfigApplicationContext(
|
this.context = new AnnotationConfigApplicationContext(
|
||||||
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class,
|
PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class,
|
||||||
MongoDataAutoConfiguration.class);
|
MongoDataAutoConfiguration.class);
|
||||||
|
assertEquals(1, this.context.getBeanNamesForType(MongoTemplate.class).length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void gridFsTemplateExists() {
|
||||||
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"spring.data.mongodb.gridFsDatabase:grid");
|
||||||
|
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||||
|
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
assertEquals(1, this.context.getBeanNamesForType(GridFsTemplate.class).length);
|
assertEquals(1, this.context.getBeanNamesForType(GridFsTemplate.class).length);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,13 @@ public class RelaxedDataBinderTests {
|
||||||
assertEquals("bar", target.getFoo());
|
assertEquals("bar", target.getFoo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBindChars() throws Exception {
|
||||||
|
VanillaTarget target = new VanillaTarget();
|
||||||
|
bind(target, "bar: foo");
|
||||||
|
assertEquals("foo", new String(target.getBar()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBindStringWithPrefix() throws Exception {
|
public void testBindStringWithPrefix() throws Exception {
|
||||||
VanillaTarget target = new VanillaTarget();
|
VanillaTarget target = new VanillaTarget();
|
||||||
|
@ -656,12 +663,22 @@ public class RelaxedDataBinderTests {
|
||||||
|
|
||||||
private String foo;
|
private String foo;
|
||||||
|
|
||||||
|
private char[] bar;
|
||||||
|
|
||||||
private int value;
|
private int value;
|
||||||
|
|
||||||
private String foo_bar;
|
private String foo_bar;
|
||||||
|
|
||||||
private String fooBaz;
|
private String fooBaz;
|
||||||
|
|
||||||
|
public char[] getBar() {
|
||||||
|
return this.bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBar(char[] bar) {
|
||||||
|
this.bar = bar;
|
||||||
|
}
|
||||||
|
|
||||||
public int getValue() {
|
public int getValue() {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue