2013-04-18 116 views
4

我们正在使用Play 2.1.1及其内置的JPA集成(JPA.em() 等)。如何在运行时更改Play 2 Framework DB配置?

  • 我们如何动态更改db.pass属性? Play.application()。configuration()似乎 在Play 2.1中是不可变的。 (或者我们至少不知道增变器)
  • 如果我们能够更改db.pass,我们如何重新加载数据库配置,以便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" 

应用收到这样的数据,然后重新创建休眠 SessionFactory的。我们新的Play应用将被要求做类似 的事情。

回答

2

要回答我的问题,首先我们通过与覆盖Configuration.onLoadConfig解决在运行时更新不可改变配置的问题如下:

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

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

更新

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

+0

我正在尝试做类似的事情。你能否提供更多关于我可以接触到的细节。我的插件似乎在db配置执行后运行。 –

+0

@ dom-farr我已经添加了关于钩子的评论。 –

+0

谢谢。这将工作。虽然我现在已经找到了那些讨厌的变种,所以我可以扩大原始配置。 –

5

关键是使用ConfigFactory创建一个新的Config条目。这个新的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())); 
    } 
} 
+0

太棒了!正是我正在寻找的。 – Chaitanya

相关问题