Exception handling in Struts 2
|
The Struts 2 framework provides some easy way to handle any uncaught exceptions. It works on exception interceptor which is part of default-stack in struts-default.xml file.
There are two ways to handle uncaught exceptions in Struts2:
- Global exception handling: specifies exception mappings which apply to all action classes in a Struts2.
- Exception handling per action: specifies exception mappings which apply to a specific action class.
Both methods require adding exception mappings in struts.xml configuration file.
** UPDATE: Struts 2 Complete tutorial now available here.
Global Exception Handling :
Add the following code snippet just after the <package> element in struts.xml file:
<global-results> <result name="null">/jsp/NullPointer.jsp</result> <result name="globalException">/jsp/GlobalExceptioon.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="null" exception="java.lang.NullPointerException"/> <exception-mapping result="globalException" exception="java.lang.Exception"/> </global-exception-mappings>
<global-exception-mappings> – specifies a set of
<global-results> – element defines global view names and its mapping page.
Here in global-exception-mapping the exception of type java.lang.NullPointerException is mapped to the view name “null”. So when any uncaught exception of type java.lang.NullPointerException or its sub types is thrown, Struts will redirect users to the view page mapped with the name “null” and in
Exception Handling Per Action
If you need to handle an exception in a specific way for a certain action you can use the exception-mapping node within the action node.
// Here an action configuration adds an addition exception handler. <action name="Addition" class="simplecode.action.Addition"> <exception-mapping result="error" exception="java.lang.NumberFormatException" /> <result name="success">/jsp/Success.jsp</result> <result name="error">/jsp/Error.jsp</result> </action>
Here If NumberFormatException occurs in Addition action then Error.jsp will be executed else framework searches in the global exception list and execute the respective page using global-result type.
In the Error page we can access information of the exception as follows:
1. Exception name: <s:property value=”exception”/>
2. Exception stack trace: <s:property value=”exceptionStack”/>
3. Exception in the value stack: <s:property value=”[0].top” />
Implementation – exception handling in Struts 2.
File: Struts.xml
<struts> <package name="default" extends="struts-default"> <global-results> <result name="null">/jsp/NullPointer.jsp</result> <result name="globalException">/jsp/GlobalExceptioon.jsp</result> </global-results> // Here the results are expected to be global results. <global-exception-mappings> <exception-mapping result="null" exception="java.lang.NullPointerException"/> <exception-mapping result="globalException" exception="java.lang.Exception"/> </global-exception-mappings> // Here an action configuration adds an addition exception handler. <action name="Addition" class="simplecode.action.Addition"> <exception-mapping result="error" exception="java.lang.NumberFormatException"/> <result name="success">/jsp/Success.jsp</result> <result name="error">/jsp/Error.jsp</result> </action> <action name="Action1" class="simplecode.action.Action1"> <result name="success">/jsp/Success1.jsp</result> </action> <action name="Action2" class="simplecode.action.Action2"> <result name="success">/jsp/Success1.jsp</result> </action> </package> </struts>
Action class
File: Addition.java
For Exception Handling in Action class – here if both numbers is not parsed in int, it will throw NumberFormatException.
package simplecode.action; import com.opensymphony.xwork2.Action; public class Addition implements Action { private String number1, number2; private String sum = ""; public String getNumber1() { return number1; } public String getNumber2() { return number2; } public void setNumber1(String number1) { this.number1 = number1; } public void setNumber2(String number2) { this.number2 = number2; } public String getSum() { return sum; } public void setSum(String sum) { this.sum = sum; } public String execute() throws Exception { int num1 = Integer.parseInt(number1); int num2 = Integer.parseInt(number2); int sum = num1 + num2; setSum("" + sum); return SUCCESS; } }
File: Action1.java – throw NullPointerException
package simplecode.action; import com.opensymphony.xwork2.Action; public class Action1 implements Action { public String execute() throws Exception { String string = null; System.out.println(string.charAt(7)); return SUCCESS; } }
File: Action2.java – throw NumberFormatException.
package simplecode.action; import com.opensymphony.xwork2.Action; public class Action2 implements Action { public String execute() throws Exception { int num = Integer.parseInt("7b"); return SUCCESS; } }
Jsp Pages
File: index.jsp
<%@ taglib uri="/struts-tags" prefix="s"%> <html> <body> <s:form action="Addition"> <s:textfield label="Number 1" name="number1" /> <s:textfield label="Number 2" name="number2" /> <s:submit label="Add" /> </s:form> <hr> Null Pointer Exception example - <a href="<s:url action="Action1"/>">ActionLink1</a> <br> <br> Global Exception - <a href="<s:url action="Action2"/>">ActionLink2</a> <br> </body> </html>
File : Error.jsp
<%@ taglib uri="/struts-tags" prefix="s"%> <html> <body> <h2>Unexpected error occurred (Exception per Action page)</h2> <p> <font color="red">Please contact your system administrator</font> </p> <h3>Error Message</h3> <br> Exception object transferred to value stack <s:property value="[0].top" /> <br> <s:property value="%{exception}" /> <hr /> <h3>Stack Trace</h3> <s:property value="%{exceptionStack}" /> </body> </html>
File: NullPointer.jsp
<%@taglib uri="/struts-tags" prefix="s"%> <html> <body> <h2>Unexpected error occurred (Global - Null Pointer exception)</h2> <p> <font color="red">Please contact your system administrator</font> </p> <h3>Error Message</h3> Exception object transferred to value stack <s:property value="[0].top" /> <br> <s:property value="%{exception}" /> </body> </html>
File: GlobalException.jsp
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Global - NumberFormatException</title> </head> <body> <h2>Global NumberFormatException occurred</h2> <p> <font color="red">Please contact your system administrator</font> </p> <h3>Error Message</h3> <br> Exception object transferred to value stack <s:property value="[0].top" /> <br> <s:property value="%{exception}" /> </body> </html>
Demo
http://localhost:8089/Struts2Exception/
On giving the input as above the result will be as shown.
Global exception- On clicking ActionLink1 and ActionLink2 the following global exception page will be rendered.
Autocompleter Textbox & dropdown in Struts 2
To create a Autocompleter component in struts 2, please follow this two steps :
1. Add struts2-dojo-plugin.jar in your class path.
2. Include the “struts-dojo-tags” tag and its header(shown below) in your jsp page
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %> <html> <head> <sx:head /> </head>
** UPDATE: Struts 2 Complete tutorial now available here.
Action class
AutoCompleteAction.java
package com.simplecode.action; import java.util.ArrayList; import com.opensymphony.xwork2.Action; public class AutoCompleteAction implements Action { public ArrayList<String> cricketNations = new ArrayList<String>(); public String country; public String execute() { populateCircketNations(); return SUCCESS; } public void populateCircketNations() { cricketNations.add("Australia"); cricketNations.add("England"); cricketNations.add("India"); cricketNations.add("West Indies"); cricketNations.add("New Zealand"); cricketNations.add("Pakistan"); cricketNations.add("Bangladesh"); cricketNations.add("South Africa"); cricketNations.add("Sri Lanka"); cricketNations.add("Zimbabwe"); } public String displayCountry() { return SUCCESS; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } }
Do read: Autocomplete in Struts 2 using Jquery and JSON via Ajax
JSP Page
autoComplete.jsp
Here <%@taglib uri="/struts-dojo-tags" prefix="sx"%> is a directive used in jsp for including dojo ajax tag files.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="/struts-dojo-tags" prefix="sx"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <sx:head /> <head> <title>Auto complete</title> </head> <body> <h3>Auto complete Dropdown | Textbox</h3> <s:form action="displayCountry"> <sx:autocompleter name="country" list="cricketNations" showDownArrow="false" label="Cricket Nations"/> <s:submit /> </s:form> </body> </html>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="struts-default" namespace="/"> <action name="autoComplete" class="com.simplecode.action.AutoCompleteAction"> <result name="success">autoComplete.jsp</result> </action> <action name="displayCountry" class="com.simplecode.action.AutoCompleteAction" method="displayCountry"> <result name="success">WelcomeToCountry.jsp</result> </action> </package> </struts>
Do read: AJAX implementation in Struts 2 using JQuery and JSON
Demo
On running the above example
http://localhost:8089/AutoComplete/autoComplete.action
Setting showDownArrow = “true”
Setting showDownArrow = “false”
|
Read More
Difference between # , $ and % signs in Struts2
Use of #
OGNL is used to refer to objects in the ActionContext as follows:
- myObject: object in the ValueStack, such as an Action property
- #myObject: object in the ActionContext but outside of the ValueStack…
- #myObject: ActionContext object that has been created using the Struts2 data tags with the default action scope (e.g., <s:set name=”data” value=”Some data” />, referenced by<s:property value=”#data” />)
- #parameters.myObject: request parameter
- #request.myObject: request-scoped attribute
- #session.myObject: session-scoped attribute
- #application.myObject: application-scoped attribute
- #attr.myObject: attribute in page, request, session, or application scope, searched in that order.
** UPDATE: Struts 2 Complete tutorial now available here.
The scoped map references above (parameters, request, session, and application) can be made one of two ways:
1. #scopeName['myObject'] 2. #scopeName.myObject
Use of $
Struts2 OGNL does not make use of the dollar sign. However, it can be used to evaluate JSTL expressions. For example:
Struts2: <s:property value="someProperty" /> (is equivalent to) JSTL: ${someProperty}
Use of %
% character is used to force OGNL evaluation of an attribute that would normally interpreted as a String literal. For eample,
<s:url id="urlAtt" action="urlTag.action"> <s:a href="%{urlAtt}">Call Action</s:a>
Now <s:a> tag will query the stack for urlAtt value.
Read More
Common Support class for Action classes in Struts 2
When you are about to create a complex application in struts 2, it is better to create a Base action class for all your actions and make this class extend ActionSupport and implement all necessary interfaces such as SessionAware, ParameterAware, HttpServletRequest, HttpServletResponse etc and implement all other common logic for your actions in this class. So now when you are about to create an action class, just extending this support class will suit all your need in action class.
** UPDATE: Struts 2 Complete tutorial now available here.
Following is a snippet of my ApplicationSupportAction class:
import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.interceptor.ParameterAware; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public abstract class ApplicationSupportAction extends ActionSupport implements SessionAware, ServletRequestAware, ParameterAware, ServletResponseAware { private static final long serialVersionUID = 1L; // Field to store session context. private Map<String, Object> session; // Field to store request parameters. private Map<String, String[]> parameters; // Field to store HttpServletRequest. private HttpServletRequest servletRequest = null; // Field to store HttpServletResponse. private HttpServletResponse servletResponse = null; // Result code for session expired action. public final static String SESSION_EXPIRED = "SessionExpired"; // Result code for Logout action. public final static String LOGOUT = "logout"; // ..... // action to be triggered when session expires public String execute() throws Exception { HttpSession sessionObj = servletRequest.getSession(true); if (sessionObj.getAttribute("currentUser") == null) { return SESSION_EXPIRED; } return executeAction(); } public abstract String executeAction() throws Exception; @Override public void setSession(Map<String, Object> session) { this.session = session; } @Override public void setParameters(Map<String, String[]> parameters) { this.parameters = parameters; } @Override public void setServletResponse(HttpServletResponse servletResponse) { this.servletResponse = servletResponse; } @Override public void setServletRequest(HttpServletRequest servletRequest) { this.servletRequest = servletRequest; } public Map<String, Object> getSession() { return session; } public Map<String, String[]> getParameters() { return parameters; } public HttpServletRequest getServletRequest() { return servletRequest; } public HttpServletResponse getServletResponse() { return servletResponse; } public String getCurrentUser() { return (String) session.get("currentUser"); } public void setCurrentUser(String currentUser) { session.put("currentUser", currentUser); } }
You can handle following common concerns in the ApplicationSupportAction class:
1. Session
2. Parameters
3. Http Request and response
4. Validating session.
5. Common result codes etc.
ApplicationSupportAction class would reduce your action class code to a large extent by handling lot of common concerns in one centralized place.
Read More
iterator tag example in Struts 2
Struts 2 Iterator will iterate over a value. An iterable value can be any of: java.util.Iterator,java.util.Collection.
In this tutorials, we will create a list and use Iterator tag to loop over it and get the iterator status with IteratorStatus.
Using IteratorStatus object one can get information about the status of the iteration, such as:
index: current iteration index, starts on 0 and increments in one on every iteration
count: iterations so far, starts on 1. count is always index + 1
first: true if index == 0
last: true if current iteration is the last iteration
even: true if (index + 1) % 2 == 0
odd: true if (index + 1) % 2 == 1
** UPDATE: Struts 2 Complete tutorial now available here.
Jsp -Iterator example
<%@taglib prefix="s" uri="/struts-tags"%> <title>Students Details</title> <style type="text/css"> .odd { background-color: silver; } .even { background-color: white; } </style> <html> <body> <h4>Simple Iterator</h4> <table> <tr> <td width="20%">RollNo</td> <td width="20%" >Student Name</td> <td width="20%">Department</td> <td width="20%">Percentage</td> </tr> <s:iterator value="students"> <tr> <td width="20%"><s:property value="rollNo" /></td> <td width="20%" ><s:property value="studentName"/></td> <td width="20%"><s:property value="department"/></td> <td width="20%"><s:property value="percentage"/></td> </tr> </s:iterator> </table> <br/> <h4>Iterator with Iterator Status</h4> <table> <tr> <td width="10%">So No</td> <td width="20%">RollNo</td> <td width="20%" >Student Name</td> <td width="20%">Department</td> <td width="20%">Percentage</td> </tr> <s:iterator value="students" status="rowstatus"> <tr class="<s:if test="#rowstatus.odd == true ">odd</s:if><s:else>even</s:else>"> <td><s:property value="#rowstatus.count"/></td> <td width="20%"><s:property value="rollNo" /></td> <td width="20%" ><s:property value="studentName"/></td> <td width="20%"><s:property value="department"/></td> <td width="20%"><s:property value="percentage"/></td> </tr> </s:iterator> </table> </body> </html>
Recommended reading :
Action Class
package com.simplecode.action; import java.util.ArrayList; import java.util.List; import com.opensymphony.xwork2.ActionSupport; import com.simplecode.form.StudentBean; public class StudentAction extends ActionSupport { private static final long serialVersionUID = 1L; private List<StudentBean> students = new ArrayList<StudentBean>(); public String fetchStudentList() { students.add(new StudentBean("o7ba062", "Lavanya", "IT", 70)); students.add(new StudentBean("o7bb040", "Jaya Prakash", "ECE", 86)); students.add(new StudentBean("o7bd047", "Sundar", "MECH", 85)); students.add(new StudentBean("o7bb039", "Ibrahim Sha", "ECE", 85)); students.add(new StudentBean("o7bb009", "Aswin", "ECE", 84)); students.add(new StudentBean("o7ba027", "Nilafar", "IT", 82)); students.add(new StudentBean("o7bc079", "Nisha", "CSC", 81)); return SUCCESS; } public List<StudentBean> getStudents() { return students; } public void setStudents(List<StudentBean> students) { this.students = students; } }
Demo
Also read :
If, Else, ElseIf Conditional/Control tag example in Struts 2
Struts 2 If, ElseIf and Else tags are used to perform basic condition checking.
These are the following scenario in real world application to check the condition.
1. Condition checking using Boolean variable.
2. Condition checking using String object.
3. Condition checking using collection object / bean object
4. Condition checking using integer data type
** UPDATE: Struts 2 Complete tutorial now available here.
Now see the example on these scenario one by one.
1. Condition checking using Boolean variable.
<s:if test="booleanValue"> returning TRUE. </s:if> <s:else> returning FALSE. </s:else>
2. Condition checking using String object.
<s:if test="%{stringValue==null}"> string is null </s:if> <s:else> string is not null </s:else>
3. Condition checking using collection object / bean object
<s:if test="%{arrayList.size()==0}"> object size is zero </s:if> <s:else> object size is greater than zero </s:else>
4. Condition checking using integer data type
<s:if test="%{integerValue==0}"> integer is zero </s:if> <s:elseif test="%{integerValue > 0}"> integer is greater than zero </s:elseif> <s:else> integer is lesser than zero </s:else>
Recommended reading :
Jsp Page
On embedding all the above scenario in a complete Jsp page
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>ControlTag - If Else Condition</title> </head> <body> <h4>Control Tag</h4> // For Boolean Value <s:if test="booleanValue"> returning TRUE. </s:if> <s:else> returning FALSE. </s:else> // For String Value <s:if test="%{stringValue==null}"> string is null </s:if> <s:else> string is not null </s:else> // For Integer Value <s:if test="%{integerValue==0}"> integer is Zero </s:if> <s:elseif test="%{integerValue > 0}"> integer is greater than zero </s:elseif> <s:else> integer is lesser than zero </s:else> // For Object Value <s:if test="%{arrayList.size()==0}"> object size is zero </s:if> <s:else> object size is greater than zero </s:else> </body> </html>
Do Read :
Acion Class
package com.simplecode.action; import java.util.ArrayList; import java.util.List; import com.opensymphony.xwork2.Action; public class ControlTag implements Action { private List<String> arrayList = new ArrayList<String>(); private String stringValue; private boolean booleanValue; private int integerValue; public String execute() { arrayList.add("Simple"); arrayList.add("Code"); arrayList.add("Stuffs"); integerValue = -2; booleanValue = true; stringValue = "someValues"; return SUCCESS; } public List<String> getArrayList() { return arrayList; } public void setArrayList(List<String> arrayList) { this.arrayList = arrayList; } public String getStringValue() { return stringValue; } public void setStringValue(String stringValue) { this.stringValue = stringValue; } public boolean isBooleanValue() { return booleanValue; } public void setBooleanValue(boolean booleanValue) { this.booleanValue = booleanValue; } public int getIntegerValue() { return integerValue; } public void setIntegerValue(int integerValue) { this.integerValue = integerValue; } }
Demo
On runnig the application