如何在运行时更改Play 2框架的DB配置?

6
我们正在使用Play 2.1.1及其内置的JPA集成(JPA.em()等)。
- 如何动态更改db.pass属性?Play.application().configuration()似乎在Play 2.1中是不可变的(或者我们至少不知道有可变的选项)。 - 如果我们能够更改db.pass,那么如何重新加载DB配置,以便JPA.em()返回一个使用新密码的EntityManager? 我们试图避免的是必须使用EntityManagerFactory重新创建EntityManager。 我们希望继续让Play在JPA助手类中管理它。
背景: 该系统在本地运行时具有默认的DB配置。 当部署到服务器上时,使用以下脚本动态设置运行应用程序的DB密码:
#!/bin/bash 
stty -echo 
read -p "Password: " PASS 
stty echo 
curl -k https://127.0.0.1:8443/someUrl/pwd --data "password=$PASS" 

应用程序接收这些数据,然后重新创建Hibernate SessionFactory。我们的新Play应用程序将需要执行类似操作。
2个回答

6

关键是使用ConfigFactory创建一个新的Config条目。这个新的Config包含了密码条目,其值来自于你的http调用密码服务。

使用新的Config创建新的Configuration,然后回退到原始Configuration中的原始Config。

基本上,新的密码条目取代了原始密码条目。

当你说出来时,听起来很冗长,但代码非常易读。

public class Global extends GlobalSettings {

    // inject http client to make call for password

    @Override
    public Configuration onLoadConfig(Configuration configuration, File file, ClassLoader classLoader) {
        final Config config = ConfigFactory.parseString(String.format("db.default.user=%s", callPasswordService()));

        return new Configuration(config.withFallback(configuration.getWrappedConfiguration().underlying()));
    }
}

3
为了回答自己的问题,我们通过覆盖Configuration.onLoadConfig来解决在运行时更新不可变配置的问题,具体操作如下:
  1. 如果配置表明production.level是PROD
  2. 从标准输入读取密码
  3. 将旧配置表转换为Map,并使用ConfigFactory.parseMap构建新的配置表,同时加入新参数
  4. 返回super.onLoadConfig
然而,这仍未解决重新加载DB配置的问题。最终,我的同事创建了一个Play!插件,它基本上是一些JPA类的副本,但增加了使用配置属性地图重新加载的功能。 更新 “钩子”是插件添加到JPA类的额外静态方法(例如reloadWithProperties)。此方法创建一个新数据源,然后在JNDI中重新绑定。

我正在尝试做类似的事情。您能否提供更多详细信息,让我知道在哪里可以插入代码?我的插件似乎是在执行数据库配置之后运行的。 - dom farr
@dom-farr 我已经添加了关于钩子的注释。 - John Lehmann
谢谢。这个可以用。虽然我现在找到了那些讨厌的变量,所以我可以增强原始配置。 - dom farr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接