Struts2

Struts 2 standard flow (Struts 2 architecture)

Let's try to understand the standard architecture of struts 2 application by this simple figure:
struts 2 architecture
  1. User sends a request for the action
  2. Container maps the request in the web.xml file and gets the class name of controller.
  3. Container invokes the controller (StrutsPrepareAndExecuteFilter or FilterDispatcher). Since struts2.1, it is StrutsPrepareAndExecuteFilter. Before 2.1 it was FilterDispatcher.
  4. Controller gets the information for the action from the ActionMapper
  5. Controller invokes the ActionProxy
  6. ActionProxy gets the information of action and interceptor stack from the configuration manager which gets the information from the struts.xml file.
  7. ActionProxy forwards the request to the ActionInvocation
  8. ActionInvocation invokes each interceptors and action
  9. A result is generated
  10. The result is sent back to the ActionInvocation
  11. A HttpServletResponse is generated
  12. Response is sent to the user

Struts 2 Custom Validation - Workflow Interceptor

We can define our own validation logic (custom validation) in struts 2 by implementing the Validateable interface in the action class.
The workflow interceptor is used to get information about the error messages defined in the action class.

Workflow Interceptor

The workflow interceptor checks if there is any validation errors or not. It doesn't perform any validation.
It is applied when action class implements the Validateable interface. The input is the default parameter for this interceptor that determines the result to be invoked for the action or field error.
It is found in the defaultStack so we don't need to define it explicitly.

Parameters of workflow interceptor

There is only 1 parameter defined for workflow interceptor.
ParameterDescription
inputResultNamespecifies the result name to be returned if field error or action error is found. It is set to inputbydefault.

Validateabale interface

The Validateable interface must be implemented to perform validation logic in the action class. It contains only one method validate() that must be overridden in the action class to define the validation logic. Signature of the validate method is:
  1. public void validate();  

ValidationAware interface

The ValidationAware interface can accept the field level or action class level error messages. The field level messages are kept in Map and Action class level messages are kept in collection. It should be implemented by the action class to add any error message.

Methods of ValidatationAware interface

The methods of ValidationAware interface are as follows:
MethodDescription
void addFieldError(String fieldName,String errorMessage)adds the error message for the specified field.
void addActionError(String errorMessage)adds an Action-level error message for this action.
void addActionMessage(String message)adds an Action-level message for this action.
void setFieldErrors(Map<String,List<String>> map)sets a collection of error messages for fields.
void setActionErrors(Collection<String> errorMessages)sets a collection of error messages for this action.
void setActionMessages(Collection<String> messages)sets a collection of messages for this action.
boolean hasErrors()checks if there are any field or action errors.
boolean hasFieldErrors()checks if there are any field errors.
boolean hasActionErrors()checks if there are any Action-level error messages.
boolean hasActionMessages()checks if there are any Action-level messages.
Map<String,List<String>> getFieldErrors()returns all the field level error messages.
Collection<String> getActionErrors()returns all the Action-level error messages.
Collection<String> getActionMessages()returns all the Action-level messages.

Note: ActionSupport class implements Validateable and ValidationAware interfaces, so we can inherit the ActionSupport class to define the validation logic and error messages.


Steps to perform custom validation

The steps are as follows:
  1. create the form to get input from the user
  2. Define the validation logic in action class by extending the ActionSupport class and overriding the validate method
  3. Define result for the error message by the name input in struts.xml file

Example to perform custom validation

In this example, we are creating 4 pages :
  1. index.jsp for input from the user.
  2. RegisterAction.java for defining the validation logic.
  3. struts.xml for defining the result and action.
  4. welcome.jsp for the view component.

1) Create index.jsp for input

This jsp page creates a form using struts UI tags. It receives name, password and email id from the user.
index.jsp
  1. <%@ taglib uri="/struts-tags" prefix="s" %>  
  2. <s:form action="register">  
  3. <s:textfield name="name" label="Name"></s:textfield>  
  4. <s:password name="password" label="Password"></s:password>  
  5. <s:submit value="register"></s:submit>  
  6. </s:form>  

2) Create the action class

This action class inherits the ActionSupport class and overrides the validate method to define the validation logic.
RegisterAction.java
  1. package com.javatpoint;  
  2. import com.opensymphony.xwork2.ActionSupport;  
  3.   
  4. public class RegisterAction extends ActionSupport{  
  5. private String name,password;  
  6. public void validate() {  
  7.     if(name.length()<1)  
  8.         addFieldError("name","Name can't be blank");  
  9.     if(password.length()<6)  
  10.         addFieldError("password","Password must be greater than 5");  
  11. }  
  12.   
  13. //getters and setters  
  14.   
  15. public String execute(){  
  16. //perform business logic here  
  17.     return "success";  
  18. }  
  19. }  

3) Define a input result in struts.xml

This xml file defines an extra result by the name input, that will be invoked if any error message is found in the action class.
struts.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts  
  3.  Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">  
  4. <struts>  
  5.   
  6. <package name="default" extends="struts-default">  
  7. <action name="register" class="com.javatpoint.RegisterAction">  
  8. <result>welcome.jsp</result>  
  9. <result name="input">index.jsp</result>  
  10. </action>  
  11. </package>  
  12. </struts>      

4) Create view component

It is the simple jsp file displaying the information of the user.
welcome.jsp
  1. <%@ taglib uri="/struts-tags" prefix="s" %>  
  2. Name:<s:property value="name"/><br/>  
  3. Password:<s:property value="password"/><br/>  

Output

struts 2 custom validation example output 1 struts 2 custom validation example output 2

Defining action level error message

The action level error message works for the whole form. We can define the action level error message byaddActionError() method of ValidationAware interface in validate() method. For example:
  1. package com.javatpoint;  
  2. import com.opensymphony.xwork2.ActionSupport;  
  3. public class RegisterAction extends ActionSupport{  
  4. private String name,password,email;  
  5. public void validate() {  
  6.     if(name.trim().length()<1 || password.trim().length()<1){  
  7.         addActionError("Fields can't be blank");  
  8.     }  
  9. }  
  10.   
  11. //getters and setters  
  12.   
  13. public String execute(){  
  14.     return "success";  
  15. }  
  16. }  
Now you need to use actionerror tag in index.jsp file to display the action level error message.
index.jsp
  1. <%@ taglib uri="/struts-tags" prefix="s" %>  
  2. <s:actionerror/>  
  3. <s:form action="register">  
  4. <s:textfield name="name" label="Name"></s:textfield>  
  5. <s:password name="password" label="Password"></s:password>  
  6. <s:textfield name="email" label="Email Id"></s:textfield>  
  7. <s:submit value="register"></s:submit>  
  8. </s:form>  

Output

struts 2 custom validation example output 1 struts 2 custom validation example output 4