How to guarantee that Spring #Autowired injection can be accessible in the constructor - spring

I have a Spring Bean which has a #Autowired setter getter injection. However, when i try to access injected bean, i get NullPointerException because the injected bean has not be really injected.
Is there any way to guarantee that the injection is done before constructure call?
#Component
#Scope("session")
public class A{
#Autowired
B;
public A()
{
//B is null here, because it has not been injected yet.
}
//Setter Getters
}

Use the #PostConstruct annotation. This will be called right after Spring initializes your bean.
#Autowired
B b;
public A() {
}
#PostConstruct
public void doAfterConstructorIsCalled() {
b.do();
}
It's from the javax.* API

Related

what is the purpose of spring boot autowired annotation on a constructor?

what is the purpose of #Autowired annotation on a constructor? What is the difference between non-annotated and annotated constructor? Thank you.
Autowiring feature enables you to inject the object dependency implicitly.
Without autowiring you have to initiate the object like:
public class SomeOperation() {
private CarService carService;
public SomeOperation() {
carService = new CarServiceImpl();
}
}
But if you annotate with #Autowired you don't have to initiate the object. The framework will bring the class which implements the carService and initiate your object with it.
public class SomeOperation() {
private CarService carService;
#Autowired
public SomeOperation(CarService carService) {
this.carService = carService;
}
}
What is the difference between non-annotated and annotated
constructor?
In Spring 3 or below, the annotation on the constructor is mandatory to make Spring consider the constructor as the way to instantiate the bean and inject dependencies provided in parameters.
Spring 4 and above versions don't require the annotation to do that.
You just need to declare the constructor with any parameter to achieve that.
So in recent Spring versions, don't clutter the code with the annotation :
public Foo(Bar bar){
this.bar = bar;
}

Use spring Transactional in a Prototype bean

I would like to use spring transaction management capabilities within a prototype bean. I did the following:
I've used javax.inject.Provider to create my prototype bean.
I've annotated the method of the prototyped bean with the #Transactional annotation.
Is this the right way of doing it?
#Service
public class SomeService {
#Autowired
private Provider<SomePrototype> myPrototypeProvider;
public void execute() {
SomePrototype somePrototype = myPrototypeProvider.get();
somePrototype.someMethod();
}
}
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SomePrototype {
#Autowired
private SomeSpringBean someSpringBean;
#Autowired
private SomeRepository someRepository;
#Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {
Result result = someSpringBean.doSomething();
someRepository.save(result);
}
}
The initialisation of transaction-scoped bean requires a proxy. Therefore, if we define a transactional bean as prototype, every that bean is requested, a new proxy is created, and that is not efficient.
What is reason behind this requirement (to have transactional prototype bean)

Spring Abstract class #Autowire null while using that field in subclass constructor

Following is the code:
public abstract class A {
#Autowired
public Provider provider;
}
#Component
public class B extends A {
B() {
provider.get();
}
}
Spring is throwing NullPointerException, while instantiating Bean of Class B.
I know #Autowired defined in Abstract class are injected, but don't know in which order they are injected.
Earlier my understanding was, While instance creation of B, Spring will autowire fields of all subclasses and then will create instance of B.
But here it seems, it overlooks the subclass concept while instance creation, and just scans B to identify #Autowire field.
Use #PostConstruct. Java Object Instantiation and Spring Dependency Injection are two different flows.
#Component
public class B extends A {
#PostConstruct
void init() {
provider.get();
}
}
If autowiring your constructors is an option the following can be helpful.
public abstract class A {
protected final Provider provider;
#Autowired
public A(Provider provider) {
this.provider = provider;
}
}
#Component
public class B extends A {
#Autowired
B(Provider provider) {
super(provider);
provider.get();
}
}
Note since the latest Spring Versions you do not need to annotate the constructor with #Autowire. If you do things right the spring framework auto-detects the constructor.

#autowired field and also #autowired constructor

I have a spring MVC application. I have a bean which is wired as a singleton and also a field which is also autowired but is of request scope.
For example:
class Hello {
#Autowired
BDepend b; // this is defined as a request scope bean
#Autowired
public Hello(ADepend a){
}
}
Here my class Hello is a singleton but BDepend is a request scope object.
How does spring handle right instance of Bdepend for each of the request since Hello is a singleton.
By default you will have runtime exception at application sturtup. Something like this:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
To use request scope objects inside of some singleton you need to obtain a fresh instace each time from application context. You can do it:
using application context directly
class Hello {
#Autowired
private ApplicationContext ctx;
#Autowired
public Hello(ADepend a){
}
public useB(){
BDepend instance = ctx.getBean(BDepend.class);
instance.doSomething();
}
}
or get a fresh instance via javax.inject.Provider.
class Hello {
#Autowired
private Provider<BDepend> provider;
#Autowired
public Hello(ADepend a){
}
public useB(){
BDepend instance = this.provider.get();
instance.doSomething();
}
}
or declare scoped proxy for this bean:
#Component
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
class BDepend {
}
class Hello {
#Autowired
private BDepend b;
#Autowired
public Hello(ADepend a){
}
public useB(){
b.doSomething();
}
}
or use scoped proxies system wide
<context:component-scan base-package="com.mycompany.beans" scoped-proxy="targetClass" />
Personally I prefer second option (javax.inject.Provider): it is clear from the code that your bean has different scope.

Implement factory design pattern with spring annotaion

I have a factory class that should return me an instance of classA or classB. These classes implement interface XYZ:
interface xyz;
getInstance()
#service
classA implements xyz{
public void checkStatus(){
}
}
#service classB implements xyz{
public void checkStatus(){
}
}
Factory class:
#component
class ABCFactory{
#Autowire classA A;
public static getInstance(str a){
return classA;
}
}
Client code:
Class A a = ABCFactory.getInstance("A");
a.checkStatus();
I get null pointer exception -- probably a is returned as null?
What is the best approach to implement the factory pattern with spring annotation and autowired bean?
It's difficult to say with any certainty why your auto-wiring isn't taking place without seeing your Spring config. My first guess is that you don't have component scanning switched on:
<context:component-scan base-package="org.example"/>
Adding something like that to your spring config file (with the correct package) will tell Spring to scan the package structure for fields that need to be auto-wired, and services that can be used for auto-wiring.
static is the root of all evil. How did you managed to access classA here?
#Component
class ABCFactory{
#Autowire classA A;
public static getInstance(str a){
return classA;
}
}
A field is not static while getInstance() method is - your code won't compile.
Furthermore, dependency injection works on instances, not on static classes. Thus you should get rid of static:
#Component
class ABCFactory {
#Autowire classA A;
public xyz getInstance(str a){
return A;
}
}
and inject ABCFactory where you need it (e.g. in other services or controllers):
#Autowired
private ABCFactory factory;
BTW your design looks supicious in Spring environment, what do you want to achieve?

Resources