How to change the configuration of the Play 2 Framework firewall at runtime?

We use Play 2.1.1 and built-in JPA integration (JPA.em (), etc.).

  • How can we dynamically change the db.pass property? Play.application (). Configuration () seems to be unchanged as of 2.1. (or at least we donโ€™t know about the mutators)
  • If we can change db.pass, how can we reload the database configuration so that JPA.em () returns EntityManager with a new password?

What we are trying to avoid is to recreate the EntityManager using the EntityManagerFactory. We want to continue for Play to manage this in the JPA support class.

Background

The system has a default database configuration for local startup. When deploying to the server, the database password is dynamically set in the running application using the following script:

#!/bin/bash stty -echo read -p "Password: " PASS stty echo curl -k https://127.0.0.1:8443/someUrl/pwd --data "password=$PASS" 

The application receives this data and then recreates the SessionFactory hibernation. Our new Play app will have to do something similar.

+4
source share
2 answers

To answer my own question, we first solved the problem of updating an immutable configuration at run time by overriding Configuration.onLoadConfig as follows:

  • If the configuration indicates production.level is PROD
  • Read password from stdin
  • Create a new configuration by transferring it to the map and creating a new one using ConfigFactory.parseMap with a new parameter
  • Return super.onLoadConfig

However, this still does not address the problem of reloading the database configuration. In the end, my colleague created Play! a plugin that is essentially a copy of some JPA classes with the added ability to reload using the configuration properties map.

Update

A hook is an additional static method that the plugin adds to the JPA class (for example, reloadWithProperties). This method creates a new data source, which is then restored to JNDI.

+2
source

The key is to use ConfigFactory to create a new Config record. This new Config contains an entry for the password with the value received from your HTTP call to the password service.

A new configuration is created using the new Config, which in turn reverts to the original configuration from the original configuration.

Basically, a new password entry replaces the original.

It sounds long when you say this, but the code is pretty readable.

 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())); } } 
+5
source

All Articles