We learned about externalised configuration in a previous blog post. Ratpack provides support out of the box for several formats and configuration sources. For example we can use files in YAML, properties or JSON format, arguments passed to the application, system properties and environment variables. We can add our own configuration source by implementing the ratpack.config.ConfigSource
interface. We must override the method loadConfigData
to load configuration data from a custom source and convert it to a format that can be handled by Ratpack.
We are going to write a custom ConfigSource
implementation that will get configuration data from a database. We assume the data is in a table with the name CONFIGURATION
and has the columns KEY
and VALUE
. The format of the key is the same as for Java properties files.
package com.mrhaki.config import groovy.sql.Sql import ratpack.config.ConfigSource import ratpack.config.internal.source.AbstractPropertiesConfigSource /** * {@link ConfigSource} implementation to read configuration * data from a database table. The database must have a table * CONFIGURATION with the VARCHAR columns KEY and VALUE. * The format of the key matches that of regular Java properties. * * E.g. we can insert the configuration key 'app.message' like this: * INSERT INTO CONFIGURATION(KEY, VALUE) VALUES('app.message', 'Ratpack rocks'); * * This class extends {@link AbstractPropertiesConfigSource}, because it supports * property key formats like we use in our database. */ class JdbcConfigSource extends AbstractPropertiesConfigSource { /** * Database JDBC url, username, password and driver. */ final Map<String, String> sqlProperties JdbcConfigSource(final Map<String, String> sqlProperties) { super(Optional.empty()) this.sqlProperties = sqlProperties } @Override protected Properties loadProperties() throws Exception { final Properties properties = new Properties() Sql.withInstance(sqlProperties) { sql-> // Get key/value pairs from database. sql.eachRow("SELECT KEY, VALUE FROM CONFIGURATION") { row -> // Save found data in Properties object. properties.setProperty(row.key, row.value) } } return properties } }
To use this ConfigSource
implementation in our Ratpack application we use the add
method of ConfigDataBuilder
:
import com.mrhaki.config.JdbcConfigSource import org.slf4j.Logger import org.slf4j.LoggerFactory import ratpack.config.ConfigData import static groovy.json.JsonOutput.prettyPrint import static groovy.json.JsonOutput.toJson import static ratpack.groovy.Groovy.ratpack class SampleConfig { String message } ratpack { bindings { final ConfigData configData = ConfigData.of { builder -> // Add our custom JdbcConfigSource as // configuration source. builder.add( new JdbcConfigSource( driver: 'org.postgresql.Driver', url: 'jdbc:postgresql://192.168.99.100:32768/', user: 'postgres', password: 'secret')) .build() } // Assign all configuration properties from the /app node // to the properties in the SampleConfig class. bindInstance(SimpleConfig, configData.get('/app', SampleConfig)) } handlers { get('configprops') { SampleConfig config -> render(prettyPrint(toJson(config))) } } }
When we request configprops
we get the following result:
$ http -b localhost:5050/configprops { "message": "Ratpack rocks!" } $
Written with Ratpack 1.1.1.