I get the following error from dagger:
[ERROR] error on execute: java.lang.IllegalArgumentException: Unexpected key: ca.nanometrics.apollo.instrument.configuration.ResourceOwnerController<>
I believe this happens because I have a class with no injectable dependencies - it has an empty public constructor (with #Inject), with nothing to inject in members either. I did this to not have to declare the #Provides for it. Note that the class with the #Inject is a subclass of the class listed in the error message above:
public class ResourceOwnerControllerHelios extends ResourceOwnerController<ResourceOwnerFactoryHelios>
{
#Inject
public ResourceOwnerControllerHelios()
{
// do nothing
}
Is this a bug in dagger, or is there something I am missing?
If I remove the #Inject and still don't add the #Provides to the module, it of course doesn't work at all, since dagger needs #Inject or #Provides on all dependencies.
Oi - this looks like its' bumping into a mishandling of generics. :/ Maybe file an issue on github. What you're doing should work - that is, adding #Inject to a no-args public constructor. I believe Dagger is trying to climb the inheritance hierarchy and not handling the generics in the parent. We should be handling this case.
Related
My setup is like this
interface ServiceProvider {...}
#Singleton
class ServiceProviderImpl implements ServiceProvider {...}
class ServiceConsumer {
#Inject
ServiceConsumer(ServiceProvider prov) {...}
}
Unfortunately, this doesn't work as it claims there are no providers for ServiceProvider, even though there is one for subclass ServiceProviderImpl.
I get
error: [Dagger/MissingBinding] c.b.d.s.ServiceProvider cannot be provided without an #Provides-annotated method.
I can fix this by adding the following to the module
#Provides
#Singleton
ServiceProvider serviceProvider(ServiceProviderImpl impl) {return impl;}
Is this by design, or am I doing something wrong?
This is by design. Dagger makes no assumptions about what implementation of an interface to use without you specifying it somewhere.
For binding an implementation for an interface you should use #Binds, though, which is an optimized version of #Provides for implementation -> interface bindings.
#Binds
#Singleton
ServiceProvider serviceProvider(ServiceProviderImpl impl);
So, is it not recommended using an inheritance-approach when implementing Grails services? I went through a simple service specialization pattern understanding that all would work in a transparent way, but I started to go into trouble regarding transaction management under the spring/grails hood. Issues happen when a method from the specialized class calls a method from the inherited class (both concrete services themselves):
#Transactional
public class MammalService {
public mammalMethod() {
}
}
#Transactional
public class DogService extends MammalService {
public dogMethod() {
mammmalMethod()
}
}
It comes that when the inherited method is called from the specialized one, org.springframework.transaction.support.GrailsTransactionTemplate() constructor is fired (by the spring/grails transaction AOP) with a null transactionManager argument, which causes some NullPointerException moreover.
Has anyone used such approach with services? Am I missing something?
PS: Curiously, I tried changing the #grails.transaction.Transactional annotation by the #org.springframework.transaction.annotation.Transactional and the NullPointerException ceased from happening. (Nevertheless, it didn't point to a nice solution, since other side effects started to happen with my pool management).
UPDATE1: While debugging, I can see TWO variables with the same name transactionManager inside my specialized service (something that doesn't happen when inspecting the concrete superclass).
I'm opening a more specific issue at Duplicated transactionManager property in Grails service
Solved by removing #Transaction from specialized service classes and
methods, keeping them only on the inherited service class and its methods.
#Transactional
public class MammalService {
#Transactional(readonly=true)
public mammalMethod() {
}
}
//Don't annotate with #Transactional - rely on the super class declaration
public class DogService extends MammalService {
//Don't annotate with #Transactional - rely on the super class transactional declaration
public dogMethod() {
mammmalMethod()
}
}
It seems that, for specialized service classes, the transaction routines try to re-inject the transactionManager attribute, resulting in two attributes with the same name and one of them null. Also, annotating overrided methods raises an StackOverflowException.
I am not sure whether I understood the exact way of how these two does the injection using #Inject,but I recently developed an app where during the first phase of development I used Dependency Injection using #inject of HK2 and binded the resources using abstract binder,it worked fine.Then I wanted to inject one more value. I needed to inject a basic String values using #Inject and the value for this was got form a method annotated with #Produces.But when I do that I get this error.
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String
I read in many places and many suggest CDI and HK2 have some issues working together.I am not able to resolve the issue.
When I try the above scenario in two different standalone programs they run fine.But when I integrate them I get the above error message.
This is what I found in java's jira:
https://java.net/jira/browse/GLASSFISH-20597
My example is:
public ClassA{
#Inject
ClassBInter b;
}
I binded the class b in the abstract binder
new AbstractBinder(){
#Override
protected void configure() {
//Binding the implementation to the interface
bind(ClassBImpl.class).to(ClassBInter.class);
}
}
this worked fine.
but when I tried the below concept of adding an #Inject to a String in the same system,it crashes with the above exception
public ClassC{
#Inject
String name;
}
Producer Class
public ProducerClass{
#Produces
public String getName(){
return "henry Ford";
}
}
String injection is generally not supported, across the board. You can use qualifiers, which should help with resolution.
Do you have a beans.xml file in your deployment?
I am trying dagger in one of my projects and i am experiencing this situation:
"Field injection only works if I declare the class as an entry point in the module definition."
Is this the correct behaviour?
The below dependencies are not injected to Messenger class if Messenger.class is not declared as an entry point. Constructor injector works fine but I don't want to declare a multi parameter constructor.
public class Messenger implements NetworkInterfaceListener {
#Inject public NetworkInterface networkInterface;
#Inject public MessageFactoryInterface messageFactory;
#Inject public Bus bus;
#Inject public Logger log;
...
...
}
You have only two alternatives: either to declare injectable constructor with all params to be injected or enlist class into entryPoints (now called injects) of your dagger module and call mGraph.inject(this) in default constructor (or whenever you need to actually "inject" maybe even outside the class).
I'm using a Ninject module to bind different types to their corresponding interfaces.
Injection will take place inside a class's constructor. The problem is that the class has another constructor with a signature including Func.
Ninject is confused and throws this at me:
Error activating ClassTest using implicit self-binding of ClassTest. Several constructors have the same priority. Please specify the constructor using ToConstructor syntax or add an Inject attribute.
See below how the binding is done and how I do the injection:
this.Bind<InterfaceA>().To<ClassA>();
...
public class ClassTest
{
public ClassTest(InterfaceA a)
{
}
public ClassTest(Func<ClassB> funcB)
{
}
}
...
var giveMeTest = kernel.Get<ClassTest>(); // exception thrown
}
It seems that Func is the culprit here, can you please explain me why Ninject gets confused?
Thanks
Best you delete all unused constructors. There is no reason for adding constructors that are never used. If you really need multiple constructors then you have to tell Ninject which one to pick, e.g.:
Bind<ClassTest>().ToConstructor(x => new ClassTest(x.Inject<InterfaceA>())).Named("A");
Bind<ClassTest>().ToConstructor(x => new ClassTest(x.Inject<Func<ClassB>>())).Named("B");
kernel.Get<ClassTest>("A");
kernel.Get<ClassTest>("B");