Thursday, July 10, 2008

Guice, main and startup configuration flags

Here is a small trick we use in an in-house program wired with Google Guice. The goal is to pick the wiring configuration from the command-line without too many contortions.

The idea is to use enums to represent the wiring, and using the command-line to pick the enum. Thus:

enum WhichOne {
   /** Uses module "A", defined elsewhere. */
   ONE(new ModuleA()),
   /** Uses module "A" and "B", defined elsewhere. */
   TWO(new ModuleA(), new ModuleB());

   private final Module module;

   WhichOne(final Module... modules) {
       module = new CompoundModule(modules);
   }

   public Module getModule() {
       return module;
   }
}

class CompoundModule extends AbstractModule {
   private final Module[] modules;

   CompoundModule(final Module... modules) {
       this.modules = modules;
   }

   @Override
   public void configure() {
       for (final Module module : modules)
           install(module);
   }
}

class Main {
    public static void main(final String... arguments) {
        // Real programs use args4j
        final WhichOne whichOne = WhichOne.valueOf(arguments[0]);
        final Module module = whichOne.getModule();
        final Injector injector = Guice.createInjector(module);

        injector.createInstance(MyProgram.class);
   }
}

Now I can pick configuration on the command line:

$ my_program ONE # use module "A"
$ my_program TWO # use module "A" and "B"

No comments: