Working on one of the big web application with struts 2.x ( currently using struts-core 2.3.4.1 )
In this app when I call an action through ajax , after returning from an action, an unrelated some other action getting called. I didn't find the solution even after spending many days.
Later I thought to create simple sample app , which has just two actions, no web service calls, just one jsp, and only one action mapped ( I tried mapping other action too in struts.xml) again the same problem
Please find the code below
Struts Action Class
package lpaction;
public class PlanAction {
public String updatePlan() {
return "PLAN_ACTION_SUCCESS";
}
public String getPlans() {
return "PLAN1_ACTION_SUCCESS";
}
}
JSP Code
<%#page import="org.json.JSONArray"%>
<%#page import="org.json.JSONObject"%>
<%# page contentType="text/html; charset=utf-8" language="java"
import="java.sql.*" errorPage=""%>
<%# taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Client</title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<link rel="icon" href="../images/favicon.png" type="image/png" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="<%=request.getContextPath()%>/js/Libs/utility.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/Libs/jquery1.10.js"> </script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/Libs/ui/jquery-ui.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/Libs/jquery.ba-throttle-debounce.min.js"></script>
<script>
function callme(){
var formdata = "";
console.log("formData = "+formdata);
$.ajax({
type: 'POST',
url: 'plan',
contentType: "application/x-www-form-urlencoded",
async: false,
data :formdata,
cache: false,
processData:false,
datatype: "json",
success: function(response) {
alert("Success"+response);
},
error: function(e) {
alert("Fail");
}
});
}
</script>
</head>
<body>
<div id="wrap">
<input type="button" onclick="callme()"> press me </>
</div>
</body>
</html>
Struts.xml file
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="lessonPlan" extends="json-default">
<action name="plan" class="lpaction.PlanAction"
method="updatePlan">
<result name="PLAN_ACTION_SUCCESS" type="json" />
<result name="PLAN_ACTION_FAIL" type="json" />
</action>
<!-- <action name="plan1" class="lpaction.PlanAction"
method="getPlans">
<result name="PLAN1_ACTION_SUCCESS" type="json" />
<result name="PLAN1_ACTION_FAIL" type="json" />
</action> -->
</package>
</struts>
Web.xml
<?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"
version="2.5">
<filter>
<filter-name>testClient</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>testClient</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
If I put breakpoint in both action methods, the first action method will be called after that second action method will call.
Why second action method is getting called ?
Infact second action is not at all mapped ( Note I tried to uncomment that action mapping in struts.xml, still same problem )
I am using the following JAR files
Reason your getPlans method is called when you call plan action is that the method name starts with get. Since you have not specified any Customized Serialization and Deserialization for your JSON Result everything that starts with get will be Serialized, that means at the time of generating response getPlans method will be called because of Serialization.
You can change the action method name to overcome this issue, also refer this JSON Plugin Documentation for controlling your json object sent in response. If you don't control json object in response it can lead to unintentional data exposure which intern cause security risks and .
Update: As per documents
The serialization process is recursive, meaning that the whole object
graph, starting on the action class (base class not included) will be
serialized (root object can be customized using the "root" attribute)
This means every thing in action will be serialized(so that means every method with prefix get will be called), And this is done with recursion that is going in depth of object excluding base class.
Related
When I try to run my Spring + Struts 2 project on WL Server 9.2 (I have to user this version, so please don't ask me to user the newer version of WL Server), I had this error.
The URL address in the browser is :
http://localhost:7003/SpringStrust2/
Full stacktrace:
The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag. - [unknown location]
at org.apache.struts2.views.jsp.TagUtils.getStack(TagUtils.java:60)
at org.apache.struts2.views.jsp.StrutsBodyTagSupport.getStack(StrutsBodyTagSupport.java:44)
at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:48)
at jsp_servlet.__user._jsp__tag0(__user.java:115)
at jsp_servlet.__user._jspService(User.jsp:12)
at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:283)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3269)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2019)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:1925)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1394)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
Here is my web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>User.jsp</welcome-file>
</welcome-file-list>
struts.xml:
<struts>
<constant name="struts.enble.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.custom.i18n.resources" value="myapp" />
<package name="default" extends="struts-default">
<action name="user" class="user">
<result name="success">/success.jsp</result>
<result name="input">/User.jsp</result>
</action>
</package>
</struts>
user.jsp:
<%# taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring + Struts2</title>
</head>
<body>
<s:form action="user" method="addUser">
<s:textfield name="username" key="user.name" />
<s:submit key="submit" />
</s:form>
</body>
</html>
I'm very sure about putting files in correct folders, including jar libraries in lib folder...
Here is the list of jars I'm using:
antlr-runtime-3.0.jar
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-lang3-3.1.jar
commons-logging-1.1.jar
freemarker-2.3.13.jar
junit-3.8.1.jar
ornl-2.6.11.jar
org.springframework.asm-3.9.9.M3.jar
org.springframework.beans-3.0.0.M3.jar
org.springframework.context-3.0.0.M3.jar
org.springframework.core-3.0.0.M3.jar
org.springframework.web-3.0.0.M3.jar
org.springframework.web.servlet-3.0.0.M3.jar
struts2-convention-plugin-2.1.6.jar
struts2-core-2.1.6.jar
struts2-spring-plugin-2.1.6.jar
xwork-2.1.2.jar
You're hitting the User.jsp file (with its S2 tags) without running through an action like the error says.
You can either:
Redirect to a Struts action from the welcome file (a common technique, and trivial)
configure the container to allow actions as welcome files
Remove the S2 tags from the welcome file
I had the same problem. My Struts 2 application was running on localhost like knife on butter but on VPS it failed. Finally the solution is that Web-Inf folder in project conflicts with web-inf folder of Tomcat.
So move your project/web-inf/web.xml contents to
usr/local/easy/share/easy-tomcat7/conf (for Cent OS)
and move your jars from youtproject/web-inf/lib to
usr/local/easy/share/easy-tomcat7/lib (for Cent OS)
For other OS do the same at respective path..
Hope this will be helpful..
I have learned theory of Struts2 and now practicing. Facing problems while executing project.I searched in Google in many ways but could not find result.Please help me. Below is the code.Please help me friends...
Project structure:
web.xml
<?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>
struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="resources" value="ApplicationResources" />
<constant name="struts.devMode" value="true" />
<package name="default" extends="struts-default">
<action name="login" class="com.practice.structs.actions.LoginAction"
method="validateUser">
<result name="success">pages/homepage.jsp</result>
<result name="error">pages/login.jsp</result>
</action>
</package>
LoginAction.java
package com.practice.structs.actions;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private String userName;
private String password;
public String validateUser(){
if(this.userName.equalsIgnoreCase("abc") && this.password.equalsIgnoreCase("abc"))
{
return "success";
}else{
addActionError(getText("error.login"));
return "error";
}
}
/**
* #return the userName
*/
public String getUserName() {
return userName;
}
/**
* #param userName the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* #return the password
*/
public String getPassword() {
return password;
}
/**
* #param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
}
login.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Login page</title>
</head>
<body>
<H1><I>Login Page</I></H1>
<s:actionerror />
<s:form action="login.action" method="post">
<s:textfield name="uname" key="label.username" size="20"/>
<s:password name="password" key="label.password" size="20"/>
<s:submit method="execute" key="label.login" align="center"/>
</s:form>
</body>
</html>
homepage.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Home Page</title>
</head>
<body>
<H2><I>Welcome</I></H2>
</body>
</html>
change your code like this
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="com.practice.structs.actions.LoginAction"
method="validateUser">
<result name="success">pages/homepage.jsp</result>
<result name="error">pages/![enter image description here][1]login.jsp</result>
</action>
</package>
<s:form action="login" method="post">
<s:textfield name="uname" key="label.username" size="20"/>
<s:password name="password" key="label.password" size="20"/>
<s:submit method="execute" key="label.login" align="center"/>
</s:form>
your action name in form is action.login and in struts.xml is login both should be same and also add the namespace
I know this question is a bit outdated, but I also thought it's worth mentioning, to those who happen to end up stumbling onto this post again and still experiencing the issue; assuming you're 100% sure that your mappings are correct and that your web.xml contains the appropriate filter, try the following:
Stop your Tomcat server
Create a "classes" folder in your "WEB-INF" folder
Move your struts.xml file into the newly created "classes" folder
Right click on your Tomcat Server and select "Clean" - not required, but would recommend doing so.
Start up Tomcat again and hope for the best :-)
As a visual aid, your WEB-INF should end up looking something like this:
If you're still experiencing the issue, double check your struts mappings again, as well as your web.xml
I don't have enough points to respond Ryan's comment nor rate him, but what he says is a valid solution in concrete cases, and I am going to tell why.
Sometimes the folders you create in a project are not taken as resources of the application, and you have to configure it.
Let me explain myself with a practical example that may have occurred to some mates who asked for this problem:
When you are developing with Eclipse, maybe you choose another project explorer than the Eclipse's default "Project Explorer", as the "Navigator", for example.
Using "Navigator" view, you can create folders, but this folders are not package resources (as they are when you create "package resources" with the default "Project Explorer"), so Struts2 cannot find "struts.xml" file to configure the actions.
So, the only folders that your project will process as "package resources" are the ones under WEB-INF as Eclipse do in "Dynamic Web Projects" by default.
So then, be sure of having all the configuration files in a "package resource".
In your LoginAction.java properties you took are
private String userName;
private String password;
But in you login.jsp you wrote as
<s:textfield name="uname" key="label.username" size="20"/>
<s:password name="password" key="label.password" size="20"/>
Change
<s:textfield name="uname" key="label.username" size="20"/> to
<s:textfield name="userName" key="label.username" size="20"/>
I hope this answer solves your problem ...
make the changes on struts.xml file,, add namespace="/" attribute in
like
<package name="default" namespace="/" extends="struts-default">
To solve this problem I had to create a classes folder in WEB-INF and place the struts.xml file there. Then I placed the .jsp files in the web folder and placed '/' before the .jsp files, for example /x.jsp
I am unable to execute my struts2 application. I am using eclipse indigo IDE, tomcat 7 and jdk 1.7.
The jar files I included are:
commons-logging-1.0.4.jar,
freemarker-2.3.8.jar,
ognl- 2.6.11.jar,
struts2-core-2.0.11.jar,
xwork-2.0.4.jar
I placed the struts.xml in classes folder in WEB-INF and I also tried it placing in
src folder but I could not able to make it. I am getting the below error on console
There is no Action mapped for namespace / and action name tutorial. - [unknown location]
index.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="./tutorial.action">
Username: <input type="text" />
<input type="submit" value="Submit" />
</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">
<action name="tutorial" class="com.test.TutorialAction">
<result name="success">/success.jsp</result>
<result name="failure">/failure.jsp</result>
</action>
</package>
</struts>
web.xml
<?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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Struts2Starter</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
TutorialAction.java
package com.test;
public class TutorialAction {
public String execute() {
System.out.println("Hello from execute");
return "success";
}
}
As others have pointed out, you do not have a getTutorial action in your mapping, only a "tutorial". However, I'm going to skip over that and suggest that you learn how to sanity check a Struts2 app. Anytime you are setting up a new technology, and even when you are working with a familiar technology, it is very useful to understand how to do a basic sanity check -- in this case, you need to verify that your struts xml has been successfully parsed and the framework knows about your actions.
I HIGHLY RECOMMEND you add the Struts 2 Config Browser plugin to your struts 2 apps. To add the plugin, you just get the jar ( all struts 2 plugins are jars ) and put in your webapp's lib directory. That's it. When you start your applicaiton, hit this URL:
http://localhost:8080/starter/config-browser/index.action
And it shows you all of the actions, as well as other configurations, that the framework knows about. Essentialy struts 2 diagnostic tool, and too easy to use to not use it.
Try to add namespace attribute into you package element of struts.xml file.
Like this:
<struts>
<package name="default" extends="struts-default" namespace="/">
<action name="tutorial" class="com.test.TutorialAction">
<result name="success">/success.jsp</result>
<result name="failure">/failure.jsp</result>
</action>
</package>
</struts>
I had the same problem and I saw multiple posts on this one....here is the possible solution
I was pretty sure that I had mapped all my actions accurately, but it was showing the same error above....so I just cleaned the project and then ran it again..it worked perfectly fine...give it a try !
I encountered this so many times...so to avoid such kind of things, I just added "../eclipse.exe -clean" to the shortcut icon property....this works and u can forget about getting such kind of errors which is actually not an error....!
The error comes because the server is not able to find correct path for struts.xml .
Its better to put the struts.xml in parallel to src folder or in WEB-INF/classes.
Try this once don't append .action
<form action="tutorial">
place your struts.xml file in src outside the package or in WEB-INF classes folder.
I am unable to execute my struts2 application. I am using eclipse indigo IDE, tomcat 7 and jdk 1.7.
The jar files I included are:
commons-logging-1.0.4.jar,
freemarker-2.3.8.jar,
ognl- 2.6.11.jar,
struts2-core-2.0.11.jar,
xwork-2.0.4.jar
I placed the struts.xml in classes folder in WEB-INF and I also tried it placing in
src folder but I could not able to make it. I am getting the below error on console
There is no Action mapped for namespace / and action name tutorial. - [unknown location]
index.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="./tutorial.action">
Username: <input type="text" />
<input type="submit" value="Submit" />
</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">
<action name="tutorial" class="com.test.TutorialAction">
<result name="success">/success.jsp</result>
<result name="failure">/failure.jsp</result>
</action>
</package>
</struts>
web.xml
<?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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Struts2Starter</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
TutorialAction.java
package com.test;
public class TutorialAction {
public String execute() {
System.out.println("Hello from execute");
return "success";
}
}
As others have pointed out, you do not have a getTutorial action in your mapping, only a "tutorial". However, I'm going to skip over that and suggest that you learn how to sanity check a Struts2 app. Anytime you are setting up a new technology, and even when you are working with a familiar technology, it is very useful to understand how to do a basic sanity check -- in this case, you need to verify that your struts xml has been successfully parsed and the framework knows about your actions.
I HIGHLY RECOMMEND you add the Struts 2 Config Browser plugin to your struts 2 apps. To add the plugin, you just get the jar ( all struts 2 plugins are jars ) and put in your webapp's lib directory. That's it. When you start your applicaiton, hit this URL:
http://localhost:8080/starter/config-browser/index.action
And it shows you all of the actions, as well as other configurations, that the framework knows about. Essentialy struts 2 diagnostic tool, and too easy to use to not use it.
Try to add namespace attribute into you package element of struts.xml file.
Like this:
<struts>
<package name="default" extends="struts-default" namespace="/">
<action name="tutorial" class="com.test.TutorialAction">
<result name="success">/success.jsp</result>
<result name="failure">/failure.jsp</result>
</action>
</package>
</struts>
I had the same problem and I saw multiple posts on this one....here is the possible solution
I was pretty sure that I had mapped all my actions accurately, but it was showing the same error above....so I just cleaned the project and then ran it again..it worked perfectly fine...give it a try !
I encountered this so many times...so to avoid such kind of things, I just added "../eclipse.exe -clean" to the shortcut icon property....this works and u can forget about getting such kind of errors which is actually not an error....!
The error comes because the server is not able to find correct path for struts.xml .
Its better to put the struts.xml in parallel to src folder or in WEB-INF/classes.
Try this once don't append .action
<form action="tutorial">
place your struts.xml file in src outside the package or in WEB-INF classes folder.
I'm currently trying to learn Struts2.
I've created a form, an action to process it, an XML to validate it, and actions in the struts.xml.
Every time the form displays, even the first time, Struts2 tries to validate, so errors are displayed before the user had a chance to complete it.
Here is the relevant code:
<!-- /WebContent/views/user/login.jsp -->
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login Page</title>
<s:head />
</head>
<body>
<h1>Login Page</h1>
<s:form action="executeUser">
<s:textfield key="userBean.userName" />
<s:password key="userBean.password" />
<s:submit align="center" />
</s:form>
</body>
</html>
<!-- /src/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>
<constant name="struts.devMode" value="true" />
<package name="overviewofstruts" extends="struts-default">
<action name="loginUser" class="hu.flux.user.LoginUserAction" method="execute">
<result name="input">/views/user/login.jsp</result>
</action>
<action name="executeUser" class="hu.flux.user.LoginUserAction" method="execute">
<result name="input">/views/user/login.jsp</result>
<result name="success">/views/user/login_thankyou.jsp</result>
</action>
</package>
</struts>
// /src/hu/flux/user/LoginUserAction.java
package hu.flux.user;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginUserAction extends ActionSupport {
private User userBean;
public void setUserBean(User userBean) { this.userBean = userBean; }
public User getUserBean() { return userBean; }
public String login() throws Exception { return this.execute(); }
public String execute() throws Exception { return SUCCESS; }
public String input() throws Exception { return INPUT; }
}
<!-- // /src/hu/flux/user/LoginUserAction-validation.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<validator type="requiredstring">
<param name="fieldname">userBean.userName</param>
<message>Username is required.</message>
</validator>
<validator type="requiredstring">
<param name="fieldname">userBean.password</param>
<message>Password is required.</message>
</validator>
What do I need to do or change to get struts to show the form the first time without complaining about all the blank fields?
Yee, I know this issue. Usually I'm using following work-around.
Mark execute with org.apache.struts2.interceptor.validation.SkipValidation
#SkipValidation
public String execute() throws Exception { return SUCCESS; }
So first pass will ignore validation method. But input will be validated.
The #SkipValidation workaround will do it, but Struts validation already has built-in rules about when it will run (or not) -- it's better to learn the rules so you don't need the extra configuration. It's also worth learning so you aren't confused when validation doesn't run when you need it...
So, short answer: if you change this
<action name="loginUser" class="hu.flux.user.LoginUserAction" method="execute">
to this
<action name="loginUser" class="hu.flux.user.LoginUserAction" method="input">
(notice the method parameter) -- that'll fix the problem (implement the method in your action class as well).
Long answer: Open struts-default.xml, at the root of the struts-core JAR file and browse around. Validation is handled by the "validation" interceptor. Then there's another interceptor called "workflow" that handles automatically showing the "input" result if validation fails, so look at these together.
Find and you'll see this:
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
The excludeMethods refers to the action method parameter, and is for exactly what you're trying to do.
You can also set up your own interceptor stack (modeled on the default, or one of the other examples) and define other excluded methods. Wildcards are supported in the names.