Dev/guice

= Firebase Guice Support = Firebase works well with Guice and an add-on is released with Guice support started. It contains base-classes for all Firebase artifacts which sets up the injection contexts properly. This page outlines how the guice support add-on works.

Requirements
A basic understanding of Cubeia Firebase is needed to understand this page.

With Maven
To build with Maven you will need the following dependency and repository:

com.cubeia.firebase guice-support 1.4

cubeia-nexus http://m2.cubeia.com/nexus/content/groups/public/ true true

Without Maven
You can easily use the Guice add-on without Maven, just download the following file and add to you build class path:

http://m2.cubeia.com/nexus/content/groups/public/com/cubeia/firebase/guice-support/1.4/guice-support-1.4.jar

Overview
Each artifact in Firebase, service, game and tournament, has a base class in the Guice support JAR. These base classes uses programmatic configuration through abstract methods to set-up an initial injection context. However, they differ in one important way:


 * The game will setup one injection context for each executed event. This context will include the event itself, the table it is executed on and the current state associated with the table. In other words, the injection will be done in a custom event scope.

Quick How-To
Extend GuiceGame:

public class MyGame extends GuiceGame [...]

However, keep in mind...

Note:  If you override init in your game implementation, then you need to call super.init or Guice will not be initialized.

Override 'getConfigurationHelp' to return a configuraton, with your processor class, and optionally your interceptor and listener classes:

public Configuration getConfigurationHelp { return new Configuration {

public Class<? extends GameProcessor> getGameProcessorClass { // Return the class of your processor, mandatory }	public Class<? extends TableListener> getTableListenerClass { // Return the class of your listener, or null }	public Class<? extends TableInterceptor> getTableInterceptorClass { // Return the class of your interceptor, or null }	public Class<?> getGameStateClass { // Return the class of your state object, or null }   }; }

Also, if you want to register your own modules, you can override 'preInjectorCreation':

public void preInjectorCreation(List list) { list.add(new MyGameModule); }

If you need to access bound resources you can override 'postInjectorCreation':

public void postInjectorCreation(Injector injector) { // do something smart here... }

Scope
All injections in the game will be scoped to the currently executing event. Any additional bindings for a game should be done in the Firebase 'event' scope:

bind(MyContract.class).to(MyImpl.class).in(EventScoped.class);

You can register listeners for scope entry and exit events. This can be used to bind additional resources such as transaction boundaries to the thread context, you do this by adding a scope listener to the super-class. For exampel, to add a listener which is managed by Guice you'd do it in the post injector creation, list so:

@Override public void postInjectorCreation(Injector injector) { MyListener l = injector.getInstance(MyListener.class); addScopeListener(l); }

Scope listeners are notified immediately after scope entry and before scope exit.

Special Injections
The following objects are available for ordinary in a game, all in the event scope:

GameProcessor GameContext TableGameState TableMetaData GameNotifier TablePlayerSet TableScheduler TournamentNotifier TableWatcherSet Table

In addition, if you have configured a listener or interceptor or state class via the configuration, these will be injectable as wrll.

Any Firebase service can be injected (must be a service contract), using the special Service injection annotation: @Service private DatasourceServiceContract dsContract;

You can also inject a Log4j logger anywhere using the special Log4j injection annotation:

@Log4j private Logger log;

Table and Player ID
NB:  Available from Guice Support 1.3.0.

It is possible to inject the table ID separately, like so:

@Inject @Named("tableId") private int tableId;

For all methods originating from a remote player it is also possible to inject the player ID:

@Inject @Named("playerId") private int playerId;

However, it is worth noting that some invocations are not originating from any particular player, and for these instances the inserted player ID will be -1:

TournamentProcessor.startRound(Table) TournamentProcessor.stopRound(Table) GameProcessor.handle(GameObjectAction, Table)

Guice Service
NB:  Tis is for Guice Support 1.4+, for older implementations see: Guice Service < 1.4.

Creating a service using Guice is no different in implementation than normally. As usual, these are the first steps:


 * Create a Contract interface.
 * Create an implementation that extends the Contract and Service, but also ma

After this there is a difference, instead of configuring Firebase to use the implementation from #2 above, where going to go the Guice route. So:


 * Make an extension of "GuiceServiceHandler" configuring you contract and implementation classes.
 * Instead of a "service" element in the service descriptor, add a "invocation-handler" element and point it to the class name of your extension from step #3.

Quick How-To
Create an Contract interface for your service:

public interface EchoService extends Contract {

public String echo(String msg);

}

Then create an implementation that also implement Service:

@Singleton public class ServiceImpl implements Service, ExchoService {

@Override public String echo(String msg) { return msg; }

@Override public void init(ServiceContext con) throws SystemException { }

@Override public void start { }

@Override public void stop { }

@Override public void destroy { }

}

Note the "@Singleton" annotation. Your service will be mounted as a singleton automatically, but marking it explicitly might be a good idea anyway.

Now create a handler for your service, this is where the Guice magic will take place:

public class Handler extends GuiceServiceHandler {

@Override protected Configuration getConfiguration { // here we're telling Guice what classes to use return new Configuration {

@Override public ContractsConfig getServiceContract { // implementation class and contract return new ContractsConfig(ServiceImpl.class, EchoService.class); }       };    } }

If you want to register your own modules, you can override 'preInjectorCreation':

public void preInjectorCreation(ServiceContext context, List modules) { list.add(new MyServiceModule); }

Almost there, now open the "service.xml" and remove the "service" element and add this instead (with the right class name of your handler created above):

test.Handler

Done!

Special Injections
Any Firebase service can be injected (must be a service contract), via the special Service' injection annotation:

@Service private DatasourceServiceContract dsContract;

If a service is injected into another service during the initiation phase of the service life-cycle, the service must be proxied, otherwise the injection may result in a null value as the injected service may not be known:

@Service(proxy=true) private DatasourceServiceContract dsContract; You can also inject a Log4j logger anywhere using the special Log4j injection annotation:

@Log4j private Logger log;

Quick How-To
Extend GuiceTournament:

public class MyMTT extends GuiceTournament [...]

Override 'getConfigurationHelp' to return a configuraton, with your actual tournament handler class:

public Configuration getConfigurationHelp { return new Configuration {

public Class<? extends TournamentHandler> getTournamentHandlerClass { // Return the class of your implementation }   }; }

Also, if you want to register your own modules, you can override 'preInjectorCreation':

public void preInjectorCreation(List list) { list.add(new MyMttModule); }

Special Injections
To use the support methods from MTTSupport in your handler, there's an assistant interface you can inject:

@Inject private TournamentAssist mttAssist;

You can also inject a Log4j logger anywhere using the special Log4j injection annotation:

@Log4j private Logger log;

NB: Contrary to the special bindings in Games and Services there is no @Service binding available in the tounament support.