Spring #Qualifer not working with Bean implementing multiple interface - java

I have a bean which implements two interfaces. Below is my code-
#Qualifier("A")
interface InterfaceA {
method a()
}
#Qualifier("B")
interface InterfaceB {
method b()
}
public class ClassC implements InterfaceA, InterfaceB {
method a(){}
method b(){}
}
When I inject my bean in some other class, say
public class MyClass {
#Autowired
#Qualifier("A")
private InterfaceA a;
#Autowired
#Qualifier("B")
private InterfaceA b;
}
I get below error whether I use Qualifier or not
UnsatisfiedDependencyException: Error creating bean with name a... nosuchbeandefinitionexception

By using the #Qualifier annotation, we can eliminate the issue of which bean needs to be injected. So it is used with #Component annotation above classes, not interfaces.
In your case, you have just one class ClassC that implements two interfaces InterfaceA and InterfaceB.
So to resolve the issue, you need to add #Component to ClassC:
#Component
public class ClassC implements InterfaceA, InterfaceB {
method a(){}
method b(){}
}
And finally, you should remove all #Qualifier annotations, from MyClass and InterfaceA and InterfaceB.
Take look at this to know more about how to use #Qualifier.

#Component is missing on your class C. Also make sure your component scan covers the package in which class C is present.

Related

Autowire a specific bean given a profile

I have 2 classes implementing InterfaceA
#Service("classA")
class ClassA implements InterfaceA
#Service("classB")
class ClassB implements InterfaceA
I need to load both beans. In class C and D, though, I need to specify the bean that I need
class ClassC {
#Autowired
#Qualifier("classA")
private InterfaceA interf;
}
class ClassD {
#Autowired
#Qualifier("classA")
private InterfaceA interf;
}
However, I have 2 profiles, profile1 and profile2. If i use -Dspring.profiles.active=profile1, I should be using qualifier "classA" for classC and classD. If i use -Dspring.profiles.active=profile2, I should use "classB" as qualifier. Also, another ClassE should always use classB regardless of the profile. Can you please advise how should I do it?
So this is how I did it. I created a configuration class
#Configuration
public class ConfigClass {
#Autowired
private ClassB classB;
#Profile("profile1")
#Qualifier("myclass")
#Bean
private InterfaceA classAtProfile1() {return new ClassA();}
#Profile("profile2")
#Qualifier("myclass")
#Bean
private InterfaceA classAtProfile2() {return classB;}
}
class ClassA implements InterfaceA
#Service("classB")
class ClassB implements InterfaceA
This way, I can autowire InterfaceA based on profile
#Autowired
#Qualifier("myclass")
private InterfaceA myclass;
While ClassE can still refer to classB
#Component
public class ClassE {
#Autowired
ClassB classB;
...
}
Define 2 configuration java files:
class ClassA implements InterfaceA
class ClassB implements InterfaceA
Sample config file 1:
Profile1Config.java
#Configuration
#Profile("profile1")
public class Profile1Config {
#Bean
public InterfaceA interfaceA() {
return new ClassA();
}
}
Sample config file 2:
Profile1Config.java
#Configuration
#Profile("profile2")
public class Profile2Config {
#Bean
public InterfaceA interfaceA() {
return new ClassB();
}
}
And wherever you want to use this:
class ClassC {
#Autowired
private InterfaceA interf;
}
class ClassD {
#Autowired
private InterfaceA interf;
}
Key point to note:
1. #Qualifier was not required.
2. #Profile is mentioned at the Java Configuration class.
3. #Service was removed from classA and classB rather defined in Config* classes now.

autowire null in the abstract class

