Pages Navigation Menu

Coding is much easier than you think

Hello world in Struts 2 – Getting started

In our previous article we learnt that there are 4 basic component in struts 2 framework.
 
They are
1. struts.xml
2. Interceptors
3. Action class
4. JSP
 
Struts 2 high level framework architecture
 
Since interceptor module is available in struts 2 by default, so for simplicity lets us ignore this module as of now and we shall explore then latter.
 
Now ignoring interceptors the flow diagram of struts 2 looks as below.
 
Basic component
 
Now create a Dynamic web project with the following folder structure.
 
Include the below list of commonly used JAR files required by Struts 2 framework to your project’s WEB-INF/lib folder.
 
Hello world in Struts 2
 

    • commons-fileupload-1.2.2.jar
    • commons-io-2.0.1.jar
    • commons-lang-2.4.jar
    • commons-lang3-3.1.jar
    • commons-logging-1.1.1.jar
    • commons-logging-api-1.1.jar
    • freemarker-2.3.19.jar
    • javassist-3.11.0.GA.jar
    • ognl-3.0.6.jar
    • struts2-core-2.3.8.jar
    • xwork-core-2.3.8.jar

 
download
 
Now the role of struts.xml here is to Controls the execution flow of the request
1. It maps the input URL to the action classes
2. It maps the input URL to the Jsp
 
Request flow
 
Now consider a scenario where i receive the input request as http://localhost/login, in this case I need this request to be mapped to a Action class, let assume that action class to be LoginAction.
 

Which Method ?

 
In case of Servlets when a servlet got invoked, then by either doget() or dopost() method will get invoked. But in case of struts 2, when an action class gets invoked then by default execute method will executed, provided the signature of this execute method should be as below

public String execute()

 
Flow of request
 
We can have other method configured in Action class, we will learn about that in our upcoming tutorials
 

Configuring request in struts.xml

 
The struts.xml file needs to be configured with these basic tags, and this file should always present in src folder.
 

<?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="login" class="com.action.LoginAction">

	</action>
</package>
</struts>

 
When a client’s request matches the action name, the framework uses the mapping from struts.xml file to process the request. The mapping to an action is usually generated by a Struts Tag. The action tag ( struts.xml file) specifies the action class to be executed.
 
Here the configuration in struts.xml is incomplete, I have just mapped the request to Action class and we need to map the response from our action class to jsp, once after creating action class we shall come back to configuring struts.xml again.
 
Note

  • In struts.xml we declare a package and wrap the action classes inside.
  • package name= “default”? – Just give any valid unique name.
  • struts-default? – By default, this package extends from struts-default base package, and it is nothing but an xml file present in struts2-core-2.x.x.jar
  • This xml is responsible for invoking series of interceptors which is configured in it. We shall explore about what is role of this struts-default? and what is interceptors? in our latter part of our tutorial series. As of now forget about it :P :)

 

Action class

 

package com.action;

public class LoginAction {

	private String userName;

	public String execute() {
		if (userName.isEmpty()) {
			return "error";
		} else {
			return "success";
		}
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
}

 
Now note that the Action Class returns a string, which can be either “success” or “error”. In struts 2, the controller maps the response from action class to a jsp using this “string”.
 
Lets assume if Action class return “success” then we need to map the response to success page. If Action class returns “error” then we need to map its response to error.jsp.
 
Request and response flow in struts 2
 
Note:

