Tag Archives: guice

Extending Guice

Guice is a framework that I had been looking forward to trying out for a while, but until recently I never had the opportunity.  Previously I had mostly used Spring (with a dash of PicoContainer), so when I got the opportunity to start using Guice, I naturally had a number of my favourite Spring features in mind as I started using it.  Very quickly I found myself wanting an equivalent of Springs DisposableBean.  Guice is focussed on doing one thing and doing it well, and that thing is dependency injection.  Lifecycle management doesn’t really come into that, so I am not surprised that Guice doesn’t offer native support for disposing of beans.  There is one Guice extension out there, Guiceyfruit, that does offer reasonably complete per scope lifecycle support, however Guiceyfruit requires using a fork of Guice, which didn’t particularly appeal to me.  Besides, Guice is very simple, so I imagined that providing my own simple extensions to it would also be simple.  I was right.

Though, to be honest, while the extensions themselves are simple, it wasn’t that simple to work out how to write them.  On my first attempt, I gave up after Googling and trying things out myself for an hour.  On my second attempt, I almost gave up with this tweet.  But, I stuck with it, and eventually made my breakthrough. The answer was in InjectionListener. This listener is called on every component that Guice manages, including both components that Guice instantiates itself, and components that are provided as instances to Guice.

Supporting Disposables

So, I had my disposable interface:

public interface Disposable {
  void dispose();
}

and I wanted any component that implemented this interface to have their dispose() method called when my application shut down.  Naturally I had to maintain a list of components to dispose of:

final List<Disposable> disposables = Collections.synchronizedList(new ArrayList());

Thread safety must be taken into consideration, but since I only expected this list to be accessed when my application was starting up and shutting down, a simple synchronized list was suffcient, no need to worry about performant concurrent access.

My InjectionListener is very simple, it just adds disposables to this list after they’ve been injected:

final InjectionListener injectionListener = new InjectionListener<Disposable>() {
  public void afterInjection(Disposable injectee) {
    disposables.add(injectee);
  }
};

InjectionListener‘s are registered by registering a TypeListener that listens for events on types that Guice encounters.  My type listener checks if the type is Disposable (this actually isn’t necessary because we will register it using a matcher that matches only Disposable types, but it is defensive to do the check), and if so registers the InjectionListener:

TypeListener disposableListener = new TypeListener {
  public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
    if (Disposable.class.isAssignableFrom(type.getRawType())) {
      TypeEncounter<Disposable> disposableEncounter = (TypeEncounter<Disposable>) encounter;
      disposableEncounter.register(injectionListener);
    }
  }
}

Now I can register my TypeListener.  This is done from a module:

bindListener(new AbstractMatcher<TypeLiteral<?>>() {
      public boolean matches(TypeLiteral<?> typeLiteral) {
        return Disposable.class.isAssignableFrom(typeLiteral.getRawType());
      }
    }, disposableListener);

The last thing I need to do is bind my collection of disposables, so that when my app shuts down, I can dispose of them:

bind((TypeLiteral) TypeLiteral.get(Types.listOf(Disposable.class)))
                .toInstance(disposables);

So now when my app shuts down, I can look up the list of disposables and dispose of them:

for (Disposable disposable : ((List<Disposable>) injector.getInstance(
    Key.get(Types.listOf(Disposable.class)))) {
  disposable.dispose();
}

If you decide to use this code in your own app, please be very wary of a potential memory leak. Any beans that are not singleton scoped will be added to the disposable list each time they are requested (per scope).  For my purposes, all my beans that required being disposed of were singleton scoped, so I didn’t have to worry about this.

Supporting annotation based method invocation scheduling

Happy that I now had a very simple extension with very little code for supporting automatic disposing of beans, I decided to try something a little more complex… scheduling. My app contains a number of simple scheduled tasks, and the amount of boilerplate for scheduling each of these was too much for my liking. My aim was to able to do something like this:

@Schedule(delay = 5L, timeUnit = TimeUnit.MINUTES, initialDelay = 1L)
def cleanUpExpiredData() {
  ...
}

(Yep, this app has a mixture of Scala and Java.) So, I started with my annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedule {
    long delay();
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
    long initialDelay() default 0;
}

The main difference this time is that I’m not listening for events on a particular type, but rather I want to check all types to see if they have a @Schedule annotated method. This is a little more involved, so I’m going to have a scheduler service that does this checking and the scheduling. Additionally it will make use of the disposable support that I just implemented:

public class SchedulerService implements Disposable {
  private final ScheduledExcecutorService executor = Executors.newSingleThreadScheduledExecutor();

  public boolean hasScheduledMethod(Class clazz) {
    for (Method method : clazz.getMethods()) {
      Schedule schedule = method.getAnnotation(Schedule.class);
      if (schedule != null) {
        return true;
      }
    }
    return false;
  }

  public void schedule(Object target) {
    for (final Method method : target.getClass().getMethods()) {
      Schedule schedule = method.getAnnotation(Schedule.class);
      if (schedule != null) {
        schedule(target, method, schedule);
      }
    }
  }

  private void schedule(final Object target, final Method method, Schedule schedule) {
    executor.scheduleWithFixedDelay(new Runnable() {
      public void run() {
        method.invoke(target);
      }, schedule.initialDelay(), schedule.delay(), schedule.timeUnit());
  }

  public void dispose() {
    executor.shutdown();
  }
}

Now in my module I instantiate one of these services:

final SchedulerService schedulerService = new SchedulerService();

I then implement my InjectionListener:

final InjectionListener injectionListener = new InjectionListener() {
  public void afterInjection(Object injectee) {
    schedulerService.schedule(injectee);
  }
}

and my TypeListener:

TypeListener typeListener = new TypeListener() {
  public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
    if (schedulerService.hasScheduledMethod(type.getRawType()))  {
      encounter.register(injectionListener);
    }
  }
}

And then all I have to do is register my type listener, and also my scheduler service (so that it gets disposed properly):

  bindListener(Matchers.any(), typeListener);
  bind(SchedulerService.class).toInstance(schedulerService);

Conclusion

Although Guice doesn’t come with as much as Spring does out of the box, it is very simple to extend to meet your own requirements. If I were needing many more container like features, then maybe Spring would be a better tool for the job, but when I’m just after a dependency injection framework with a little sugar on top, Guice is a very nice and much lighter weight solution.