struts 2 action class instance variable initialization - spring

I am currently working a existing project.It's using Struts 2 + Spring 2.5.
There is one action class, let's call it ActionA.java, inside which, there is a instance variable which is a service interface, like,
class ActionA{
//variables
protected ServiceAInterface serviceA;
//action methods, utilizing serviceA methods
}
in spring bean definitions, there is a definition, as <bean id="serviceA" class="com.company.serviceAImplementationClass"/>
I didn't find anywhere else related to initialization of the serviceA variable, and really wondering, which part finds out the correct implementation class for this variable, and initialize it?
It really puzzle me. Thanks for any enlightenment.
Jackie

One way is to define service bean as
<bean id="serviceA" class="com.company.serviceAImplementationClass"/>
<bean id="actionClassA" class="com.company.ActionA">
<property name="serviceA" ref="serviceA"/>
</bean>
and then in your class, write setter and getter for your service class.
class ActionA{
//variables
protected ServiceAInterface serviceA;
//action methods, utilizing serviceA methods
public ServiceAInterface getServiceA() {
return this.serviceA;
}
public void setServiceA(ServiceAInterface serviceA)
this.serviceA = serviceA;
}
}
Thats it. Service class bean will be initilized by spring during application start up and its reference will be assigned to your action class.

Related

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.

Injecting property using #Value to abstract class