  • The Action class in struts 2 is not required to implement any interface or extend any class i.e, can be simple POJO, and there are four different ways to create an Action class which we shall explore in our upcoming tutorials.
  • In case of struts 1 Action class used will be extending several classes in turn in order to process request and response.

 

Configuring Response struts.xml

 
Earlier we have configured request flow in struts.xml now we have to configure the response via result tag in it as shown below.
 

<?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="login" class="com.action.LoginAction">
		<result name="success">success.jsp</result>
		<result name="error">error.jsp</result>
	</action>
</package>
</struts>

 

Jsp pages

 
Now lets go a head and create jsp pages to receive request and send response back.
Create a new JSP file login.jsp inside the WebContent folder and type in the below code in this JSP file.
 
File : login.jsp use the Struts 2 tags to display username input fields and submit button.
 
File: login.jsp

<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>Login</title>
</head>
<body>
<h3>Struts 2 Hello World</h3>
<s:form action="login">
	<s:textfield name="userName" label="Username" />
	<s:submit value="Submit" />
</s:form>
</body>
</html>
  • In Struts 2, the “userName” will map to the JavaBean property of Action class automatically. In this case, on form submit, the textbox value with name=”userName” will call the corresponding Action’s setUserName(String xx) to set the value
  • We shall explore different types of tags used in struts 2 in our tutorials.
  • Also Note that I have referred taglib at the beginning of jsp, By defenision the Struts Taglib component provides a set of JSP custom tag libraries that help developers create interactive form-based applications. There are several different tags to help with everything from displaying error messages to dealing with nested ActionForm beans.

 
file : success.jsp : A JSP view page to display a welcome message to user.

<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Welcome Page</title>
</head>
<body>
	Hello <s:property value="userName" /> 
</body>
</html>

 
file :error.jsp : A JSP view page to display error message when a wrong user id and password is entered.

<html>
<head>
<title>Error Page</title>
</head>
<body>
    <h3>Login failed</h3>
</body>
</html>

 

Configuring web.xml

 
web.xml is the entry point for any request sent, hence in order to indicate web.xml that this is a struts2 project, and to indicate that the request and response are handled in struts.xml, we have to provide any filter entry in web.xml file as shown below.
 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <display-name>Struts2</display-name>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>
	org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 
That all on building a struts 2 project, now lets go a head and run this application in TomCat Server
 

Demo

 
Since I have given welcome file to be login.jsp in my web.xml, so on running the application in tomcat the login.jsp gets rendered as shown below.
Url: http://localhost:8089/HelloWorldStruts2/
 
Hello world in struts2
 
When you give a non empty value in userName then success page appears
Hello world in struts2_a
 
If you have not entered any value for userName then error page appears as shown below.
Hello world in struts2_b
 
In our next article we will learn about the conceptional difference between struts 2 and servlets
 

About Mohaideen Jamil


Am currently working as a Struts 2 Developer in a reputed IT Organisations. I can help you with teaching Core java and Struts 2. Follow me on Facebook or Google Plus. If you like my tutorials, consider making a donation to this charity, thanks.

  • Hitesh

    I am facing the problem stating

    HTTP status 404

    The requested resource () is not available.

    Please help me to resolve this ASAP

  • Fayaz Ahammed

    When I execute the above code as is , I am facing the below error, Can you please help me in resolving the below issue..

    There is no Action mapped for namespace [/] and action name [login] associated with context path [/HelloWorldStruts2]. – [unknown location]

    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)

    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)

    at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)

    at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)

    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)

    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)

    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)

    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)

    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)

    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)

    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)

    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

    at java.lang.Thread.run(Unknown Source)

    Nov 01, 2015 2:12:01 PM org.apache.struts2.dispatcher.Dispatcher warn

    WARNING: Could not find action or result: /HelloWorldStruts2/login;jsessionid=FE622B545BE37641D11FC906AB2178AF

    There is no Action mapped for namespace [/] and action name [login] associated with context path [/HelloWorldStruts2]. – [unknown location]

    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)

    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)

    at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)

    at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)

    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)

    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)

    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)

    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)

    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)

    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)

    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)

    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

    at java.lang.Thread.run(Unknown Source)

  • Bennett Lan

    Thanks for sharing! I’m a beginner for struts2.
    I do step by step util encountering the following exception:

    The server encountered an internal error that prevented it from fulfilling
    this request.

    java.lang.NullPointerException
    com.action.LoginAction.execute(LoginAction.java:16)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:891)
    ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1293)
    ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
    com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
    ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1369)
    ognl.ASTMethod.getValueBody(ASTMethod.java:90)
    ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    ognl.SimpleNode.getValue(SimpleNode.java:258)
    ognl.Ognl.getValue(Ognl.java:494)
    ognl.Ognl.getValue(Ognl.java:458)
    com.opensymphony.xwork2.ognl.OgnlUtil$2.execute(OgnlUtil.java:309)
    com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecute(OgnlUtil.java:340)
    com.opensymphony.xwork2.ognl.OgnlUtil.getValue(OgnlUtil.java:307)
    com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:423)
    com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:287)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:250)
    org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
    org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

    It drive me crazy since I had checked it so many time and I cannot solve the problem.Please give me some suggestions.

    Regards.

    Bennett.
    2015.4.16

    • http://www.simplecodestuffs.com/ Mohaideen Jamil

      Hi Bennett Lan ,

      In the above code I have not checked for any null pointer exception, the above error occurs when you try to submit the form without typing anything in the userName text box. Just fill the text box with some and hit submit.

      • Bennett Lan

        Thinks for the reply.The problem has been resolved.

  • Avneet

    I am creating a web application in struts 2. I need to read data from an xml file(I have created configuration file for the application). I am not able understand where should I keep this file in the folder structure and how to configure that path so that the java classes can read that.
    I also need to create some text files. When I create those text files, they are not created in project folder.