autowire null in the abstract class - java

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.

Related

Spring #Qualifer not working with Bean implementing multiple interface

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.

Inject a field in Abstract Class using Guice

I have an abstract class, which has many classes extending it. The abstract class has a field used by all the child classes. The field needs to be injected using guice.
public abstract class StrategyClass {
#Inject
ClassTobeInjected variableName;
}
I have a provider written for injecting this, which has a provider and a singleton:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
final AppConfigBinder appConfigBinder = new AppConfigBinder(binder());
appConfigBinder.bindPrefix("*");
}
#Provider
#Singleton
public ClassTobeInjected getfield() {
return new Instance of ClassTobeInjected;
}
}
I see that the provider is creating an instance. However the abstract class field is always null. Do I need to add anything in the configure of my module? Is there something I am missing?

Changing a class annotated #Component to #Bean annotated method

I have a class that is annotated #Component that was then #Autowired into another class. However, I need to remove this #Component annotation and instead, create it with an #Bean annotated method in the class where its was previously autowired.
Where previously the classes looked like:
#Component
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Autowired
private IMyClass myClass;
private void methodUsingMyClass()
{
myClass.doStuff();
}
}
So now I have removed the #Component annotation and written a #Bean annotated method like this:
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Bean
public IMyClass getMyClass()
{
return new MyClass();
}
....
}
My question is around replacing the previous call of myClass.doStuff() to use the new bean. Do I now pass in a parameter of type MyClass to the private method:
private void methodUsingMyClass(final MyClass myClass)
{
myClass.doStuff();
}
... or do I call this method directly (doesn't seem the correct way to me):
private void methodUsingMyClass()
{
getMyClass().doStuff();
}
... or are neither of these correct?
I think you misunderstand the #Bean annotation. It can be used to create a Bean. So basically spring will scan all classes, will find your #Bean and create a Bean, not more. You can now use this bean, like if you would use one created with <bean></bean>. To actually use the bean you need to either get it from ApplicationContext or #Autowire it. Of course you can still use that function like any other function in your code, to create a new instance of that object, but that would contradict to what you want to achieve with beans
Using Annotations that solutions
public class MyClass implements IMyClass{
private OtherClassInjection otherClassInjection;
private OtherClassInjection2 otherClassInjection2;
MyClass(OtherClassInjection otherClassInjection, OtherClassInjection2 otherClassInjection2){
this.otherClassInjection=otherClassInjection;
this.otherClassInjection2=otherClassInjection2;
}
public void useObject(){
otherClassInjection.user();
}
}
#Bean(name = "myClass")
#Autowired
#Scope("prototype") //Define scope as needed
public MyClass getMyClass(#Qualifier("otherClassInjection") OtherClassInjection otherClassInjection,
OtherClassInjection2 otherClassInjection2) throws Exception
{
return new MyClass(otherClassInjection, otherClassInjection2);
}
that logical, it's work injection #Autowired when create a Bean if context are know that bean, that you will to want inject.
I'm use that way.

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;
}

Roboguice - Two implementations for one interface

My code is like this:
interface MyIntreface{
...
}
class A implements MyInterface{}
class B implements MyInterface{}
class BaseClass{
#Inject
MyInterface instance;
}
class MyFirstClass extends BaseClass{
....
}
class MySecondClass extends BaseClass{
....
}
Now I want to MyFirstClass have implementation A and MySecondClass implementation B. #Named annotations seems not to work in this case. Is there any other robo-solution ?
This use case is impossible to implements using Roboguice. But there are two ways to resolve your problem.
Implement provider that injects MyFirstClass and MySecondClass and then inject to provider A or B and use setter to set it in created instance
class Baclass BaseClass{
protected abstract MyInterface extractMyInterface();
}
class MyFirstClass extends BaseClass{
#Inject
B instance;
protected MyInterface extractMyInterface() {
return instance;
}
}
class MySecondClass extends BaseClass{
#Inject
A instance;
protected MyInterface extractMyInterface() {
return instance;
}
}
In my opinion the first one (with Provider) is much more cleaner.

Categories

Resources