Injecting a bean inside another bean and use it in the constructor? - spring

I have a bean that looks like this:
#Component
#Scope("session")
public class AlarmChartSettingsBean implements Serializable {
...
Inside this bean i inject another bean like this:
#Inject
private SessionInfoBean sessionInfoBean;
Then i call the injected bean inside the constructor of the first bean like this:
public AlarmChartSettingsBean() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
The problem is that the injected bean is null. So the question is when is that bean injected? Can i use it inside the constructor or i should use it after the bean has been constructed?

The constructor of a Spring bean is called before Spring has any chance to autowire any fields. This explains why sessionInfoBean is null inside the constructor.
If you want to initialize a Spring bean, you can:
annotate a method with #PostConstruct:
#PostConstruct
public void init() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
implement InitializingBean and write the initialization code inside the afterPropertiesSet method:
public class AlarmChartSettingsBean implements Serializable, InitializingBean {
#Override
void afterPropertiesSet() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
}

The #Inject on a Field will autowire after the constructor has been called.
Note: In some Spring-Apps the #Inject may not work, use #Autowire instead.

Related

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 Autowired annotation with service implementation

I have few doubts in the scenario below.
Having one interface and two implementation classes:
Interface:
interface ServiceInt
{
public void save();
}
First implementation class:
Public class ServiceIntImpOne implements ServiceInt
{
public void save()
{
// I am first service implementation
}
}
Second implementation class:
Public class ServiceIntImpTwo implements ServiceInt
{
public void save()
{
// I am Second service implementation
}
}
Main class calling the save method of an implementation class:
Public class controller
{
#Autowired ServiceInt;
public void save()
{
ServiceInt.save()
}
}
My Questions:
ServiceInt.save() – which save method of service class implementation will it invoke?
How we can use the save method implementation of the ServiceIntImpTwo class?
How does autowired work?
ServiceInt.save() – which save method of service class implementation
will it invoke?
If you have two beans of the same type (beans defined via annotations or via xml) when you autowire that beans it will fail (throw exception), because Spring don't know what bean to inject.
caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [ServiceInt] is defined:
How we can use the save method implementation of the ServiceIntImpTwo
class?
If you defined your bean in a xml file, then you can use the id property
<bean id="beanTwo" class="ServiceIntImpTwo" />
then you can autowire using Qualifier annotation
#Autowired
#Qualifier("beanTwo")
ServiceInt myServiceTwo;
if you are using annotations instead.
#Component
Class ServiceIntImpTwo impl...{}
Then you can autowire
#Autowired
#Qualifier("serviceIntImpTwo ")
ServiceInt myServiceTwo;
How does autowired work?
This you can read it on Internet.
http://memorynotfound.com/handling-multiple-autowire-dependencies-with-spring-qualifier/
https://www.mkyong.com/spring/spring-autowiring-qualifier-example/
https://www.tutorialspoint.com/spring/spring_qualifier_annotation.htm
If you have two implementation to one interface you will need to provide spring hint which one to use:
you can use #Qaulifier annotation
you can use #Profile and choose the active profile.

Failed to instantiate [..]: No default constructor found;

I'm getting:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mz.server.rest.braintree.webhooks.SubscriptionWebhook]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.mz.server.rest.braintree.webhooks.SubscriptionWebhook.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
... 22 more
Even though I have defined this constructor in my applicatioContext-restapi.xml file:
<bean id="subscriptionWebhook" class="com.mz.server.rest.braintree.webhooks.SubscriptionWebhook">
<constructor-arg ref="dslContext" />
</bean>
Any idea why?
#RestController
public class SubscriptionWebhook {
private final static Logger LOGGER = Logger.getLogger(SubscriptionWebhook.class.getName());
private AdminService adminService;
public SubscriptionWebhook(DSLContext ctx) {
this.adminService = new AdminService(ctx);
}
}
Since Spring 3(ish) you can configure your container by applying #Component annotations to classes. #Controller annotation is defined as follows:
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Controller
Which means classes annotated by it are going to get picked up, too. And RestController is just Controller and ResponseBody put together.
Anyway as you admitted in the comments you have enabled component scanning, and the configuration in xml is not going to get picked up in this case.
What you could do is convert the xml configuration to annotation-based injection, like that:
#RestController
public class SubscriptionWebhook {
private final static Logger LOGGER = Logger.getLogger(SubscriptionWebhook.class.getName());
private AdminService adminService;
public SubscriptionWebhook(#Qualifier("dslContext") DSLContext ctx) {
this.adminService = new AdminService(ctx);
}
}
Qualifier annotation is going to look in the container for a bean with name/id dslContext and inject it in the constructor. Alternatively you can use the javax.inject Named annotation, or if this is the only bean with that type, Spring's #Autowired or JSR-330's #Inject.
Annotation #RestController is autodetected by spring. Spring will create a bean for you so you shouldn't add bean definition in the xml, because it would create a second bean. If you want to inject another bean into the controller just use #Autowired. So the solution in your case is:
Remove "subscriptionWebhook" bean definition from the xml
Add #Autowired on SubscriptionWebhook constructor

multiple instance of autowired bean

When a bean is autowired, does it create multiple instances of the class?
Here's an example;
public class ClassA {
#Autowired
private ClassB classB;
public ClassB getClassB() {
return classB;
}
public void setClassB(ClassB classB) {
this.classB = classB;
}
// using ClassB in method 1
public void useClassBmethod1() {
// currently using autowired ClassB instance
classB.doSomething();
}
// using ClassB in method 2
public void useClassBMethod2() {
// need a new instance of ClassB but through the same autowired bean
ClassB classb = getClassB();
}
}
public class ClassB {
public void doSomething() {}
}
So my question is, does autowiring a bean know how to create a new instance of a bean when needed or this is left to the programmer to decipher?
Thanks for helping out.
It depends on attribute scope of bean tag. If scope="singleton" which is by default then each time you will get single instance and if scope="prototype" then you will get different instances. And it doesn't depend on autowire.
<bean class="ClassB" scope="prototype">
By using #Autowired you instruct classloader to associate any class instance available in container to associate with the callee. You need to make sure that you have made an entry to instantiate the bean in your config file like <bean id="test" class="xxx.Test" />. Also you might want to check scopes too.
If you have multiple instances of same class define with different names then with #Autowired you need to provide specific name that you want to use with the help of qualifier.
by default all beans are singleton so only one instance will be created, more about scopes http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-factory-method-injection

Is it possible to autowire bean name in Spring?

Is it possible to autowire bean name in Spring using annotations instead of using BeanNameAware interface?
It is not possible out of the box, you can create own annotation #BeanNameInjected and register own BeanPostProcessor to deal with it.
You can annotate bean setter method with #Autowired.
public class SimpleMovieLister {
private MovieFinder movieFinder;
#Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}

Resources