ModelDriven Interceptors in Struts 2
In our last article we have learned how to use a JavaBean class as a property in struts 2 action.
In this tutorial we will learn about Struts 2 support for model objects.
The Model object is a simple JavaBean object, which will be available to action class directly from ValueStack,
i.e we dont need to do deeper referencing to refer its attribute(JavaBeans attribute).
To make a JavaBean object as a model object, our Action class should implement ModelDriven interface which forces the getModel() method to be implemented. This method provides the model object to be pushed into the Value Stack.
Here the getModel() must be invoked earlier for populating its input properties with data from request parameters,
To make sure that the model is available in Value Stack when input parameters are being set, the ModelDrivenInterceptor is configured for the Action in struts.xml.
Most Popular Article for Reference
Since the ModelDriven interceptor is already included in the default stack, we don’t need to inculde modelDriven interceptor explicitly.
** UPDATE: Struts 2 Complete tutorial now available here.
Let’s see a sample example of POJO form, which can be injected in the action as its model.
Bean Class(Model Class)
File : User.java
package com.simplecode.bo; public class User { private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
Action Class
Action class implements the ModelDriven interface, declared the getModel() method to return the user’s object. When the form data is submitted to this action, it will transfers the form data into the user properties automatically.
File : HelloAction.java
package com.simplecode.action; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ModelDriven; import com.simplecode.bo.User; public class HelloAction implements Action,ModelDriven<User> { // Need to initialize model object private User user = new User(); public String execute() { if (user.getUserName().isEmpty()) return ERROR; else return SUCCESS; } public User getModel() { return user; } }
Note:
1. Since the model object to be pushed into ValueStack must not be null hence model must be initialized before returned by getModel() method.
2. We can use only one model object per action class
Do read :
JSP page
JSP pages for the ModelDriven demonstration.
login.jsp
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Login</title> </head> <body> <h3>Struts 2 ModelDriven Example</h3> <s:form action="hello"> <s:textfield name="userName" label="User name"/> <s:submit name="submit" /> </s:form> </body> </html>
success.jsp
<%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Welcome Page</title> </head> <body> Welcome, <s:property value="userName" /> </body> </html>
error.jsp
<%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Error Page</title> </head> <body> Login failed! Please enter a valid user name </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"> <action name="hello" class="com.simplecode.action.HelloAction"> <result name="success">/jsp/success.jsp</result> <result name="error">/jsp/error.jsp</result> </action> </package> </struts>
Demo
http://localhost:8089/ModelDriven/
When I enter a non empty value in the textbox and press submit button, then the application redirects to success page as shown.
On Clicking submit button without any value in textbox, then the application redirects to error page as shown.
Remove .action extension in struts2 and to give user defined extension
In Struts 2, all action class by default has .action as extension.
For example, by default to access an action say LoginAction class, we will use the following URL
** UPDATE: Struts 2 Complete tutorial now available here.
Action URL: http://localhost:8089/Struts2/jsp/Login.action
So in order to remove or to give any user defined extension, just declare a constant “struts.action.extension” in struts.xml and set the value to the extension you wish.
For example to change the extension from .action to .jsp, the following code is used.
<constant name="struts.action.extension" value="jsp"/>
Output URL will be shown like this:-
Action URL: http://localhost:8089/Struts2/jsp/Login.jsp
Suppose If you want to shown empty extension URL try this:-
<constant name="struts.action.extension" value=""/>
Output URL will be shown like this:-
Action URL: http://localhost:8089/Struts2/jsp/Login
Hope This Help You :)
Struts 2 Namespace Configuration
Struts 2 Namespace is a new concept to handle the multiple modules by giving a namespace to each module
- The namespace attribute of element in struts.xml is an optional attribute. The default namespace is “” . i.e. an empty string.
- The value of your namespace must always begin with a “/”.
- Namespaces are used to group together a set of actions.
- An action with the same name can exist in several namespaces. The action that will be invoked depends upon the namespace in which it is called.
** UPDATE: Struts 2 Complete tutorial now available here.
See this picture to understand how an URL matches to Struts 2 action namespace.
1. Final project structure
2. Namespace configuration
Let us go through a Struts 2 namespace configuration example to know how it matches with URL and folder.
The package “name” will not affect the result, just give a meaningful name.
File:struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <action name="default"> <result>jsp/home.jsp</result> </action> </package> <package name="staff" namespace="/staff" extends="struts-default"> <action name="Staff"> <result>/jsp/staff.jsp</result> </action> </package> <package name="student" namespace="/student" extends="struts-default"> <action name="Student"> <result>/jsp/student.jsp</result> </action> </package> </struts>
3. JSP Pages
File:home.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <html> <head> <title>Home</title> </head> <body> <h2> Welcome user</h2> </body> </html>
File:Staff.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Staff home page</title> </head> <body> <h2>Welcome staff</h2> </body> </html>
File:Student.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Student home page</title> </head> <body> <h2>Welcome Student</h2> </body> </html>
4. Mapping - How it works?
Example 1
The URL : http://localhost:8089/Name_Space/student/Student.action
.
Will match the root namespace, and display the content of WebContent/jsp/student.jsp.
<package name="student" namespace="/student" extends="struts-default"> <action name="Student"> <result>/jsp/student.jsp</result> </action> </package>
Example 2
URL : http://localhost:8089/Name_Space/staff/Staff.action
Will match the common namespace, and display the content of WebContent/jsp/staff.jsp
<package name="staff" namespace="/staff" extends="struts-default"> <action name="Staff"> <result>/jsp/staff.jsp</result> </action> </package>
Example 3
URL : http://localhost:8089/Name_Space/default
Will match the common namespace, and display the content of WebContent/jsp/home.jsp.
<package name="default" namespace="/" extends="struts-default"> <action name="default"> <result>jsp/home.jsp</result> </action> </package>
** UPDATE: Struts 2 Complete tutorial now available here.
Given below is the genaralised url
Http://<server>:<port>/<webapp>/<namespace>/<action>.action
|
Read More
Struts 2- Include multiple Struts configuration files
Struts 2 comes with include file- feature to include multiple Struts configuration files into a single unit.
Single Struts configuration file
Bad way of Struts 2 configuration example (From Previous Example).
File:struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <action name="default"> <result>jsp/home.jsp</result> </action> </package> <package name="staff" namespace="/staff" extends="struts-default"> <action name="Staff"> <result>/jsp/staff.jsp</result> </action> </package> <package name="student" namespace="/student" extends="struts-default"> <action name="Student"> <result>/jsp/student.jsp</result> </action> </package> </struts>
** UPDATE: Struts 2 Complete tutorial now available here.
In the above Struts configuration file, it groups all the -student and staff- settings in a single file, which is not recommended and MUST BE AVOID. You should break this struts.xml file into smaller module related pieces. Multiple Struts configuration files In Struts 2, you should always assign each module a struts configuration file. In this case, you can create three files :
- student.xml - Put all student module settings here.
- staff.xml - Put all staff modules settings here.
- struts.xml - Put default settings and include the staff.xml and student.xml.
File:student.xml - Put all student module settings here.
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="student" extends="struts-default"> <action name="Student"> <result>/jsp/student.jsp</result> </action> </package> </struts>
File: Staff.xml – Put all staff modules settings here.
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="staff" extends="struts-default"> <action name="Staff"> <result>/jsp/staff.jsp</result> </action> </package> </struts>
File: Struts.xml – Put default settings and include the staff.xml and student.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <package name="default" namespace="/" extends="struts-default"> <action name="default"> <result>jsp/home.jsp</result> </action> </package> <include file="student.xml"/> <include file="staff.xml"/> </struts>
Final project structure
Read More
Struts 2 FieldError Example
In this section, we are going to describe the fielderror tags. The fielderror tag is a UI tag that renders field errors if they exist.
** UPDATE: Struts 2 Complete tutorial now available here.
1. Folder Structure
2. Properties file
Properties files to store the messages.
LoginAction.properties
password.required = UserName Cannot be blank username.required = Password Cannot be blank details.display = Enter user name as simplecode and password as struts2 to Login login_failed = Login failed
3. Action Class
Develop an action class using addFieldError(String fieldName, String errorMessage)
method
. This method adds an error message for a given field to the corresponding jsp page.
Here the error messages is added to each field individually using the addFieldError() method. The error messages can either be specified in a separate property file or can be added directly in the Action class itself.
package com.simplecode.action; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport { private static final long serialVersionUID = 6677091252031583948L; private String userName; private String password; public String execute() { if (getUserName().equals("simplecode") && getPassword().equals("struts2")) { return SUCCESS; } else { if ("".equals(getUserName()) && "".equals(getPassword())) { addFieldError("userName", getText("username.required")); addFieldError("password", getText("password.required")); return "fielderror"; } if ("".equals(getPassword())) { addFieldError("password", getText("password.required")); return "fielderror"; } if ("".equals((getUserName()))) { addFieldError("userName", getText("username.required")); return "fielderror"; } addFieldError("loginfailed", getText("login_failed")); addFieldError("logindetails", getText("details.display")); return ERROR; } } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
4. JSP View Page
Create a Login jsp page as shown:
File: Login.jsp
Create a jsp page that will display your field error messages (when fails to logged-in) using the empty<s:fielderror/>
tag as shown:
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Login</title> </head> <body> <s:form action="Login"> <s:textfield name="userName" label="User Name" /> <s:password name="password" label="Password" /> <s:submit value="Submit" /> </s:form> </body> </html>
File : Error.jsp
<%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>Un Authorised</title> </head> <body> <s:fielderror /> </body> </html>
File : Success.jsp
<%@taglib uri="/struts-tags" prefix="s"%> <html> <head> <title>Login</title> <s:head /> </head> <body> <h1> Welcome <s:property value="userName" /> , you are logged in successfully </h1> </body> </html>
1. We have done the coding such that If the username and password are empty , then the user will be forwarded to login.jsp where the field error added using addFieldError will get displayed.
2.When the enter username and password is not equal to simplecode & struts2 , then it will be redirected to error.jsp where the tag <s:fielderror/> is used to display the FieldError
5. struts.xml
<!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="/jsp"> <action name="Loginuser"> <result>/jsp/login.jsp</result> </action> <action name="Login" class="com.simplecode.action.LoginAction"> <result name="success">/jsp/success.jsp</result> <result name="error">/jsp/error.jsp</result> <result name="fielderror">/jsp/login.jsp</result> <result name="input">/jsp/login.jsp</result> </action> </package> </struts>
6. Run it
http://localhost:8089/Struts2_ActionError_&_ActionMessage/
When Username and password is empty, display error message with <s:actionerror/>
2
When Username and password is invalid, display error message set by <s:fielderror/>
|
Read More