Hi all,
I'm currently dealing with migrating some code from Guice to HK2, and we
are running into some troubles with circular dependencies in @Immediate
scope.
Please consider the following interfaces and implementations:
*interface* MessageHandler *{*
*}*
*interface* RepositoryClient *{*
*}*
*interface* ServiceClient *{*
*}*
*class* MessageHandlerImpl *implements* MessageHandler {
*private* RepositoryClient *handler*;
@Inject
MessageHandlerImpl(RepositoryClient handler) {
*this*.handler = handler;
}
}
*class* RepositoryClientImpl *implements* RepositoryClient {
*private* ServiceClient *client*;
@Inject
*public* RepositoryClientImpl(ServiceClient client) {
*this*.client = client;
}
}
*class* ServiceClientImpl *implements* ServiceClient {
*private* MessageHandler *handler*;
@Inject
*void* registerHandler(MessageHandler *handler*) {
*this*.handler = handler;
}
}
In particular, please note that there is effectively a circular dependency
between the three implementation glasses. Not good, definitely a code
smell, but also not the end of the world, and, for purposes of this
discussion, let's just say it cannot easily be avoided.
In the existing Guice code, there are no problems with instantiating the
classes. Guice figures out the correct order to instantiate the classes and
to break the cycle; no proxies or other trickery are involved under the
hood, AFAICT.
To translate the Guice code to HK2, we replaced .asEagerSingletion() with
.in(Immediate.class). It is my understanding that this is HK2's closest
equivalent of eager singletons.
Now, if we try to instantiate the objects with HK2, we run into a deadlock
inside the ImmediateHelper class. The following JUnit test demonstrates the
issue; Guice produces the correct object graph, whereas HK2 times out:
*import* org.glassfish.hk2.api.Immediate;
*import* org.glassfish.hk2.api.ServiceLocator;
*import* org.glassfish.hk2.utilities.ServiceLocatorUtilities;
*import* org.glassfish.hk2.utilities.binding.AbstractBinder;
*import* org.junit.Test;
*import* com.google.inject.AbstractModule;
*import* com.google.inject.Guice;
*import* com.google.inject.Injector;
*import* *static* org.junit.Assert.*assertNotNull*;
*public* *class* CircularDependencyInjectionHK2vsGuice {
@Test(timeout=5000)
*public* *void* testHK2Immediate() {
ServiceLocator serviceLocator = ServiceLocatorUtilities.
*createAndPopulateServiceLocator*();
ServiceLocatorUtilities.*enableImmediateScope*(serviceLocator
);
AbstractBinder binder = *new* AbstractBinder() {
@Override
*protected* *void* configure() {
bind(ServiceClientImpl.*class*).to(ServiceClient.
*class*).in(Immediate.*class*);
bind(MessageHandlerImpl.*class*
).to(MessageHandler.*class*).in(Immediate.*class*);
bind(RepositoryClientImpl.*class*
).to(RepositoryClient.*class*);
}
};
ServiceLocatorUtilities.*bind*(serviceLocator, binder);
MessageHandler messageHandler = serviceLocator
.getService(MessageHandler.*class*);
ServiceClient serviceClient = serviceLocator
.getService(ServiceClient.*class*);
*assertNotNull*(messageHandler);
*assertNotNull*(serviceClient);
}
@Test(timeout=5000)
*public* *void* testGuiceEagerSingleton() {
AbstractModule module = *new* AbstractModule() {
@Override
*protected* *void* configure() {
bind(ServiceClient.*class*).to(ServiceClientImpl.
*class*).asEagerSingleton();
bind(MessageHandler.*class*
).to(MessageHandlerImpl.*class*).asEagerSingleton();
bind(RepositoryClient.*class*
).to(RepositoryClientImpl.*class*);
}
};
Injector injector = Guice.*createInjector*(module);
MessageHandler messageHandler = injector
.getInstance(MessageHandler.*class*);
ServiceClient serviceClient = injector
.getInstance(ServiceClient.*class*);
*assertNotNull*(messageHandler);
*assertNotNull*(serviceClient);
}
}
Is this a bug in HK2's Immediate resolution code? Should I file a JIRA
issue?
Or am I doing something else wrong that sends HK2 into a deadlock?
Thanks,
Mirko
--
This email and any attachments may contain information which is
confidential and/or privileged. The information is intended exclusively for
the addressee and the views expressed may not be official policy, but the
personal views of the originator. If you are not the intended recipient, be
aware that any disclosure, copying, distribution or use of the contents is
prohibited. If you have received this email and any file transmitted with
it in error, please notify the sender by telephone or return email
immediately and delete the material from your computer. Internet
communications are not secure and Lab49 is not responsible for their abuse
by third parties, nor for any alteration or corruption in transmission, nor
for any damage or loss caused by any virus or other defect. Lab49 accepts
no liability or responsibility arising out of or in any way connected to
this email.