#Autowired bean null when inside at least two levels of components - spring

I have the following structure:
#Component
#Scope("request")
public class ListCompaniesBean {
#Autowired
private JsfUtil jsfUtil;
...
#Component
public class JsfUtil {
#Autowired
private ComponentLookup componentLookup;
...
#Component
public class ComponentLookup {
...
Spring creates the ListCompaniesBean and autowires JsfUtil without any problem, but for some reason ComponentLookup comes null when I use it inside ListCompaniesBean. If I create a new field on ListCompaniesBean and autowire ComponentLookup it is created normaly, seems that I can't create beans inside beans until some level, does anyone had this problem?
I'm not creating new instances of any of them, JstUtil and ComponentLookup are in a separate jar, and everything is on an EAR with a shared context, if you need more information just tell me.
Thanks in advance.

Related

How to use #Autowired annotation two or more different Component class for same service?

For example, have a class like as follows.
First XService service in class A is not null but second XService service in AmountValidator is null.I get NullPointerException I try to create bean new it works and then I get same exception when call AmountValidateService outsideRestService in XService.
How can I use XService everywhere that I use #Autowired annotation.
My main class:
#Service
class A extends AbstractA implements IA {
#Autowired
XService service; //first autowired definition. code go to check() method. service not null now.
public doSometing(){
validator.check();
service.methodA();
super.AbstractMethod();
}
}
Validator class used in class A :
class Validator<T> implements IValidator<T> {
public void check(){
rule.check(); // rule have a implements IValidator eg: amountValidator, dateValidator class
}
}
AmountValidator added to rule in class Validator.
#Component
class AmountValidator implements IValidator<T>{
#Autowired
XService service; // code comes here service is null. same service class mentioned above class A.
#Override
public void check(){
service.validateAmount(); // nullPointerException.
}
}
My main Service
#Component
class XService {
#Autowired
AmountValidateService outsideRestService;
public validateAmount(){
outsideRestService.validate(); // nullPointer when create XService with the `New` keyword
}
}
You have an error cause you are trying to create components/beans/services yourself. As i mentioned in comment when you create components yourself it - #Autowired doesn't work - thats you've got NPE
All classes annotated with #Component, #Service are considered special classes which are instantiated by Spring automatically via DI, instantiating them with new defeats the purpose of DI.
These special classes are named Spring Beans.
Every time the application starts, the framework instances all Spring Beans, and all #Autowired fields are injected by Spring automatically. But the Spring Beans must be defined somewhere in the class path. Else you will receive a NoSuchBeanDefinitionException
As an attempt to answer the question, since I don't have a stack trace nor all the Spring Bean definitions:
When you instantiate XService using new XService() your new instance will not actually initialize the field AmountValidateService outsideRestService, effectively leaving it as null.
You may set the field yourself but as I mentioned earlier, it defeats the purpose of DI
Your question is not complex, it is incomplete.

when using functional bean registration, is there a way to inform Spring that ClassA is responsible for creating an instance of BeanA?

I've switched a portion of a Spring app to use functional bean registrations. The motivation for the switch is due to requiring multiple instances of some beans under certain conditions. It also turns out to be much more concise (which won't be at all apparent with the simplistic examples below).
The code used to look like this (simple example):
#Configuration
public class ConfigA {
#Bean
public BeanA beanA() {
return new BeanA();
}
}
#Service
public class Service1 {
#Autowired BeanA beanA;
...
}
#Service
public class Service2 {
#Autowired BeanA beanA;
...
}
I've switched the configuration class to look like this:
#Configuration
public class ConfigA implements ApplicationContextInitializer<GenericApplicationContext> {
#Override
public void initialize(GenericApplicationContext context) {
context.registerBean("beanA", BeanA.class, () -> new BeanA());
}
}
The issue I'm now encountering is that Spring is complaining about autowired beans not being found. With the original code, Spring could determine that a BeanA bean was declared via ConfigA and would create that bean before initializing the services.
With the new code, I guess there is no way for Spring to determine where the BeanA bean(s) are being declared, and so it tries to init the services before the BeanA is initialized (which causes the app to not start).
I was hoping that Spring would prioritize #Configuration classes over #Service or #Controller classes, but that doesn't seem to be the case.
I could annotate all the services with #DependsOn("configA"), but there are many services that autowire BeanA (some in other code bases), so the #DependsOn option isn't really realistic.
Question: When using functional bean registration, is there a way to inform Spring that ConfigA is responsible for creating an instance of BeanA?
In order to use the functional style of bean registration and enable autowiring mechanism in other beans you can do the following:
Remove #Configuration annotation from your ConfigA class;
Create directory named META-INF under main/java/resources and create a file named spring.factories under the newly created directory;
Fill the newly created file with the line org.springframework.context.ApplicationContextInitializer=(package-name-to-configA-class).ConfigA
Now Spring should be able to successfully autowire bean named BeanA where requested.

Spring bean management using #Autowired

I have a messaging call that will process my payload which starts from MyClass. In load test i see that the first payload is getting over written by the next. All my classes are spring managed by #Autowired. Obviously the bean scope is singleton and thats why this is happening. But i do not want to use new operator and want it to be spring annotation configured. Is there any way to fix this issue of losing data ?
UPDATE
My configuration looks like below :
Public class MyClass {
...
#Autowired
public MyService myService;
...
}
#Component
#Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class MyService{
#Autowired
public Aone one;
#Autowired
public Atwo two;
...
}
#Component
#Scope(value="prototype")
public class Aone {
}
I am attempting this configuration after suggestions from net. For every call i get in MyClass a new instance of MyService will be created and from there on all other instances like Aone / Atwo should have new instance, will this configuration be ok ?

Difference between #Qualifier("beanName") and #Component("beanName")

Is there any difference between using #Qualifier("beanName") and #Component("beanName") ?
If not, is there a preferred approach?
Generally, you use #Component("beanName") on the component, You use #Qualifier("beanName") on a class you are autowiring. Ex
#Component("myComponent1")
public class MyComponent1 implements MyComponent {
....
}
#Component("myComponent2")
public class MyComponent2 implements MyComponent {
....
}
#Service
public class SomeService implements MyService {
#Qualifier("myComponent1")
private MyComponent myComponent;
...
}
If there is more than one implementation of a bean/component, spring won't know which bean to select, so you need to use a the qualifier to specify which one is correct.
Additionally, you can use #Primary on one of the components, so it is always selected by default.
They are totally two different things , sound like you are compare apple and orange to me.
#Component is used to declare a class as a Spring bean which you cannot do it with #Qualifier.
#Qualifier is intended to help Spring to determine which bean to inject if there are more than 1 eligible bean for that injection. It is normally used with #Autowired which add more constraint on the injection point such that there are only one bean can be injected in it.

Injecting 2 bean with same class name

I have a app 'app_test' which consists a class TestClass with #Service anotation. I have a library class 'lib_test' with bean in XML file with id=''TestClass'. Both are in different package.
I m injecting #Service bean as follows
Import com.app.TestClass
Class TestController
{
Private final TestClass testClass;
#Inject
TestController (TestClass testClass)
{
This.testClass =testClass;
}
}
It should inject by type since they are in different package. But the controller is giving qualified bean not found.
I can resolve it by giving #Qualifier and giving name to #Service. But y is it needed? Since both are in different package it should autowire by type right? Or m missing some concept?
Although they are in different packages if they are of the same type Spring does not know which to use
I'd suggest marking any service class with #Primary.
package com.app.TestClass
#Primary
#Repository
public class TestClass implements XXX
This way it will be selected as the default autowire candididate, with no need to autowire-candidate on the other bean.
Also, rather than using #Autowired #Qualifier, I find it more elegant to use #Resource for picking specific beans.
I've always found this a strange limitation of Spring's standard bean naming convention. It does not include the package part of the class in the name leading to duplicates in large projects when classes have the same name.
This is why I always configure Spring projects with a different BeanNameGenerator:
public class CustomAnnotationConfigWebApplicationContext extends AnnotationConfigWebApplicationContext {
private BeanNameGenerator qualifiedAnnotationBeanNameGenerator = new QualifiedNameAnnotationBeanNameGenerator();
#Override
protected BeanNameGenerator getBeanNameGenerator() {
return this.qualifiedAnnotationBeanNameGenerator;
}
}
And the generator:
public class QualifiedNameAnnotationBeanNameGenerator extends AnnotationBeanNameGenerator {
#Override
protected String buildDefaultBeanName(BeanDefinition definition) {
String qualifiedName = definition.getBeanClassName();
return Introspector.decapitalize(qualifiedName);
}
}
With this setup, common class names that are in different packages are automatically recognized as being different and the correct one gets injected.

Resources