I had an issue to autowire an object in my abstract base class. It always give me null instead of an instance. Please help.
Base class:
public abstract class BaseClass implements IReq<Req> {
#Autowired
protected ReqDao dao;
protected void updateReq() {
dao.update();
}
}
Child class:
#Component
public class ChildClass extends BaseClass {
...
}
ReqDao class:
#Component
public class RptRequestDao {
public void update(){
...
}
}
I am thinking of simply use the update() function in Base class, which means in my ChildClass, I don't override that one. Is this the problem? If it is, what's the normal way to do it? Thanks in advance.
A bean is created on demand, in your case when you initialize your object,
RepoDao is private so it wont be inhereted to the class which will be intialized, you either need to put
#Component
public class ChildClass extends BaseClass {
#Autowired
private ReqDao dao;
or make it protected/public in BaseClass, sure public will make it accessible to other classes which violates the encapsulation
Instantiate your child class using #Autowired like this
public class SomeClass{
#Autowired
ChildClass childClass; //IMPORTANT
}
The error occurs when you try to instantiate the childClass like this:
public class SomeClass{
ChildClass childClass = new ChildClass();
}
BaseClass is abstract you can't instantiate it.You need to have your ReqDao in ChildClass to be autowired.Spring will only autowire when it will create an instance of that class.Hope that helps
Check how you are instantiating the child class. Make sure you are NOT using "new" keyword to instantiate child class.
ChildClass cc = new ChildClass() // **Not recommended**
You must autowire the childclass and let spring take care of bean creation.

Spring autowire priority with more than two layers

How am I able to override an autowired bean more than once? Consider this 3-layer construct:
Library 1 defines an interface and a default implementation.
public interface Foo {}
#Component
public class FooImpl1 implements Foo {}
Throughout all 3 layers the interface will be used for autowiring.
#Autowired
private Foo foo;
Library 2 depends on library 1 and provides its own implementation which has to override the first one, i.e. be autowired into existing code of library 1.
#Component
public class FooImpl2 implements Foo {}
The actual application depends on library 2 and also provides another implementation that has to override the former one.
#Component
public class FooImpl3 implements Foo {}
How do I configure this? If there were only two layers, I could use #Primary but this doesn't work with more than two layers because #Primary can't be overriden again. Is there a more fine-grained way of prioritizing beans that I'm overlooking or can I accomplish a second override using a #Configuration or do you simply can not overide a bean more than once and I have to resort to some kind of static helper like FooProvider.getFoo() instead of autowiring?
Maybe is not the case, however when you have more than one implementation and want to establish some kind of ordination, existe the annotation #order
#order(3)
#Component
public class FooImpl1 implements Foo {}
#order(1)
#Component
public class FooImpl2 implements Foo {}
#order(2)
#Component
public class FooImpl3 implements Foo {}
public class PrintFoo {
List<Foo> fooList;
#autowired
public PrintFoo() {
for(Foo fooImpl: fooList) {
System.out.println(fooImpl.getClass().getSimpleName());
}
}
the output should be:
FooImpl2
FooImpl3
FooImpl1

Create instance of call with autowire

I have to create a instance of a class, that have autowired elements, for test.
public class MyClass extends SomeOtherClass {
#Autowired
public MyClass(OtherClass1 one, OtherClass2 two){
super(one, two)
}
}
How can i in code create instance of this class, with the arguments wired in though spring?
Your test can be made Spring-aware if you use the SpringJUnit4ClassRunner to read in your Spring Context to be used in the test. For instance:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"the-config.xml"})
public final class MyClassTests {
#Autowired
private MyClass testee;
#Test
public void testSomething() {
assertThat(testee).doesSomethingExpected();
}
}
Note that you should reuse as much of your production config as possible and not create a parallel Spring Context config that mirrors it.
Instead of passing the other elements in as constructor arguments, you Autowire them as properties. Spring will then inject the objects.
public class MyClass extends SomeOtherClass {
#Autowired
private OtherClass1 one;
#Autowired
private OtherClass2 two
public MyClass(){
super(one, two)
}
}
Edit: Based on http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/, adding #Autowired to the constructor is also valid.
If you want to Autowire MyClass, you must annotate it with #Component or a similar annotation such as #Service.
#Component
public class MyClass extends SomeOtherClass
Then, you can use it in other classes
public class ClassThatUsesMyClass {
#Autowire
private MyClass myClass;
}

EJB3 instantiation

I got some propably trivial question.
If I got defined EJB3+ interface, lets say it's remote like that:
#Remote
public class FooServiceRemote {
void foo();
}
and one implementation
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
How does the application server by default resolves what implementation to use (and call via proxy) if he knows only #EJB annotation for dependency injection like on interface:
public class SomeClass {
#EJB
private FooServiceRemote fooService;
}
Is it done by reflection (shortening name of interface)? Or he scans possible implementations of such interface, choosing one. Or.. ? And what if I want to create more implementations of one interface, is it possible and how to specify what implementation should be instantiated (maybe it is possible via some argument of annotation).
Thanks:-)
In the rare case that you need to have two beans implementing the same interface (not a good practice), you can name them and choose which one you want by name.
#Stateless(name="FooService1")
public class FooService1 implements FooService { }
#Stateless(name="FooService2")
public class FooService2 implements FooService { }
public class SomeClass {
#EJB(beanName="FooService1")
private FooService fooService;
}
Other possible approaches are looking it up using JNDI or the mappedName property.
See the javadoc for EJB annotation here: http://download.oracle.com/javaee/6/api/javax/ejb/EJB.html
Just a fix,
#Remote
interface FooServiceRemote {
void foo();
}
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
With this, application server knows which classes implements the specified interface.
If you have two classes, you must specifify which class do you need.

Categories

Resources