I’ve always wanted to add dependency injection support to Firebase, and today we released a candidate for Guice! And if you ask me, it’s very cool indeed.
The documentation is a bit sparse at the moment, but can be found on our wiki. The rest of the post I’ll just show how a small fictional game would look using Guice.
To start with, the Guice support comes in a set of abstract base classes, one for each Firebase artefact. And to use those you’d have to add a dependency to you Maven build (I’ll assume Maven here, you can of course use whatever you’d like):
<dependency> <groupId>com.cubeia.firebase</groupId> <artifactId>guice-support</artifactId> <version>1.0-RC.1</version> </dependency>
And if you haven’t already got it, you’d need our repository as well:
<repository> <id>cubeia-nexus</id> <url>http://m2.cubeia.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository>
Now your all set to go, just extend GuiceGame and return the class of you game processor within the configuration, like so:
public class MyGame extends GuiceGame { public Configuration getConfigurationHelp() { return new ConfigurationAdapter() { public Class getGameProcessorClass() { return MyProcessor.class; } }; } }
So what’s the magic then? It is this: The class MyProcessor will be instantiated by Guice and can therefore contain injections. And further, it will be done in a custom scope, per event, thus isolating instances nicely.
You can also add your own modules to the injection context, again by overriding a method in GuiceGame:
protected void preInjectorCreation(List list) { list.add(new MyGameModule()); }
Which means, you can inject not only stuff from the current table but also, your own classes. So if we continue:
public class MyProcessor implements MyProcessor { /* * This is probably configured in the "MyGameModule" configured * in the guice game extension. */ @Inject private MyHandler handler; /* * This is a speciality, you can inject Firebase services * right into your classes. */ @Service private ScriptSupport support; /* * And another shortcut, if you use Log4j, we have a * a helper annotation for you... */ @Log4j private Logger log; public void handle(GameDataAction action, Table table) { // do something here eh? } [...] }
That should give you the idea. You can inject Firebase services as well as a logger (and remember, if you don’t use Log4j, Guice support the Java utility logging package from scratch). There’s a couple of things not shown here, for example, you can inject table members directly into the classes and the state object, so you don’t have to pass those around.
Any catch? Well, when you create your own modules you’ll need to keep in mind that the processor will only work in a custom scope, called EventScope. So if you have something which needs to be bound not as a singleton or in the default scope, you’ll probably need to do something like this:
bind(MyHandler.class).to(MyHandlerImpl.class).in(EventScoped.class);
And that’s it! In a few days we’ll release our script support, which is as you might imagine built on top of the Guice support. And so far? I love it!