Home > potd > POTD: Application configuration via Guice binding + Groovy

POTD: Application configuration via Guice binding + Groovy

March 1st, 2014

Often I write my applications with Guice. I also often want to make those applications configurable externally. For example I might inject username and password for that app to talk to another app, I might configure some timeout value, and so on. I make these configuration values available in Guice, so that I can access them wherever I need them. All of this is pretty common in many other places, I’d imagine.

Given that all I’m doing here is to pass configuration values from left to right, I thought it’d be nice if I can write configuration directly as a Guice module by using Guice binder EDSL. Then I won’t have to parse and translate these configuration any more.

And that became my project of the day.

This little library allows you to write Guice binding definitions in a text file:

timeout = 3
bind Payment named "customer" to VisaPayment

From your program, you use GroovyWiringModule to load this configuration file:

Module config = new GroovyWiringModule(new File("/etc/myapp.conf"));
Injector i = Guice.createInjector(
  Modules.override( ... my application's modules ...)
    .with(config))

The end result is that the above script gets translated into the following binding:

bind(int.class).annotatedWith(Names.named("timeout")).toInstance(3)
bind(Payment.class).annotatedWith(Names.named("customer")).to(VisaPayment.class)

Using Groovy as the host language for DSL has other benefits. If you are using system properties or environment variables to configure something, you are basically stuck with strings as the only representation of the configuration. With Groovy, I can create a relatively complex object and bind them, or even put some logic to further obtain values from elsewhere:

bind Payment toInstance new VisaPayment(
  cardNumber: "1234-5678-9012-3456",
  expiration: new Date(System.currentTimeInMillis()+TimeUnit.DAYS.toMillis(30),
  cvv: new URL("http://secret.server/cvv").text)

With the functionality in Guice to override definitions in one module by another, I can also even override bindings defined in programs, for example to get more logging, add a filter, etc.

potd , , , ,

  1. Vivek
    March 1st, 2014 at 15:36 | #1

    Pretty cool. The Pattern I have using is injectable Configuration object constructed from a configuration file, I also use it during guide binding. Your approach is very handy, makes these bendable infections auto configurable.

    There is a typo – “annotatedWith(Names.named(“timeout”)).to(VisaPayment.class)” timeout should be “customer”.

  2. Emanuele
    March 1st, 2014 at 23:03 | #2

    Sweet! Did you post this in the Guice mailing list? I’m sure they would appreciate it! :)

  3. March 2nd, 2014 at 21:48 | #3

    @Vivek
    Thanks, corrected.

  4. March 2nd, 2014 at 21:50 | #4

    @Emanuele
    All right, I guess I will post this and see what happens.

  5. Ross Judson
    March 11th, 2014 at 08:22 | #5

    The text DSL is neat, but losing type safety isn’t a fun part of that. ;)

    As one of the architects of HK2, why would you use Guice instead of HK2? And conversely, why use HK2 instead of Guice?

  6. March 25th, 2014 at 14:00 | #6

    This is meant for configuration of apps, and in that context I don’t think there’s a loss of type safety here. You run the app and you’ll get any type errors reported.

    As for HK2 vs Guice, I don’t think a technical difference was a major part of decisions behind doing it, and right now I have no reasons to use HK2.

  1. No trackbacks yet.