In Ratpack we can use Guice modules to organise code to provide objects to the registry. Ratpack adds configurable modules that take an extra configuration object. Values from the configuration object are used to create new objects that are provided to our application. Using the Groovy DSL we have several ways to make a configuration object available to a configurable module.
Let's create a sample configurable module and look at the different ways to give it a configuration object. We create a module, GreetingModule
, that provides a Greeting
object. The configuration is defined in the class GreetingConfig
.
// File: src/main/groovy/com/mrhaki/ratpack/GreetingModule.groovy package com.mrhaki.ratpack import com.google.inject.Provides import groovy.transform.CompileStatic import ratpack.guice.ConfigurableModule @CompileStatic class GreetingModule extends ConfigurableModule<GreetingConfig> { @Override protected void configure() {} /** * Method to create a new Greeting object with values * from the GreetingConfig configuration object. */ @Provides Greeting greeting(final GreetingConfig config) { new Greeting(message: "${config.salutation}, ${config.message}") } }
// File: src/main/groovy/com/mrhaki/ratpack/GreetingConfig.groovy package com.mrhaki.ratpack import groovy.transform.CompileStatic /** * Configuration properties for creating * a {@link Greeting} object using the * configurable module {@link GreetingModule}. */ @CompileStatic class GreetingConfig { String message String salutation }
// File: src/main/groovy/com/mrhaki/ratpack/Greeting.groovy package com.mrhaki.ratpack import groovy.transform.CompileStatic /** * Simple class with a greeting message. * The {@link GreetingModule} module creates * an instance of this class. */ @CompileStatic class Greeting { String message }
We have our configurable module and the supporting classes. Now we define the configuration and module in the bindings
block of our Ratpack Groovy application. We use the ConfigData
class to set configuration properties we later bind to the GreetingConfig
object. With ConfigData
we can define configuration properties from different sources, like files in Yaml, JSON or Java properties format. In our sample we simply define them using a Map
. In the first sample we use the module
method with a Closure
argument to configure the GreetingModule
// File: src/ratpack/Ratpack.groovy import com.mrhaki.ratpack.Greeting import com.mrhaki.ratpack.GreetingConfig import com.mrhaki.ratpack.GreetingModule import ratpack.config.ConfigData import ratpack.config.ConfigDataBuilder import static ratpack.groovy.Groovy.ratpack ratpack { bindings { final ConfigData configData = ConfigData.of { ConfigDataBuilder builder -> builder.props( ['greeting.salutation': 'Hi', 'greeting.message' : 'how are you doing?']) // We can also use external files, // system properties and environment // variables to set configuration properties // inside this block. builder.build() } // The module methods allows a Closure argument to // set values for the supported configuration class. module GreetingModule, { GreetingConfig config -> config.salutation = configData.get('/greeting/salutation', String) config.message = configData.get('/greeting/message', String) } } handlers { // Simple handler using the created Greeting object. get { Greeting greeting -> render greeting.message } } }
In the following sample we create an instance of GreetingConfig
using the bindInstance
method. The GreetingModule
will pick up this instance and use it automatically:
// File: src/ratpack/Ratpack.groovy import com.mrhaki.ratpack.Greeting import com.mrhaki.ratpack.GreetingConfig import com.mrhaki.ratpack.GreetingModule import ratpack.config.ConfigData import ratpack.config.ConfigDataBuilder import static ratpack.groovy.Groovy.ratpack ratpack { bindings { final ConfigData configData = ConfigData.of { ConfigDataBuilder builder -> builder.props( ['greeting.salutation': 'Hi', 'greeting.message' : 'how are you doing?']) // We can also use external files, // system properties and environment // variables to set configuration properties // inside this block. builder.build() } // First create an instance of the GreetingConfig class. bindInstance GreetingConfig, configData.get('/greeting', GreetingConfig) // With the module method we use the GreetingModule and // because there is a GreetingConfig instance available // it is used to configure the module. module GreetingModule } handlers { // Simple handler using the created Greeting object. get { Greeting greeting -> render greeting.message } } }
Finally we can use the moduleConfig
method. This methods accepts a configuration object as an argument directly. So we can use an instance of GreetingConfig
as method argument. We can also combine it with a Closure
argument to override configuration properties:
// File: src/ratpack/Ratpack.groovy import com.mrhaki.ratpack.Greeting import com.mrhaki.ratpack.GreetingConfig import com.mrhaki.ratpack.GreetingModule import ratpack.config.ConfigData import ratpack.config.ConfigDataBuilder import static ratpack.groovy.Groovy.ratpack ratpack { bindings { final ConfigData configData = ConfigData.of { ConfigDataBuilder builder -> builder.props( ['greeting.salutation': 'Hi', 'greeting.message' : 'how are you doing?']) // We can also use external files, // system properties and environment // variables to set configuration properties // inside this block. builder.build() } // With the moduleConfig method we can pass an instance // of GreetingConfig directly. moduleConfig GreetingModule, configData.get('/greeting', GreetingConfig) // Or we can even combine it with a Closure argument to override a // configuration property. //moduleConfig( // GreetingModule, // configData.get('/greeting', GreetingConfig)) { GreetingConfig config -> // config.message = 'Ratpack rocks!' //} } handlers { // Simple handler using the created Greeting object. get { Greeting greeting -> render greeting.message } } }
Written with Ratpack 1.1.1.