4

我们在 Tomcat 中部署了一个基于 spring 的 webapp,我们希望为用户提供一个连接到哪个 mongo 数据库的选项。为此,我们有一个设置向导,它通过在线表单从用户那里捕获 mongo 连接详细信息。捕获这些细节后,我们想动态连接到 Mongo。现在我们通过 xml 配置加载我们的 mongo:

<bean id="configmapper" class="com.db.util.ConfigurationMapper" />
<bean id="configmap" factory-bean="configmapper" factory-method="readXML" />
<mongo:mongo host="#{configmap.getHost()}" port="#{configmap.getPort()}" />
<mongo:db-factory dbname="#{configmap.getName()}"
    mongo-ref="mongo" />

用户值由配置映射器 bean 读取/写入存储,但是在设置它们之后,我们基本上想要“重新启动”mongo 驱动程序。为此,我们正在尝试:

XmlWebApplicationContext context = ((XmlWebApplicationContext) ContextLoader
            .getCurrentWebApplicationContext());
context.refresh();

这带来了重新加载所有应用程序 bean 的好结果,我们甚至可以在日志中看到重新创建的 Mongo bean 以及上下文中的所有其他 bean:

DEBUG 2015-05-12 21:09:29,590 [http-nio-8087-exec-6] (DefaultSingletonBeanRegistry.java:221) - Creating shared instance of singleton bean 'mongo'
...
DEBUG 2015-05-12 21:09:08,121 [localhost-startStop-1] (DefaultSingletonBeanRegistry.java:221) - Creating shared instance of singleton bean 'mongoTemplate'
...
DEBUG 2015-05-12 21:09:29,590 [http-nio-8087-exec-6] (AbstractAutowireCapableBeanFactory.java:449) - Creating instance of bean 'mongoDbFactory'

但是,当我们去使用连接时,我们会得到以下堆栈跟踪:

Caused by: java.lang.IllegalStateException: open
    at org.bson.util.Assertions.isTrue(Assertions.java:36)
    at com.mongodb.DBTCPConnector.isMongosConnection(DBTCPConnector.java:367)
    at com.mongodb.Mongo.isMongosConnection(Mongo.java:622)
    at com.mongodb.DBCollection.findOne(DBCollection.java:936)
    at com.mongodb.DBCollection.findOne(DBCollection.java:914)
    at com.mongodb.DBCollection.findOne(DBCollection.java:858)
    at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2069)
    at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2053)
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1828)
    at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:1645)
    at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.java:560)

我们认为也许 mongo 连接没有正确关闭,所以我们引入了 mongo bean 并在重新加载之前将其关闭:

@Autowired
private Mongo mongo;
...
mongo.close();
XmlWebApplicationContext context = ((XmlWebApplicationContext) ContextLoader
                .getCurrentWebApplicationContext());
context.refresh();

但是我们收到了同样的例外。

有谁知道我们如何在不重新启动应用服务器的情况下实现动态 mongo 重新连接?也许还有另一种方法可以解决这个问题?我们希望为最终用户提供 GUI Web 配置,而不是自己编辑配置文件。

感谢您提供的任何建议。

4

1 回答 1

0

从 spring 应用程序上下文访问数据库时,我遇到了类似的问题。经过几天的调查,我终于发现存在时间问题,并且在设置数据库凭据之后和重新加载上下文之前引入了延迟再次解决了这个问题。由于某种原因,我重新加载上下文的时间过早,并且在尝试重新加载时尚未设置数据库设置。

引入延迟后,一切都开始按预期工作。

我希望它有所帮助。

于 2017-08-13T13:15:01.663 回答