I have an abstract class in which I am trying to use the #Value annotation to inject value from a property file
public abstract class Parent {
#Value ("${shared.val}")
private String sharedVal;
public Parent() {
//perform common action using sharedVal
}
}
#Component
public class ChildA extends Parent {
Param a1;
#Autowired
public ChildA (Param a1) {
super();
this.a1 = a1;
}
}
I am getting NullPointerException since sharedVal is not set. I tried adding #Component stereotype on the abstract class and still the same thing.
Can I inject value into abstract class this way? If not how can accomplish this?
I think you'll find the sharedVal is being set, but you're trying to use it too soon in the constructor. The constructor is being called (must be called) before Spring injects the value using the #Value annotation.
Instead of processing the value in the constructor, try a #PostContruct method instead, eg:
#PostConstruct
void init() {
//perform common action using sharedVal
}
(or alternatively, implement Spring's InitializingBean interface).
Can I inject value into abstract class this way?
Abstract classes cannot be instantiated, so nothing can be injected into the abstract class. Instead , you should inject the value to its concrete subclass.
Make sure your concrete subclass is marked as #Component stereotype and being "component scanning" by Spring . #Component on the abstract class is not needed as it cannot be instantiated.
Update : I finally figure out that you are trying to access the injected value inside the constructor but found that the value is not set. It is because Spring will inject the value after the bean is instantiated . So if constructor injection is not used , the injected value cannot be accessed inside the constructor . You can use #PostContruct or implementing InitializingBean as suggested by Matt.
Following shows if XML configuration is used :
<context:property-placeholder location="classpath:xxxxx.properties" ignore-unresolvable="true" />
<bean id="parent" class="pkg.Parent" abstract="true" init-method="postConstruct">
<property name="sharedVal" value="${shared.val}" />
</bean>
<bean id="child" class="pkg.ChildA" parent="parent">
Perform your common action using sharedVal inside Parent#postConstruct()

What are advantages of spring DAOSupport

I read about Spring framework's DAOSupport classes. But I could not understand the advantages of these DAOSuport classes. In DAOSupport classes we call getXXXTemplate() method to get the specific template object and then use it further for DB access.
Even without extending DAOSupport we can inject XXXTemplate in our class.
Rest of this things will remain same.
Then what is advantage of extending DAOSupport class?
EDIT:- Adding example
Class extends spring's SimpleJdbcDaoSupport
public class JdbcDao extends SimpleJdbcDaoSupport {
public int create(Bb obj) {
getSimpleJdbcTemplate().update("insert into ..... ") //insert query
}
Bean of this class can be defined as :-
<bean id="jdbcDao" class="example.dao.support.JdbcDao">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
We can create a custom class without extending SimpleJdbcDaoSupport which will have property of type JdbcTemplate
public class MyDAO {
public myJdbcTemplate; // ant its getter and setter
public int create(Bb obj) {
getMyJdbcTemplate().update("insert into ..... ") //insert query
}
It's bean wil be defined as :-
<bean id="jdbcDao" class="MyDAO">
<property name="myJdbcTemplate"><ref local="jdbcTemplateBean"/></property>
</bean>
As you can see both classes do same thing. While extending SimpleJdbcDaoSupport we are injecting DataSource and without it we are injecting directly jdbcTemplate bean. That's it. No more difference.
So I do not see any much advantage with this much use of DAOSupport classes. Any additional functionality given by DAOSupport classes ?
When you use HibernateDAOSupport you can see the difference.
1. Config the transaction to optimize the performance of the application on the applicationContext :
select : read only
create/update : read and write.
You use one session only(with getHibernateTemplate() and the sessionFactory)
When we update some data on the database we do only merge the modifications whith the method impleted on HibernateDAOSupport.
There are many method already implemented on the DAOSupport and we can use this to our need.

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

Accessing a session-scoped bean inside a controller

I'm experimenting with session-scoped beans in Spring 3. I have the following bean definition:
<bean id="userInfo" class="net.sandbox.sessionbeans.UserInfo" scope="session" />
Here is net.sandbox.controllers.RegistrationController, a controller class that needs access to this bean. I've taken out the imports for brevity's sake.
#Controller
#RequestMapping("/register")
public class RegistrationController {
private UserInfo userInfo; // This should reference the session-scoped bean
#RequestMapping(method = RequestMethod.GET)
public String showRegForm(Model model) {
RegistrationForm regForm = new RegistrationForm();
model.addAttribute("regform", regForm);
return "regform";
}
#RequestMapping(method = RequestMethod.POST)
public String validateForm(#Valid RegistrationForm regForm, BindingResult result, Model model) {
if (result.hasErrors()) {
return "regform";
}
userInfo.setUserName(regForm.getFirstName());
model.addAttribute("regform", regForm);
return "regsuccess";
}
}
Is there a way to automatically tie the session-scoped bean I defined to the member variable private UserInfo userInfo in RegistrationController?
Yes - see section 3.4.5.4 of the Spring manual, "Scoped beans as dependencies".
Briefly, you can ask Spring to wrap your session-scoped bean in a singleton proxy, which looks up the correct session when you invoke a method on the scoped bean. This is called a "scoped proxy", and uses the <aop:scoped-proxy> config macro. You can then inject the reference as you would any other (e.g. <property>, or #Autowired). See the above link for details.
By default, Spring creates a proxy by implementing an interface at run-time. So, the only methods available on the proxy are those defined in any interfaces UserInfo implements (if any). You may have to create a suitable interface that includes the setUserName() method.
Alternatively, you will need to force a CGI based proxy (the proxy is a sub-class of your class created at run-time so it doesn't need an interface). Specify:
<bean id="userInfo" class="net.sandbox.sessionbeans.UserInfo" scope="session" >
<aop:scoped-proxy proxy-target-class="true"/>
</bean>
About this comment:
I tried applying this technique. I put
inside the bean
definition and I #Autowired'd private
UserInfo userInfo. It seems to work,
but for some reason the bean's setter
function isn't executed properly...
i.imgur.com/zkxVA.png – Pieter 1 hour
ago
If you use interface-based proxies, the setter method is not available on the Proxy unless the interface has the setter method.
If you don't like XML, you can also use ObjectFactory<T> like this :
#RestController
public class MyController {
private final ObjectFactory<MySessionScopedComponent> OFSession;
#Autowired
public MyController(ObjectFactory<MySessionScopedComponent> OFSession) {
this.OFSession = OFSession;
}
#RequestMapping(path = "/path", method = RequestMethod.GET)
public String myMethod () {
MySessionScopedComponent sessionBean = OFSession.getObject();
// Do some stuff
return bean.myValue();
}
}
Note: Tested with Spring Boot 1.5.6 (Spring 4.3)

Resources