Command queue Bootstrap code looks like Service Locator pattern not DI

63 views
Skip to first unread message

Dave Elton

unread,
Aug 8, 2012, 3:32:06 PM8/8/12
to google...@googlegroups.com
I have an architectural conundrum.

I am using Guice in a project that is following CQRS. The Query side of the system is fine. 

For the command side of the system I have chosen to use a queue to store the commands as they are received along with their arguments. The commands all implement a common interface with an execute method. 
The idea is that the commands are later executed in sequence by a worker thread which calls execute() on each Command in turn.
The classes that implement Command contain the command arguments as fields which vary depending on which implementation the command represents.

The commands only require injection once they are taken off the queue ready for execution (this is mostly because I would like to be able to serialize commands, but also because the execution of commands needs different modules to the part of the application that receives and queues them)

My problem is this:
Because the commands need to wait until they are taken off the queue to get their dependencies, I end up passing a lightly wrapped Injector to their 'execute' method so they can create themselves an object graph. This feels more like the Service Locator pattern than Dependency Injection.

I've not been using Guice (or DI) long so if I've utterly missed the point please forgive me and give me a gentle nudge in the right direction.

Thanks,
Dave

Leigh Klotz, Jr.

unread,
Aug 23, 2012, 3:58:22 PM8/23/12
to google...@googlegroups.com
It sounds like the queue entries -- especially since they are serializable --- are value objects and you shouldn't give execution behavior to them and shouldn't create them with Guice.  Serializing objects that have Guice providers in them does not work out well.
Instead, create them using new and have them encapsulate the arguments necessary to create a real runnable command.
Then in your Worker, dequeue one and use a Map<String,Provider<Command>> or a Map<String,CommandFactory> (or if there are are two different injection times, a Map<String,Provider<CommandFactory>>) using MapBinder http://code.google.com/p/google-guice/wiki/Multibindings

The Provider and possible the use of an Assisted injection should give you the inflection points you need without recourse to injecting the injector. 
(Usually that trick is reserved for meta-level extensions or integration with other frameworks or systems (such as Servlets or Quartz or Hadoop) that use classnames or class objects and newInstance(), and you need to write an adapter.  And of course your own static void main().)

Leigh.

Reply all
Reply to author
Forward
0 new messages