unexpected injections with "No implementation..." exception

3,262 views
Skip to first unread message

yurique

unread,
May 14, 2010, 12:31:30 AM5/14/10
to google-guice
Hi!

I've faced the following problem.

I am using Guice within OSGI (though I'm not sure if it is relevant to
the problem itself).

I have one bundle - Persister, within it I configure Guice and then
inject members like this:

Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
install(PersistenceModule.create("SOME_PERSISTENCE_UNIT"));
}
}).injectMembers(this);

PersistenceModule.create() initializes a module for warp-persist and
returns it. Actually, this code works just fine - everything gets
injected correctly.

This bundle then exports this guice-initialized object as an OSGI
service ("Persister").

Another bundle (Client) uses this service. First it is passed with a
"Persister" service instance:

protected void setPersister(Persister persister) {
this.persister = persister;
}

This works fine as well. After that the Client is activated:

protected void activate(ComponentContext context) {
Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Persister.class).toInstance(this.persister); //
this.persister is initialized earlier by the setter method mentioned
above
}
}).injectMembers(this);
}

injectMembers() initialized needed fields, and some of them in turn
have fields like this:

@Inject
private Persister persister;

I expected that those fields would just be set according to the
"bind(Persister.class).toInstance(this.persister)" configuration
instruction. But instead I get exceptions like the following:

1) No implementation for javax.persistence.EntityManager was bound.
while locating
com.google.inject.Provider<javax.persistence.EntityManager>
for field at persister.impl.RequestDAO.em(RequestDAO.java:15)
while locating persister.impl.RequestDAO
for field at
persister.impl.PersisterComponent.requestDAO(PersisterComponent.java:
42)
at client.ClientComponent$1.configure(ClientComponent.java:47)

2) No implementation for javax.persistence.EntityManager was bound.
while locating
com.google.inject.Provider<javax.persistence.EntityManager>
for field at persister.impl.ResponseDAO.em(ResponseDAO.java:15)
while locating persister.impl.ResponseDAO
for field at
persister.impl.PersisterComponent.responseDAO(PersisterComponent.java:
41)
at client.ClientComponent$1.configure

2 errors
at
com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:
354)
at
com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:
152)
at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105)
at com.google.inject.Guice.createInjector(Guice.java:92)
at com.google.inject.Guice.createInjector(Guice.java:69)
at com.google.inject.Guice.createInjector(Guice.java:59)
at client.ClientComponent.activate
... 36 more

I can't figure out what Guice is trying to do. Why would it need
bindings for EntityManager which is only referenced by objects that
are already successfully built before (using a different module)?

P.S. I'll try to summarize the above:

[Persister bundle]: configure-guice, inject members, export built
object as a service (works fine)
[Client bundle]: consume the above service, save it to a field (ok),
configure guice and bind Persister.class to that object, create an
injector - fails

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Sam Berlin

unread,
May 14, 2010, 6:09:03 PM5/14/10
to google...@googlegroups.com
A wild guess... does the class "this.persister" refers to have any methods or fields annotated with @Inject?  Guice is probably trying to Inject them.  Without thinking too much about the relative merits of this design, one possible workaround is to bind it using bind(Persister.class).toProvider(Providers.of(this.persister)).

sam

yurique

unread,
May 15, 2010, 6:35:18 PM5/15/10
to google-guice
> does the class "this.persister" refers to have any methods
or fields annotated with @Inject?

Yes, this object is built with guice within another module of an
application and has fields annotated with @Inject.

> Guice is probably trying to Inject them.

Thats what it seems to me, too. But I can't find a reason for it to do
so - the object is already built and bound using "toInstance".

Does this mean, that one cannot bind objects built by Guice (with
different Module and bindings)? This doesn't seem right to me.

I've just created a simple test project.

I have the following classes within it:

ITool - a simple interface
SpecificTool - some implementation of that interface

IService - another interface
SpecificService - a service that uses an ITool interface (@Inject
private ITool tool)

Client - a simple class, that uses an IService (@Inject private
IService service)


Here's what I do in the test:
* I create one AbstractModule - with bindings for ITest and for
IService
* create an injector using that module and create an instance of
IService (actually an instance of SpecificService)

Then I create another AbstractModule (and injector) in which I bind
the IService.class to the created object using
bind(...).toInstance(...). This module doesn't "know" about ITool.
Now using this new injector I try to create an instance of Client,
which has an injected IService field. And Guice fails complaining that
ITool is not bound.

But at this moment Guice has everything needed to successfully build
Client - because IService is already bound to an *existing* instance.

Yuriy Malchenko

unread,
May 15, 2010, 6:35:43 PM5/15/10
to google...@googlegroups.com
I'll try to attach this test project.
guice-test.zip

Sam Berlin

unread,
May 15, 2010, 6:36:11 PM5/15/10
to google...@googlegroups.com
Did you try the workaround?

yurique

unread,
May 15, 2010, 6:39:09 PM5/15/10
to google-guice
I just did - it seems to work.

Stuart McCulloch

unread,
May 15, 2010, 11:29:12 PM5/15/10
to google...@googlegroups.com
On 16 May 2010 06:35, yurique <jmalc...@gmail.com> wrote:
> does the class "this.persister" refers to have any methods
or fields annotated with @Inject?

Yes, this object is built with guice within another module of an
application and has fields annotated with @Inject.

> Guice is probably trying to Inject them.

Thats what it seems to me, too. But I can't find a reason for it to do
so - the object is already built and bound using "toInstance".

Does this mean, that one cannot bind objects built by Guice (with
different Module and bindings)? This doesn't seem right to me.



--
Cheers, Stuart

Yuriy Malchenko

unread,
May 16, 2010, 4:41:31 PM5/16/10
to google...@googlegroups.com
Stuart, thanks for clearing this out!
Reply all
Reply to author
Forward
0 new messages