views:

192

answers:

2

I've taken the plunge and used Guice for my latest project. Overall impressions are good, but I've hit an issue that I can't quite get my head around.

Background: It's a Java6 application that accepts commands over a network, parses those commands, and then uses them to modify some internal data structures. It's a simulator for some hardware our company manufactures. The changes I make to the internal data structures match the effect the commands have on the real hardware, so subsequent queries of the data structures should reflect the hardware state based on previously run commands.

The issue I've encountered is that the command objects need to access those internal data structures. Those structures are being created by Guice because they vary depending on the actual instance of the hardware being emulated. The command objects are not being created by Guice because they're essentially dumb objects: they accept a text string, parse it, and invoke a method on the data structure.

The only way I can get this all to work is to have those command objects be created by Guice and pass in the data structures via injection. It feels really clunky and totally bloats the constructor of the data objects.

What have I missed here?

+1  A: 

Dependency injection works best for wiring services. It can be used to inject value objects, but this can be a bit awkward especially if those objects are mutable.

That said, you can use Providers and @Provides methods to bind objects that you create yourself.

Jesse Wilson
If your value objects vary depending on the hardware emulated, you can write a factory to create them and have Guice inject the factory to the code that needs it. In other words, one way to avoid injecting value objects is to create a service that produces the value objects.
NamshubWriter
A: 

Assuming that responding to a command is not that different from responding to a http request, I think you're going the right path.

A commonly used pattern in http applications is to wrap logic of the application into short lived objects that have both parameters from request and some backends injected. Then you instantiate such object and call a simple, parameterless method that does all magic.

Maybe scopes could inspire you somehow? Look into documentation and some code examples for read the technical details. In code it looks more less like that. Here's how this might work for your case:

class MyRobot {
   Scope myScope;
   Injector i;       

   public void doCommand(Command c) {
      myScope.seed(Key.get(Command.class), 
      i.getInstance(Handler.class).doSomething();
   }
}


class Handler {
   private final Command c;
   @Inject
   public Handler(Command c, Hardware h) {
     this.c = c;
   }

   public boolean doSomething() {
     h.doCommand(c);
     // or c.modifyState(h) if you want c to access internals of h
   }
}

Some people frown upon this solution, but I've seen this in code relying heavily on Guice in the past in at least two different projects.

Granted you'll inject a bit of value objects in the constructors, but if you don't think of them as value objects but rather parameters of the class that change it's behaviour it all makes sense.

It is a bit awkward and some people frown upon injecting value objects that way, but I have seen this in the past in projects that relied heavily on Guice for a while and it worked great.

Marcin