Thursday, July 3, 2008

Action Form and Struts 2 Actions

A big leap in struts 2, the action class properties can be used as input properties; this eliminates the need of any Action Form like classes in struts 2. These properties can be accessed in a web page using struts 2 tag libraries. We can create different action classes with getters/setters for their own set of input fields. It means the actions in struts 2 can also behave as Action Forms in struts 2.
An Action class with I/p fields:-
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
private String username;
private String password;
public getUsername(){
return username;
}
public setUsername(String username){
this.username = username;
}
public getPassword(){
return password;
}
public setPassword (String password){
this.password = password;
}
public String execute() throws execution{
// some logic
return SUCCESS;
}
public void validate(){
// logic to validate
}
}
These input fields (username/password) should be set prior to the execution of the execute() method.
What is required for setting all input parameters before execute() method is invoked.. This is an interceptor named param(ParametersInterceptor). This interceptor is a part of basicstack and default stack interceptor stack. ParameterInterceptor sets all parameters on the value stack using ValueStack.setValue(String, Object) methods.

Model Driven Actions
Struts 2 also supports ActionForm pattern and POJO form objects. The concept of Model Driven action is used to inject the POJO from the Object (model) into the action. But for the action to process over it , the model of the action needs to be added to the action in its value stack making it available in the action.
This approach needs some additional implementation, The action class must implement com.opensymphony.xwork2.ModelDriven interface. The only method which is exposed by Model driven interface is the Object getModel(). This method provides the model to be pushed into the value stack.
Let’s see a sample example of POJO form, which can be injected in the action as its model.
public class user{
private String username;
private String password;
public getUsername(){
return username;
}
public setUsername(String username){
this.username = username;
}
public getPassword(){
return password;
}
public setPassword (String password){
this.password = password;
}
}

The loginAction described earlier can be converted into ModelDriven action by removing input properties with their getter/setter methods and implementing interface ModelDriven .

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class LoginAction extends ActionSupport
implements ModelDriven, Preparable{
User user;
public void prepare(){
user = new User();
}
public User getModel(){
return user;
}
public String execute() throws execution{
// some logic
If(user.getUsername().equals(“ashu”)){
return SUCCESS;
}
else
return ERROR;
}
public void validate(){
// logic to validate
}
}
The getModel() method must be invoked earlier for populating its input properties with the data from request parameters, to make sure that the model is available in the value stack when input parameters are being set, the model driven interceptor is configured for the action. This interceptor should be configured before ParameterInterceptor and staticParameterInterceptor in the interceptor stack. We can use defaultStack as default interceptor stack.
The model object to be pushed into stack cannot be null, hence the model must be initialized before it is returned by getModel() method to be populated and pushed into Value stack. We can initialize model Object at a number point, Struts 2 provides an interface/interceptor duo which can be used to prepare action for execution. The interface to be implemented here is preparable which exposes the prepare () method, and the configuration of PrepareInterceptor makes sure that this method is invoked. So, the flow of execution of various methods can be controlled by the position of interceptors in the interceptor stack. The default stack is the good one to use.

No comments: