how to load spring bean from another class - spring

I have loaded "myspring.xml" in web.xml using context-param
in "myspring.xml" I have written bean to which I have passed arguments as constructor argument
<bean id="abc" class="com.Hello">
<constructor-arg ref="dataSource"/>
<constructor-arg value= “dummy data”/>
</bean>
in Hello bean I have initialized constructor as ,
public class Hello{
public Hello(datasource,dummydata){
}
public void methodFromHelloBean(){
// use here dummydata from constructor
}
}
Here , 'Hello' bean is getting initialized at server startup, as I defined in web.xml and it is working fine.
My question is -
I am working on exisitng applciation.
I want to call methodFromHelloBean() inside my another class say MyService class.
How I can call the method in MyService class.
One way i know is using applicationContext.
But in my existing application I have not seen any bean loaded using application-context path.
what is other way , how I can initialize 'Hello' bean from 'MyService' class.
Do I need to pass parameters to constructors while initializing & how.
Thanks in advance.

Let's suppose we have MyService a class whose bean instance consumes some method methodFromHelloBean from abc, the Hello bean.
public class Hello {
private boolean cacheInitialized;
public void methodFromHelloBean(Object param) {
if (!cacheInitialized) {
initializeCache(param);
cacheInitialized = true;
}
// do whatever you please with cache.
}
private void initializeCache(Object param) {
// TODO
}
}
public class MyService {
#Autowired
private Hello abc;
public void someMethod() {
// determine which parameters to pass to abc
Object param = ...
abc.methodFromHelloBean(param);
}
}

Related

Spring - #Autowired bean from #Configuration is null

I define a bean in a configuration class. I would like to autowire this bean in a component. However, the property stays null. E.g.:
Appconfiguration.java
#Configuration
public class AppConfiguration {
#Bean
public SomeType someObject() {
return new SomeType();
}
}
AppComponent.java
#Component
public class AppComponent {
#Autowired
private SomeType someObject; // TODO why null?
public AppComponent() { // note: passing a SomeType constructor argument works
System.out.println(someObject);
}
}
How can I autowire a bean defined in a configuration class?
Are you missing a fundamental detail that properties are injected after a bean is created? Have you tried access your property after a bean is fully initialized?
Update:
I've reworked your example a little to demonstrate you the difference:
#Test
public void initializationTest() {
try (AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext()) {
context.register(AppConfiguration.class, AppComponent.class);
context.refresh();
}
}
#Configuration
public class AppConfiguration {
#Bean
public SomeType someObject() {
return new SomeType();
}
}
#Component
public class AppComponent {
#Autowired
private SomeType someObject;
public AppComponent() {
// Here properties are not yet injected by Spring IoC container
System.out.println(someObject); // Obviously prints null
}
/**
* Method is invoked after a bean is initialized and all its properties are being set.
*/
#PostConstruct
private void init() {
System.out.println(someObject); // Prints SomeType#6b419da
}
}
public class SomeType {
}
So basically bean lifecycle consists of the following steps:
1. Bean instance is created
2. Bean properties are set
3. In case bean implements Aware interfaces - those implemented methods are invoked
4. BeanPostProcessor#postProcessBeforeInitialization methods of custom bean post-processors are invoked
5. Initialization callbacks are invoked in the following order:
5.1. #PostConstruct method is invoked
5.2. InitializingBean#afterPropertiesSet() method is invoked
5.3. #Bean#initMethod() method is invoked
Bean is fully initialized now.
6. BeanPostProcessor#postProcessAfterInitialization methods of custom post-processors are invoked
are invoked.
7. Destruction callbacks are invoked in the following order:
7.1. #PreDestroy method is invoked
7.2. DisposableBean#destroy() method is invoked
7.3. #Bean#destroyMethod method is invoked

Injecting a prototype bean into a singleton bean

