Hi Sam,
> Can you expand a little more on what you're using your TypeListener &
> InjectionListener for? TypeListener doesn't work so well for knowing
> what objects will be bound -- it misses things like scope that can be
> set in the module (and not on the class). InjectionListener also
> doesn't work very well -- it only notifies about objects that are
> injected, not objects that are bound (but not yet injected).
Thank you for trying to help me on this problem.
In more details, GUTS-Events needs to process ALL Guice injected
instances, in search of methods with @Consumes annotation (which marks
an event consumer method), then it adds these methods as event listeners
to the right events providers (I simplify a bit but that's mainly it).
I was thus looking for a way to be notified immediately after Guice
injects some instance of any class which has those @Consumes annotated
methods, this includes classes instances that are created by Guice and
also instances that were created outside Guice but injected (field- and
method-, not constructor-injected of course) by Guice.
Here is the code I use in GUTS-Events (it's more complex than the
original test case, but this is only to show my complete use case):
final public class EventModule extends AbstractModule
{
@Override protected void configure()
{
// Make sure @Consumes annotation get automatically processed for
// any instance created by Guice
ConsumerInjectionListener injectionListener = new
ConsumerInjectionListener();
//FIXME injection of injectionListener may happen too late and
throw NPE!
requestInjection(injectionListener);
ConsumerTypeListener typeListener = new
ConsumerTypeListener(injectionListener);
bindListener(Matchers.consumer(), typeListener);
...
}
}
public class ConsumerInjectionListener implements InjectionListener<Object>
{
@Inject public void setEventService(EventService service)
{
_service = service;
}
public void afterInjection(Object injectee)
{
_service.registerConsumers(injectee);
}
private EventService _service = null;
}
public class ConsumerTypeListener implements TypeListener
{
public ConsumerTypeListener(InjectionListener<Object> injectionListener)
{
_injectionListener = injectionListener;
}
public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter)
{
encounter.register(_injectionListener);
}
final private InjectionListener<Object> _injectionListener;
}
public final class Matchers
{
static final public Matcher<TypeLiteral<?>> consumer()
{
return new AbstractMatcher<TypeLiteral<?>>()
{
public boolean matches(TypeLiteral<?> type)
{
for (Method m: type.getRawType().getMethods())
{
if (m.isAnnotationPresent(Consumes.class))
{
return true;
}
}
return false;
}
};
}
}
In the classes above, I use Matchers.consumer() method to filter the
classes which instances have to be processed (only classes with
@Consumes methods).
Then the ConsumerTypeListener is called for all those classes and
register for them an ConsumerInjectionListener instance, which will be
called for all injected instances of these classes.
This is in this ConsumerInjectionListener that the EventService
"_service" member was not injected before afterInjection() being called.
As I mentioned in my original mail, on some occasions it works , on some
(described in my first mail) it doesn't; in the actual code above, I
have an NPE on CustomerInjectionListener.afterInjection() method
(because _service was not injected yet and thus is null)
I don't see why scope would be important here, I expect my
InjectionListener called for all instances created/injected by Guice,
whatever their scope.
> It sounds like you may be looking for something like a binding
> listener. See patch # 387 @
> http://code.google.com/p/google-guice/issues/detail?id=387 .
I have just checked the description and I don't see how it could help
solve my problem.
If there was an RFE to submit for solving that problem, I think that
would be something like:
"Have Guice inject bound TypeListener instances as for any other
"normal" bindings; and make sure TypeListener injection is performed
with top-priority."
Of course, this could open a Pandora box because of potential circular
dependencies, but I'm not sure these could be that serious.
Well I am still stuck with this issue; I have checked several
possibilities, and the only solution I see so far would be to create my
EventService impl "by hand" and pass it to my ConsumerInjectionListener
instance. But that would be a pain in the neck (because of all deps it
has, all managed by Guice), I'm not even sure that would really be feasible.
Cheers
Jean-Francois
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en
-~----------~----~----~----~------~----~------~--~---