How to validate specific action using XML configuration in Struts 2 - java

I want to validate specific method only in action class.
Action method is this.
public String add() throws Exception {
// aflag = true;
org.setAoName(aoName);
orgBo.addOrg(org);
orglist = orgBo.searchOrg(organisationSearch);
setAoName("");
setAflag("viewaddorgs");
return "add";
}
Problem is currently I have many action methods in action class. When I call those methods it validate this method. Please help me to validate only this method by XML.
This is my OraganisationAction-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="aoName">
<field-validator type="requiredstring">
<message>
The name is required!
</message>
</field-validator>
<field-validator type="requiredfield">
<message>
The name is required!
</message>
</field-validator>
</field>
</validators>
This is my JSP :
<s:form id="post" action="addorgs" validate="true" >
<s:textfield name="aoName" label="Add Organisations" />
</s:form>
struts xml :
<package name="default" extends="struts-default">
<result-types>
<result-type name="tiles"
class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<action name="*security" class="com.ast.action.admin.SecurityAction"
method="{1}">
<result name="second" type="tiles">secondTemplate</result>
<result name="pass" type="tiles">orgTemplate</result>
</action>
<action name="*orgs" class="com.ast.action.admin.OraganisationAction"
method="{1}">
<result name="viewadd" type="tiles">orgAddTemplate</result>
<result name="input" type="tiles">orgAddTemplate</result>
<result name="add" type="tiles">orgAddTemplate</result>
<result name="addtbl" type="tiles">orgAddTemplate</result>
<result name="search" type="tiles">orgTemplate</result>
<result name="delete" type="tiles">orgTemplate</result>
<result name="viewedit" type="tiles">orgEditTemplate</result>
<result name="edit" type="tiles">orgEditTemplate</result>
<result name="edittbl" type="tiles">orgEditTemplate</result>
<result name="orgmenu" type="tiles">orgTemplate</result>
<result name="view" type="tiles">orgViewTemplate</result>
</action>
it works with annotations but with XML no success yet.

To exclude some methods from validation you can override parameters of the validation interceptor. For example in interceptor stack you can write
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse,yourmethod</param>
</interceptor-ref>
in the action configuration you can use above code and
<interceptor-ref name="defaultStack">
<param name="validation.excludeMethods">input,back,cancel,browse,yourmethod</param>
</interceptor-ref>
Note yourmethod is a method name.
You can specify a validation.xml for only one action by a postfix of action name in this file. For example AcrionClass-add-validation.xml will work only for the action name add in the action config. Note here add is an action name, not a method name.
Often, the name attribute matches the method name, but they may also differ.

I had similar problems but then these are couple of things that i rectified :
1) DOCTYPE in the yourAction-yourAlias-validation.xml should be
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
2)Created a custom interceptor to exclude the methods that need not be validated.Below is a sample for my candidate registration where i had to skip validation for district method which fetched districts for a state.
<interceptor-stack name="clientValidation">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,district</param>
</interceptor-ref>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<package name="registration" namespace="/candidate" extends="struts-default">
<action name="candidateRegistration" class="com.app.action.CandidateAction">
<interceptor-ref name="clientValidation"/>
<result name="input">/jsps/student/studentregistration.jsp</result>
<result name="failure1">/jsps/student/registrationfailure.jsp</result>
<result name="cancelRegistration">/jsps/login.jsp</result>
<result name="district">/jsps/includes/dropdown_districts_regoffice.jsp</result>
</action>
</package>

Use an action alias: map different methods of an Action to different action aliases in struts.xml, and instead of the single yourAction-validation.xml file, add a yourAction-yourAlias-validation.xml for the validators you want to perform for that method only.
Read more here.
EDIT
No its not validation anything now.
<validators>
<field name="aoName">
<field-validator type="required">
<message>You cannot leave the aoName address field empty.</message>
</field-validator>
</field>
</validators>
name is OraganisationAction-add-validation.xml and put it with action class package. Is there anything to enable validation in struts.xml ?
If you have a correctly configured (for example the default) Interceptor Stack, validation is already enabled. If you are using a file named OraganisationAction-add-validation.xml, that means that:
your action CLASS must be named OraganisationAction.java;
your action mapping in struts.xml must be the following:
<action name="add" class="your.package.OraganisationAction" method="add">
<result>yourResult.jsp</result>
</action>
Look for typos, check your Interceptor Stack, and it will work automatically.