I am new to Spring and trying to understand the concept "Injecting a prototype bean into a singleton bean". As per my understanding In singleton, only a single instance per Spring IoC container, no matter how many time you retrieve it. validator.validate(requestId);, because still private RequestValidator validator not instantiated.
I developed below example where in a singleton bean I give a reference of prototype bean like below:
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
RequestProcessor.java
public class RequestProcessor {
private RequestValidator validator;
public RequestProcessor(){
System.out.println("Constructor:: RequestProcessor instance created!");
}
public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
validator.validate(requestId);
}
public RequestValidator getValidator() {
return validator;
}
public void setValidator(RequestValidator validator) {
this.validator= validator;
}
}
RequestValidator.java
public class RequestValidator {
private List<String> errorMessages = new ArrayList<String>();
public RequestValidator() {
System.out.println("Constructor:: RequestValidator instance created!");
}
// Validates the request and populates error messages
public void validate(String requestId){
System.out.println("RequestValidator :"+requestId);
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
Now when I called the main method I see the following output:
MainDemo.java
public class MainDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}
the output is:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
RequestValidator :1212
------------------------
Request ID : 1213
RequestValidator :1213
Now looking at the output, it looks like for the 2nd call processor.handleRequest("1213"); bean is not instantiated, instead already instantiated bean gets used thats why constructor wont get called again. So Prototype bean validator acting as a singleton bean only.
To me : it is expected that when ever I fetch requestProcessor from application context, it will be wired with a new validator as we declared the validator bean is of prototype scope. But this does not happen.
How to solve it ? Is my understanding correct ?
Another way:
<!-- Lookup way -->
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="getValidator" bean="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
If I call my main method I see below output + error: Here code validator.validate(requestId); executes, private RequestValidator validator; is not instatiated and whats why null pointer exception coming.
I've shown in the below code:
public class MainDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
RequestValidator requestValidator = (RequestValidator) context.getBean("validator");
RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}
Now I see the below error:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
Exception in thread "main" java.lang.NullPointerException
at com.injection.testing.RequestProcessor.handleRequest(RequestProcessor.java:12)
at com.injection.testing.MainDemo.main(MainDemo.java:14)
Injection happens only once, when the Spring context is started. If bean has prototype scope, Spring will create new prototype bean for every injection. But prototype bean will not be created every time you call its methods. Lets consider next example:
<bean id="firstRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="secondRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
In this case both of RequestProcessor beans will have its own instance of RequestValidator bean.
Lookup method is the method, you should call every time when you need new instance of prototype bean. It's better to make this method abstract, because anyway Spring will override this method automatically. For example:
public class abstract RequestProcessor {
public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
RequestValidator validator = createValidator(); //here Spring will create new instance of prototype bean
validator.validate(requestId);
}
protected abstract RequestValidator createValidator();
}
Note, that createValidator returns instance of RequestValidator and has not any parameters. Also you don't need private class variable validator. In this case bean's configuration will looks like:
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="createValidator" bean="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
Now every time you call createValidator method, Spring will create new instance of validator bean.
You can find more details in documentation.
When spring creates the context, it will instantiate an instance of the RequestProcessor. During the instantiation of that instance, an instance of the RequestValidator is created and injected in the RequestProcessor.
Because any subsequent reference to the RequestProcessor Bean will access the same instance of the RequestProcessor in the context - and it is already fully constructed - there will never be a call to create a new instance of a RequestValidator. Although your Validator is scoped to be a prototype - in the example above - you only ever ask for a single copy - when you create the RequestProcessor singleton.
For the second part of your question - you misunderstand the use of the lookup-method. Spring allows you to override the method on your RequestProcessor - so when you call requestProcessor.getValidator() - spring will return a new instance of that RequestValidator. However - during the construction of your requestProcessor instance - you never initialized the validator field. Nor did spring inject a validator during instantiation. Hence the NullPointerException.
Lookup method injection
As noted earlier, lookup method injection is an advanced feature that
you should use rarely. It is useful in cases where a singleton-scoped
bean has a dependency on a prototype-scoped bean. Using Java for this
type of configuration provides a natural means for implementing this
pattern.
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
}
Using Java-configuration support , you can create a subclass of
CommandManager where the abstract createCommand() method is overridden
in such a way that it looks up a new (prototype) command object:
#Bean
#Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
#Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
}
In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.
A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it.
With this approach , our business logic is get coupled with Spring conatiner (Application Context) which does not looks to be a good Solution. An alternate of this is Lookup Method Injection.

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

