PUBLIC OBJECT

Guice commands

I recently checked in a new Guice extension called commands. The goal is simple - make it possible to modify your modules at runtime.

But modules aren't naturally data, they're more like code:

    Module module = new AbstractModule() {
      protected void configure() {
        bind(Soda.class).to(Coke.class);
        bind(Snack.class).to(BuffaloRanchDoritos.class);
      }
    };`</pre>
How can I convert this executable chunk of code into a manipulatable datastructure? Since Guice is built-on a well-defined  API, this wasn't  too difficult. I created a custom `Binder` that recorded the method calls into it made by the modules. I wrapped that in an API that converts the method calls into `Command` objects:
<pre class="prettyprint">`    CommandRecorder commandRecorder = new CommandRecorder(new FutureInjector());
    List&lt;Command&gt; commands = commandRecorder.recordCommands(module);`</pre>
The `Command` interface has different implementation for each method[*](#) on `Binder`. There's `BindConstantCommand`, `BindScopeCommand`, `RequestStaticInjectionCommand` and several others. The interface supports [visitors](http://en.wikipedia.org/wiki/Visitor_pattern), so manipulating commands with type safety is easy. 

Finally, there's a class called `CommandReplayer` that can convert a list of commands back into a module. By extending the template methods, you can rewrite commands while you replay them:
<pre class="prettyprint">`    CommandReplayer rewriter = new CommandReplayer() {
      @Override public &lt;T&gt; void replayBind(Binder binder, BindCommand&lt;T&gt; command) {
        Key&lt;? extends T&gt; target = command.getTarget().getKey(null);

        if (Key.get(Soda.class).equals(target)) {
          binder.bind(Soda.class).to(Pepsi.class);
        } else {
          super.replayBind(binder, command);
        }
      }
    };

    Module rewrittenModule = rewriter.createModule(commands);`</pre>
The last thing left to do is to build an injector from the rewritten module. It works!
<pre class="prettyprint">`    Injector injector = Guice.createInjector(rewrittenModule);
    assertEquals(new Pepsi(), injector.getInstance(Soda.class));

We're using commands in a soon-to-be-released test library. I suspect other Guice users will come up with more interesting uses of commands. If you're hacking on Guice, consider using commands when you need to tweak a module.