registering an InjectionListener for @PostConstruct

478 views
Skip to first unread message

James Strachan

unread,
Apr 1, 2009, 2:49:34 PM4/1/09
to google...@googlegroups.com
When using optional injection points other than just a constructor,
there's sometimes a need for a @PostConstruct callback (if nothing
else to implement JSR250/EJB3 :). e.g.

public class Cheese {
@Inject Foo foo;
@Resource bar;
@PersistentContext context;

...
@PostConstruct
public void check() {
// all injection completed here so lets setup some things or validate
}
}

currently different parts of different Modules could register
different InjectionListener implementations to process, say,
@Resource, @PersistentContext, @PostConstruct.

e.g. we might have a JSR 250 module and an EJB/JPA module which are
optional but folks could use them together if they wanted JSR 250 and
EJB.

The tricky bit is - @PostConstruct is a kinda special kind of
InjectionListener as it wants to go last after all the mutation has
completed. Currently it looks like the order is determined by the
registration order in the module right?

I wonder if there's a way to somehow denote a special kind of
InjectionListener as going last - after all the mutation listeners? So
a kind of post initialisation listener.

This isn't required for *just* JSR 250; but I'm thinking a little
ahead here - if there's a spring annotations module, an EJB3/JPA
module and a JSR 250 module - it could be slightly tricky ensuring
that the listeners are all added in the correct order.


One really simple idea is maybe the Encounter could have a method
registerPostInject(listener) which just adds the listener to separate
list to the listeners list; which is then appended to the other list
when all of the modules have been initialised? i.e. so the encounter
still passes a single list of listeners to its callers (e.g.
ConstructorInjector) - but that there's a concrete way to specify
listeners that are fired after all the other injection listeners are
fired.

It'd be a pretty minor change; as the Encounter object is shared
across all invocations of the injectable type listeners; it'd just be
a way for any 'post commit hooks' to be processed after the other
kinds of listener (which typically inject/mutate the object).

i.e. so it just adds one method to Encounter and adds one extra
(optional & lazy) list object there.

Thoughts?

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

Bob Lee

unread,
Apr 1, 2009, 3:31:48 PM4/1/09
to google...@googlegroups.com
Good point. We could also add more callback methods to the listener...

interface InjectableTypeListener {
  void inject(...);
  void afterInjection(...);
}

Bob

James Strachan

unread,
Apr 2, 2009, 2:02:20 AM4/2/09
to google...@googlegroups.com
Yeah - either works for me. I would say post injection hooks are very
rare. I can currently only think of 2 possible implementations
(@PostConstruct and supporting Spring' InitializingBean). Also they
tend to be mutually exclusive to any particular injection annotation -
eg @PostConstruct could be used with @Resource, @PersistentContext or
@Autowired (from spring). So pretty much all InjectionListener
implementations i can imagine would only implement one of the methods.

Also i think the former might be a little bit more efficient; trading
a new List lazily created which is appended to the other at class
inspection time versus avoiding a double iterate & invocation of lots
of empty methods (though hotspot would no doubt speed that up to e
barely noticable :-).

Don't mind though. Do you want a patch?

Bob Lee

unread,
Apr 2, 2009, 2:17:17 AM4/2/09
to google...@googlegroups.com
On Wed, Apr 1, 2009 at 11:02 PM, James Strachan <james.s...@gmail.com> wrote:

Yeah - either works for me. I would say post injection hooks are very
rare. I can currently only think of 2 possible implementations
(@PostConstruct and supporting Spring' InitializingBean). Also they
tend to be mutually exclusive to any particular injection annotation -
eg @PostConstruct could be used with @Resource, @PersistentContext or
@Autowired (from spring). So pretty much all InjectionListener
implementations i can imagine would only implement one of the methods.

Also i think the former might be a little bit more efficient; trading
a new List lazily created which is appended to the other at class
inspection time versus avoiding a double iterate & invocation of lots
of empty methods (though hotspot would no doubt speed that up to e
barely noticable :-).

Good points.
 
Don't mind though. Do you want a patch?

Sure!

Bob

James Strachan

unread,
Apr 2, 2009, 7:18:41 AM4/2/09
to google...@googlegroups.com
2009/4/2 Bob Lee <craz...@crazybob.org>:

Done...
http://code.google.com/p/google-guice/issues/detail?id=351

I went with the former solution for now. We might wanna rename
Encounter.register() to registerListener() or
registerInjectionListener() or something as the other method is
currently registerPostInjectListener() but I'll leave that up to you
guys to pick nicer names if you like.

There's a test case in
InjectableTypeListenerTest.testPostInjectListenersAreProcessedInOrder()
that asserts that when listeners are registered out of order; the post
inject listeners are fired last.

Reply all
Reply to author
Forward
0 new messages