Why do the protected fields of type String not get Autowired, while other beans do

I am trying to set value of protected String field in a annotation configured bean using property-override mechanism. It throws following exception unless I add a setter for the field in the bean.
org.springframework.beans.NotWritablePropertyException: Invalid property 'cookie' of bean class [com.test.TestBean]: Bean property 'cookie' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
To compare I also have another protected field which is of type of another class. Bean of the other class is defined in XML. This field gets properly autowired.
Here's the first bean
#Component("testBean")
public class TestBean {
protected #Autowired(required=false) String cookie;
protected #Autowired InnerBean innerBean;
public String getCookie() {
return cookie;
}
public void setCookie(String cookie) {
this.cookie = cookie;
}
public InnerBean getInnerBean() {
return innerBean;
}
}
Here's InnerBean
public class InnerBean {
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Spring configuration file - only interesting bits
<context:property-override location="beans.properties"/>
<context:component-scan base-package="com.test"></context:component-scan>
<context:annotation-config></context:annotation-config>
<bean id="innerBean" class="com.test.InnerBean">
<property name="value">
<value>Inner bean</value>
</property>
</bean>
beans.properties
testBean.cookie=Hello Injected World
Main
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test.xml");
TestBean bean = context.getBean(TestBean.class);
System.out.println("Cookie : " + bean.getCookie());
System.out.println("Inner bean value : " + bean.getInnerBean().getValue());
}
Output
Cookie : Hello Injected World
Inner bean value : Inner bean
If I just comment out the setter for cookie in TestBean, I get the mentioned NotWritablePropertyException exception. Is there a difference between autowiring a bean and autowiring a property?
#Autowired should only be used when you want to wire up a Spring bean to another bean.
Properties are set by PropertyOverrideConfigurer which is a different process to autowiring, and doesn't use the #Autowired annotation. That #Autowired annotation on the cookie property is unnecessary and probably confusing Spring's bean factory. I expect that simply removing the annotation should fix the problem for you, ie:
protected String cookie;
protected #Autowired InnerBean innerBean;
Spring is capable of setting properties even if they are private or protected.

Autowired not working as expected

I'm using Spring Roo and want to access a bean within of Controller class which has following configuration in applicationContext.xml:
<bean class="com.reservation.jobs.Configuration" id="jobsConfiguration" autowire="byType">
<property name="skipWeeks" value="4" />
</bean>
The configuration class itself is:
package com.reservation.jobs;
public class Configuration {
private int skipWeeks;
public void setSkipWeeks(int value) {
System.out.println("SkipWeeks set auf: " + value);
this.skipWeeks = value;
}
public int getSkipWeeks() {
return this.skipWeeks;
}
}
In my Controller I thought that a simple Autowired annotation should do the job
public class SomeController extends Controller {
#Autowired
private com.reservation.jobs.Configuration config;
}
During startup Spring prints the message within the setSkipWeeks method. Unfortunately whenever I call config.getSkipWeeks() within the controller it returns 0.
Have I to use the getBean method of the ApplicationContext instance or is there some better way?
autowire="byType" is redundant. It indicates that fields of the Configuration class should be autowired, and you have just one primitive. So remove that attribute.
Apart from that, config.getSkipWeeks() must return 4 unless:
you are using a different instance (made by you with new)
you have called the setter somewhere with a value of 0

Resources