Related

Interceptor not getting called in Struts

My interceptor (validation) is not getting called before or after the action. Any ideas how to get it work ?
Note : Everytime the default interceptor is being called.
<?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" namespace="/" extends="struts-default,json-default">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>
<interceptors>
<interceptor name="validation" class="ValidatorBaseAction"/>
<interceptor-stack name="default">
<interceptor-ref name="logger"/>
</interceptor-stack>
<interceptor-stack name="validationStack">
<interceptor-ref name="validation"/>
<interceptor-ref name="default"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="default" />
<action
name="viewRequest"
class="ViewAction"
method="execute">
<interceptor-ref name="validationStack" />
<result name="input" type="redirectAction">explore</result>
<result name="success" type="redirect">/showRequest.do?${explorerParameters}</result>
</action>
</package>
</struts>
Main problem:
class both for Actions and Interceptors must specify the FQCN, not only the name. Then change it to something like:
<interceptor name="validation" class="com.foo.bar.ValidatorBaseAction"/>
and also change your action to
<action name="viewRequest" class="com.foo.bar.ViewAction" method="execute">
Side problems:
Don't call it ValidatorBaseAction if it is an Interceptor, call it ValidatorBaseInterceptor. And ensure there is nothing of an Action inside it;
Don't use an Interceptor Stack with only one Interceptor, I'm pretty sure it would be useless in 99% of the cases. If you are not sure, just use the defaultStack, adding your interceptor to it.
Polishing:
json-default already extends struts-default, so this
<package ... extends="struts-default,json-default"
is equivalent to this
<package ... extends="json-default"
that is cleaner;
Since you extends json-default, you don't need to redefine the JSON result, then remove
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
that is useless.
Try always to prefer redirectAction result when redirecting to an Action, and use redirect result only when redirecting to other resources or external URLs

Struts 2 get all namespaces and actions from xml

I'm new to Struts 2 overall and would like to know, if there is a way to get a list of all the namespaces and actions for each namespace that is defined in the xml?
I have a package and I am including configurations for each namespace:
<include file="struts_someNamespace1.xml" />
<include file="struts_someNamespace2.xml" />
<include file="struts_someNamespace3.xml" />
Each of those XML files is defined similar to this (this has less code):
<package name="somePackage" namespace="/someNamespace1" extends="default">
<action name="firstAction" class="com.someAction">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="json"> </interceptor-ref>
<result type="json"> </result>
</action>
<action name="secondAction" class="com.otherAction">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="json"> </interceptor-ref>
<result type="json"> </result>
</action>
</package>
Is there a way using some utility class where I can get a list or of each namespace and its actions?
Example Results (in JSON)
{
"someNamespace1": ["firstAction","secondAction"},
"someNamespace2": ["about","home"]
}
Take a look on the Config Browser plugin, it allows browse (almost) all configuration options.
https://git-wip-us.apache.org/repos/asf?p=struts.git;a=blob;f=plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ConfigurationHelper.java;h=536435f84a7bd818c3051b92fdc94c06cdaa40f6;hb=refs/heads/develop

Struts2 localize interceptor

