In Struts2, can we have both validation xml (ActionClass-method-validation.xml) and validate method implemented in Action class.
I was asking as this validation xml don't get invoked in my situation.
hope you have created proper rule file actionname-validation.xml (note- actionname is case sensitive) and kept it in same package as of Action class.
Also, if you do not have default interceptor configured then please add validation interceptor in Struts.xml within that particular action tag.
<action name="welcome" class="com.abc.web.WelcomeAction">
<interceptor-ref name="validation" />
<result name="success" >hello.jsp</result>
</action>
Refer for more details about Validation framework at
http://struts.apache.org/2.0.14/docs/validation.html and http://java.dzone.com/articles/struts2-tutorial-part-37
<?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>
<field name = "firstname">
<field-validator type = "stringlength">
<param name = "minlength">3</param>
<param name ="maxlength">18</param>
<message>Please Enter Your First Name</message>
</field-validator>
</field>
<field name = "lastname">
<field-validator type = "required">
<message>Please Enter Your Last Name</message>
</field-validator>
</field>
<field name = "mobilenumber">
<field-validator type = "int">
<message>Please Enter Your Mobile Number</message>
</field-validator>
</field>
<field name = "dob">
<field-validator type = "date">
<message>Please Enter Your Date Of Birth</message>
</field-validator>
</field>
<field name = "emailid">
<field-validator type = "email">
<message>Please Enter Email ID Correctly</message>
</field-validator>
</field>
<field name = "hometown">
<field-validator type = "required">
<message>Please Enter Your Home Town</message>
</field-validator>
</field>
<field name = "currentcity">
<field-validator type = "required">
<message>Please Enter Your Current City</message>
</field-validator>
</field>
<field name = "username">
<field-validator type = "stringlength">
<param name = "minlength">3</param>
<param name ="maxlength">18</param>
<message>Please Enter Your User Name</message>
</field-validator>
</field>
<field name = "password">
<field-validator type = "stringlength">
<param name = "minlength">8</param>
<message>Password must Contain minimum of 8 Characters</message>
</field-validator>
</field>
<validator type = "expression">
<param name = "expression">password.equals(password1)</param>
<meaasage>Passwords Does Not Match</message>
</validator>
</validators>
Just go through it and check whether its correct
Related
I'm using Struts2 (version 2.5.14.1) with the Spring and Tiles plug-ins.
This is my (relevant) struts.xml configuration:
<package name="enrollment" namespace="/enrollment" extends="struts-bean-validation">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<action name="start" class="io.shido.struts.action.enrollment.StartAction">
<result name="success" type="tiles">enrollment.start.tiles</result>
</action>
<action name="personal-info" class="io.shido.struts.action.enrollment.PersonalInfoAction">
<result name="input" type="tiles">enrollment.personal-info.tiles</result>
<result name="success" type="tiles">enrollment.billing-info.tiles</result>
</action>
<action name="billing-info" class="io.shido.struts.action.enrollment.BillingInfoAction">
<result name="input" type="tiles">enrollment.billing-info.tiles</result>
<result name="success" type="tiles">enrollment.finish.tiles</result>
</action>
<action name="finish" class="io.shido.struts.action.enrollment.FinishAction">
<result name="success" type="tiles">enrollment.finish.tiles</result>
</action>
</package>
...the JSP file that holds one of the forms:
<%# taglib prefix="s" uri="/struts-tags" %>
<link rel="stylesheet" href="<s:url value='/resources/styles/enrollment.styles.css' />">
<s:form cssClass="form-input-info" action="personal-info" method="post">
<legend><s:text name="legend.text" /></legend>
<hr>
<s:textfield cssClass="form-control" key="textfield.first-name" name="personalInfo.firstName" />
<s:textfield cssClass="form-control" key="textfield.last-name" name="personalInfo.lastName" />
<s:textfield cssClass="form-control" key="textfield.email" name="personalInfo.email" />
<s:textfield cssClass="form-control" key="textfield.phone-number" name="personalInfo.phoneNumber" />
<s:textfield cssClass="form-control" key="textfield.age" name="personalInfo.age" />
<s:submit class="btn btn-primary btn-lg btn-block" key="submit.continue" />
</s:form>
...and finally the (super simple) Action class:
package io.shido.struts.action.enrollment;
// imports
public final class PersonalInfoAction extends ActionSupport {
private static final long serialVersionUID = 3560814234131884357L;
private final Logger logger = LogManager.getLogger(this.getClass());
private PersonalInfoHandler handler;
#Valid
private PersonalInfo personalInfo;
#Override
public String execute() {
// If personalInfo is not null is guaranteed to be valid due to Bean Validation contraints
if (null != personalInfo) {
logger.debug("Processing personal info...");
handler.save(personalInfo);
return Action.SUCCESS;
}
logger.info("Collecting personal info...");
return Action.INPUT;
}
public PersonalInfoHandler getHandler() { return handler; }
public void setHandler(final PersonalInfoHandler handler) { this.handler = handler; }
public PersonalInfo getPersonalInfo() { return personalInfo; }
public void setPersonalInfo(final PersonalInfo personalInfo) {
this.personalInfo = personalInfo;
this.personalInfo.normalize();
}
}
The issue is, whenever I submit that form, I'm expecting the Bean Validation to kick out and check all the annotated fields (check, this is happening) and when everything is fine, send the flow to /WEB-INF/content/enrollment/billing-info.jsp (defined in Tiles by enrollment.billing-info.tiles)...but all I see is (almost) the "billing info" form with the wrong labels. See the below picture:
The URL should have changed, as well as the labels. To put the cherry on top, if I click the Continue button again, the form is displayed then correctly.
Any clues?
I have no direct answer but you could try to use a redirect action instead of using the tiles several times.
So you could try this here:
<action name="personal-info" class="io.shido.struts.action.enrollment.PersonalInfoAction">
<result name="input" type="tiles">enrollment.personal-info.tiles</result>
<result name="success" type="redirectAction">
<param name="actionName">billing-info</param>
</result>
</action>
And if you need to transfer some kind of id to show the data you can use additional params in the struts.xml like this:
<!-- rest as above -->
<result>
<param name="param1">${value1}</param>
</result>
The param1 must have valid getter/setter-methods in both actions to transfer the information.
I have a search box on my index page, it is supposed to return a message if no result was found or redirect to result page if it succeeded.
Currently, if results were found it redirects to the new page, and if not will stay on the same page (index) but it does not show the message, just add the mymessage parameter to the page address as following
www.address.com/index.jsp?mymessage=Sorry,No+results+were+found.
Index
.......
<s:property value="mymessage"/>
SearchBox
public String search(){
....
if(found)
return "success";
else
return "failed;
}
struts.xml
<package name="Search" extends="default" namespace="/Search">
<action name="*" method="{1}" class="com.myproject.myclasses.Search">
<result name="success" type="tiles">search</result>
<result name="failed" type="redirectAction">
<param name="actionName">index</param>
<param name="namespace">/</param>
<param name="mymessage">${mymessage}</param>
</result>
</action>
</package>
I think <s:property> expects a getter getMyMessage() on your action class to populate
values can you try <s:property value="#request.mymessage" />
OR
Why can't you use action errors?
public String search(){
....
if(found) {
return "success";
}
else {
addActionError("No results found");
return "failed;
}
}
Now in the index.jsp add the following,
<s:if test="hasActionErrors()">
<s:iterator value="actionErrors">
<s:property escape="false"/>
</s:iterator>
</s:if>
I am using Struts 2 Validator framework with XML. But the server side validations are not working. Following is the code snippet.
Struts.xml
<interceptor-stack name="MyStack">
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,.*\\.*,.*\(.*,.*\).*,.*#.*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,reset</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse,reset</param>
</interceptor-ref>
</interceptor-stack>
<action name="process" method="process" class="org.web.action.MyAction">
<interceptor-ref name="MyStack" />
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
<result name="wait">wait.jsp</result>
<result name="input">Index.jsp</result>
</action>
MyAction.java
public class MyAction extends ActionSupport {
private String amount;
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String process() throws Exception {
//some processing done here
}
}
MyAction-process-validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"##xwork.validator.dtd##">
<validators>
<field name="amount">
<field-validator type="requiredstring" short-circuit="true">
<message key="order.amount.required"/>
</field-validator>
<field-validator type="amountValidator" short-circuit="true">
<message key="order.amount.invalid" />
</field-validator>
</field>
</validators>
AmountValidator.java
public class AmountValidator extends FieldValidatorSupport {
public Struts2DonationAmountValidator() {
super();
}
public void validate(Object object) throws ValidationException {
//some validation check here
}
}
validators.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator Config 1.0//EN"
"https://s3.amazonaws.com/static/xwork-validator-config-1.0.dtd">
<validators>
<validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator" />
<validator name="amountValidator" class="org.web.validator.AmountValidator"/>
</validators>
Index.jsp
<input type="text" id="amountTemp" name="amount">
I have put sysouts at the first line of validator as well as in action method. The sysout in AmountValidator.java is not called. Even while debugging, the validation doesn't get called and the control jumps to action method. There is no hint of any exception in console. The action method flow works fine.
Thanks in advance!!!
I found a other solution on http://struts.apache.org/release/2.1.x/docs/validation.html. I changed the name of my MyAction-process-validation.xml to MyAction-processAction-validation.xml and named my action as processAction instead of process. That means instead of method I used action name.
Thanks for your support.
I have following simple code for login & secured login. For secured login I am using tokenSession interceptor at the time of form submit . In success.jsp I am unable to get the userId value if I submit secureLogin but fine with Login . Can anyone pls help me what is the reason behind it.
<%# taglib prefix="s" uri="/struts-tags" %>
<html>
<body><LOGIN.JSP>
<s:form action="login" >
<s:textfield name="userId" label="Login Id"/><br>
<s:password name="password" label="Password"/><br>
<s:submit value="Login" align="center"/>
</s:form>
<s:form action="secureLogin" >
<s:textfield name="userId" label="Login Id"/><br>
<s:password name="password" label="Password"/><br>
<s:token />
<s:submit value="secureLogin" align="center"/>
</s:form>
</body>
</html>
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="tokenSession" class = "org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
</interceptors>
<global-results>
<result name="invalid.token">/error.jsp</result>
</global-results>
<action name="secureLogin" class="com.actions.HelloAction" method="secureLogin">
<result name="success">/success.jsp</result>
<result name="failure">/login.jsp</result>
<interceptor-ref name="tokenSession" />
</action>
<action name="login" class="com.actions.HelloAction" method="login">
<result name="success">/success.jsp</result>
<result name="failure">/login.jsp</result>
</action>
</package>
</struts>
package com.actions;
public class HelloAction {
private String userId;
private String password;
public String execute() {
return "success";
}
public String login(){
return "success";
}
public String secureLogin(){
return "success";
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
<%# taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>SUCCESS.JSP</title>
</head>
<body>
Welcome <b><s:property value="userId"/></b> , you have loged in. <br />
</body>
</html>
you need a interceptor-stack
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="tokenSession" class = "org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
<interceptor-stack name="yourStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="tokenSession"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="yourStack"/>
<global-results>
<result name="invalid.token">/error.jsp</result>
</global-results>
</package>
</struts>
Here is a link: Interceptors
When I am using Interceptors, the values on Action class coming as null. I have removed the Interceptors, the values coming perfect from the JSP page.
Login.jsp
<s:form id="loginFrm" name="loginFrm" action="LoginAction">
<s:textfield key="username"/>
<s:password key="password"/>
<s:submit/>
</s:form>
LoginAction.java
public class LoginAction {
private static Logger LOGGER = Logger.getLogger(LoginAction.class);
private String username;
private String password;
public String execute() throws Exception {
LOGGER.info("LoginAction : authenticate()");
LOGGER.info("LoginAction : {[" + username + "],["+password+ "]}");
return "success";
}
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;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Bulk Fund Switching</display-name>
<context-param>
<param-name> org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG </param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener </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>jsp/Login.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml (working version)
<?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="false" />
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="BFSView,BFSMessages" />
<package name="home-default" extends="struts-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="AuthenticationInterceptor" class="com.lv.bfs.controller.interceptor.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="SecureStack">
<interceptor-ref name="AuthenticationInterceptor" />
</interceptor-stack>
</interceptors>
<action name="LoginAction" class="com.lv.bfs.controller.action.LoginAction">
<result name="success">jsp/Welcome.jsp</result>
<result name="error">/jsp/Login.jsp</result>
</action>
</package>
</struts>
struts.xml (Not working version )
<?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="false" />
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="BFSView,BFSMessages" />
<package name="home-default" extends="struts-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="AuthenticationInterceptor" class="com.lv.bfs.controller.interceptor.AuthenticationInterceptor"></interceptor>
<interceptor-stack name="SecureStack">
<interceptor-ref name="AuthenticationInterceptor" />
</interceptor-stack>
</interceptors>
<action name="LoginAction" class="com.lv.bfs.controller.action.LoginAction">
<interceptor-ref name="SecureStack"></interceptor-ref>
<result name="success">jsp/Welcome.jsp</result>
<result name="error">/jsp/Login.jsp</result>
</action>
</package>
</struts>
AuthenticationInterceptor.java
public class AuthenticationInterceptor extends AbstractInterceptor {
private static Logger LOGGER = Logger.getLogger(AuthenticationInterceptor.class);
private static final long serialVersionUID = 1844249996954274967L;
public String intercept(ActionInvocation invocation) throws Exception {
LOGGER.info("intercept : START");
return invocation.invoke();
}
}
Logs statements (both cases)
12:39:05,533 INFO [AuthenticationInterceptor] intercept : START
12:39:05,533 INFO [LoginAction] LoginAction : authenticate()
12:39:05,533 INFO [LoginAction] LoginAction : {[null],[null]}
12:09:05,533 INFO [LoginAction] LoginAction : authenticate()
12:09:05,533 INFO [LoginAction] LoginAction : {[admin],[admin]}
Any suggestions?
When you define an interceptor stack for a specific action you must define all the interceptors for that action. In this case, you are only defining your custom interceptor, meaning the "params" interceptor doesn't run, so the action properties won't be set.
Either define a new stack that includes the normal S2 interceptors, or include those interceptors (or stack) in your action configuration.