5

我们正在使用 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 助手类中管理它。

背景

系统具有用于在本地运行的默认数据库配置。部署到服务器时,使用以下脚本在正在运行的应用程序上动态设置数据库密码:

#!/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 应用将需要执行类似的操作。

4

2 回答 2

6

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

使用新配置创建一个新配置,而新配置又从原始配置回退到原始配置。

基本上,新密码条目会取代原来的密码条目。

当你说它时听起来很啰嗦,但代码非常可读。

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()));
    }
}
于 2013-06-18T06:37:18.463 回答
3

为了回答我自己的问题,首先我们通过使用以下内容覆盖 Configuration.onLoadConfig 来解决在运行时更新不可变配置的问题:

  1. 如果配置表明 production.level 是 PROD
  2. 从标准输入读取密码
  3. 通过将旧配置转换为地图并使用 ConfigFactory.parseMap 构建新配置来创建新配置,同时使用新参数
  4. 返回 super.onLoadConfig

但是,这仍然没有解决重新加载数据库配置的问题。最后,我的同事创建了一个 Play!插件,它本质上是一些 JPA 类的副本,具有重新加载配置属性映射的附加功能。

更新

“钩子”是插件添加到 JPA 类的附加静态方法(例如 reloadWithProperties)。此方法创建一个新的数据源,然后在 JNDI 中重新绑定。

于 2013-05-20T18:49:43.997 回答