I'm trying to create an Interceptor able to change the language but I can not change it.
Relevant Interceptor code:
public String intercept(ActionInvocation invocation) throws Exception {
ActionMapping mapping = (ActionMapping) invocation
.getInvocationContext()
.get(ServletActionContext.ACTION_MAPPING);
Map<String, Object> params = mapping.getParams();
if (params != null) {
Locale locale = (Locale) params.remove(LOCALE_PARAMETER);
if (locale != null) {
ActionContext.getContext().setLocale(locale);
}
}
return invocation.invoke();
}
struts.xml:
<package name="default" extends="struts-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="navigator"
class="it.apps.mca.web.interceptors.NavigatorInterceptor">
</interceptor>
<interceptor name="locale"
class="it.apps.mca.web.interceptors.internationalizations.LocaleInterceptor">
</interceptor>
<interceptor-stack name="customStack">
<interceptor-ref name="navigator" />
<interceptor-ref name="locale" />
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<action name="locale"
class="it.apps.mca.web.actions.internationalizations.LocaleAction">
<interceptor-ref name="customStack"></interceptor-ref>
<result name="success" type="redirect">
<param name="location">${target}</param>
<param name="parse">true</param>
</result>
</action>
<action name="login"
class="it.apps.mca.web.actions.authentication.LoginAction">
<result name="success" type="tiles">/welcome.tiles</result>
<result name="input">index.jsp</result>
<result name="error">index.jsp</result>
</action>
</package>
I know i18n interceptor already exists.
I added an interceptor that performs redirections. After adding this interceptor, I lose the location of the page.
The same thing happens if I perform a redirect through the action. You know tell me the reason?
That Interceptor already exists: i18n Interceptor
It is part of the defaultStack, so you don't have to manually include it.
Example of usage
Other info in this answer.

How to allow slashes in Struts 2 Action Names?

I'm trying to enable slashes in Struts 2 action names. I've put this in my config file:
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.action.extension" value=","/>
<constant name="struts.multipart.maxSize" value="2147483648" />
<constant name="struts.enable.SlashesInActionNames" value="true"/>
<package name="myApp" extends="struts-default">
<action name="home" class="net.myapp.actions.HomeAction" method="execute">
<result name="landing">/landing.jsp</result>
</action>
<action name="/ajax/foo" class="net.myApp.actions.ajax.FooAction" method="execute">
<result name="success">/foo.jsp</result>
</action>
</package>
</struts>
When I go to just the homepage of this app, e.g http://localhost:8034/myApp, I see the homepage correctly. But if I visit http://localhost:8034/myApp/ajax/foo, I get the error: There is no Action mapped for action name ajax/foo. even though I have described it above as the 2nd action.
What am I doing wrong?
I'd say you need a namespace as well, so ajax would be the namespace in your case:
<package name="myApp" extends="struts-default" namespace="/ajax">
<action name="foo" class="net.myApp.actions.ajax.FooAction" method="execute">
<result name="success">/foo.jsp</result>
</action>
</package>
Note that you could use slashes in your action names, e.g. foo/bar, but it's not advisable, since some plugins (e.g. the conversation plugin) might have difficulties to determine the namespace and action from a string like /ajax/foo/bar.
Btw, the error message says There is no Action mapped for action name ajax/foo., i.e. struts looks for an action named ajax/foo but you only have an action /ajax/foo.

struts2.xml - can't include other .xml file

I am using struts2, for that my struts.xml file contains code like :
<?xml version="1.0" encoding="UTF-8" ?>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<include file="strutsAuthentication.xml"/>
<package name="default" extends="struts-default">
<interceptors>
<interceptor-stack name="crudStack">
<interceptor-ref name="checkbox" />
<interceptor-ref name="params" />
<interceptor-ref name="static-params" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
</package>
And i have specified all the required actions inside the strutsAuthentication.xml. That code is :
<struts>
<package name="authentication" extends="default" namespace="/authentication">
<action name="saveCountry" class="saveCountryAction">
<interceptor-ref name="defaultStack" />
<result name="success">/savecountry.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
When i am deploying my application into tomcat, it gives me warning that :
WARN (org.apache.struts2.components.Form:308) - No configuration found for the specified action: 'saveCountry' in namespace: ''. Form action defaulting to 'action' attribute's literal value.
It means struts.xml can't include strutsAuthentication.xml. Anyone have a solution ?? Thanx in advance....
Got d solution.... For above problem i was done a mistake in calling the action from jsp page. So namespace name "authentication" should be included at the time of calling the action class. Final solution is : "authentication/saveCountry.action".
I don't know what version of struts2 you're using but if you're using the 2.1.x branch you should look at the convention plugin http://cwiki.apache.org/S2PLUGINS/convention-plugin.html. You can get rid of 99% XML configuration.
As an add note. We should never use "xyz.action" in JSP pages. If we later need or decide to change the url-pattern from .action to .do or .html etc. We have to change all JSP pages. A better approach to compose links is:
Link Text

Categories