I'm using this as a reference to create a REST only configuration on Struts2:
https://cwiki.apache.org/confluence/display/WW/REST+Plugin
My current problem is with interceptors. I created a sample interceptor that should be executed before the action gets hit.
Here it is:
public class AuthInterceptor extends AbstractInterceptor implements Interceptor
{
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("intercepting AuthInterceptor...");
return invocation.invoke();
}
public void destroy() {
System.out.println("Destroying AuthInterceptor...");
}
public void init() {
System.out.println("Initializing AuthInterceptor...");
}
}
and here's my struts.xml file:
<?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="true"/>
<constant name="struts.mapper.class" value="rest" />
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>
<constant name="struts.convention.package.locators" value="controllers"/>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="com.company.interceptors.AuthInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
</package>
</struts>
The logs (catalina.out) say that my interceptor got initialized, but never actually intercepted anything.
Initializing AuthInterceptor...
Apparently the default-interceptor-ref doesn't work well with the rest mapper class. Is this the case? or am I doing something wrong here?
You need to change this
<constant name="struts.convention.default.parent.package" value="default"/>
<package name="default" extends="rest-default">
The convention plugin when creates action configuration inherits interceptors defined in the parent package. To define a parent package you can use #ParentPackage annotation or the constant above which defines a parent package for all actions.
The previous respuest is correct but for implement all REST functionality in the interceptor you must change your inteceptor stack to:
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="restDefaultStack"/>
</interceptor-stack>
Related
I am working on struts2-archetype-starter. Got a demo struts 2 project by executing:
mvn archetype:generate -B -DgroupId=demoStrutsStarter -DartifactId=DemoStrutsStarter -DarchetypeGroupId=org.apache.struts -DarchetypeArtifactId=struts2-archetype-starter
I modified my struts.xml and added a struts.action.extension constant declaration. Now it looks like this:
<?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.action.extension" value=","/>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<package name="myPackage" extends="struts-default">
<default-action-ref name="index" />
<action name="index" class="demoStrutsStarter.IndexAction">
<result>/jsp/index.jsp</result>
</action>
<action name="helloWorld" class="demoStrutsStarter.HelloWorldAction">
<result name="input">/jsp/index.jsp</result>
<result>/jsp/helloWorld.jsp</result>
</action>
</package>
</struts>
But, I am getting a 404 error when I type:
http://localhost:8080/DemoStrutsStarter/index
I am not sure where I am wrong. Can anybody please help me find out why I am unable to call actions without .action extension?
Try adding a namespace to your package:
<package name="myPackage" namespace="/" extends="struts-default" >
Try this out in both results
result 1
<result>/WEB-INF/jsp/index.jsp</result>
result 2
<result>/WEB-INF/jsp/helloWorld.jsp</result>
else check your package name is correct or not.
by default, it's name default
try this links. it may help
1.stack overflow link 1
2.link 2 mkyong
3.stack overflow link 3
With some help of the people here, I've managed to get my project to call the default actions of the packages without the suffix .htm. However, the request end up to index.jsp inside the webapp folder if I call the URL without the forward slash.
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.action.extension" value="htm,," />
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.devMode" value="true"/>
...
<package name="home" namespace="/secured" extends="default">
<default-action-ref name="index" />
<action name="index" class="homeAction" method="execute">
<result name="success" type="tiles">home</result>
</action>
</package>
</struts>
Actions are executed if I call http://someurl/someproject/secured/, but calling the URL http://someurl/someproject/secured end up to the file index.jsp.
What to do? Thanks
When you are calling http://someurl/someproject/secured url the secured is treated like action w/o suffix, because you have configured that actions can have empty suffix (which is also default btw). If you want that this url redirects to /secured namespace you can declare secured action with redirectAction result in package with empty or / namespace.
<package name="..." namespace="/" extends="struts-default">
...
<action name="secured">
<result type="redirectAction">
<param name="actionName">index</param>
<param name="namespace">/secured</param>
</result>
</action>
...
</package>
I am new to struts2. In application there is Action called userLogin. when i enter to url http://servername:9090/appName/userLogin, It should forward the request directly to to /jsp/account/login.jsp. it should not call action method. how can i ensure that when request is through get then forword to loginPage else if Request is Post then it should call the action
Struts.xml is as follows
<?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" />
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<package name="default" extends="struts-default">
<action name="index">
<result>jsp/index.jsp</result>
</action>
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<result>jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
<action name="ministatement" class="com.ril.tc.action.MiniStatementAction">
<result>jsp/account/ministatement.jsp</result>
<result name="success">jsp/account/ministatementdetails.jsp</result>
<result name="error">jsp/account/ministatement.jsp</result>
</action>
</package>
</struts>
1. You can simply check the request method in action method before the business method executes.
It will add 2-3 lines of java code in action method and a line modification in xml configuration.
2. Or you can strictly restrict the execution of the Action method by using an interceptor.
Interceptor requires a seperate java class and a few lines of xml configuration.
Method 1
a) Java code
public String execute (){ // or your method name
if(ServletActionContext.getRequest().getMethod().equals("GET")){
return "getrequest";
}
........
//your business logic
}
b) xml configuration
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<result name="getrequest">jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
Method 2.
a) Java Code
public GetRequestFilterInterceptor extends AbstractInterceptor{
#Override
public void intercept (ActionInvocation action){
if(ServletActionContext.getRequest().getMethod(). equals("GET")){
return "getrequest";
}else{
action.invoke();
}
}
}
b) Xml configuration
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="getUrlFilter" class="packagename.GetRequestFilterInterceptor"/>
<interceptor-stack name="requestFilter">
<interceptor-ref name="getUrlFilter"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
......
<action name="userLogin" class="com.ril.tc.action.LoginAction">
<interceptor-ref name="requestFilter"/>
<result name="getrequest">jsp/account/login.jsp</result>
<result name="success">jsp/index.jsp</result>
<result name="error">jsp/account/login.jsp</result>
</action>
</package>
</struts>
I recommend you to use interceptors, if you want to filter a lot a methods. If you have want to filter only one method, the first one is better.
How can I tell to Struts 2 convention plugin to scan all subpackages of a package. I tried with this
<constant name="struts.convention.action.suffix" value="Controller" />
<constant name="struts.convention.package.locators.basePackage" value="fi.fpf.mvc" />
and this
<constant name="struts.convention.action.suffix" value="Controller" />
<constant name="struts.convention.package.locators.basePackage" value="fi.fpf.mvc.*" />
but they don't work. my actions end with "Controller" suffix. Someone knows how to do it?
here's my struts.xml:
<struts>
<constant name="struts.convention.exclude.parentClassLoader" value="true"/>
<constant name="struts.convention.action.fileProtocols" value="jar,vfs,vfsfile,vfszip"/>
<constant name="struts.convention.action.suffix" value="Controller" />
<constant name="struts.convention.package.locators.basePackage" value="fi.fpf.mvc" />
<package name="fpf-default" extends="struts-default">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
</package>
</struts>
and one action:
#Action("indexController")
public class IndexController extends ActionSupport{
private static final long serialVersionUID = -2613425890762568273L;
#Action(value="loadIndex", results={
#Result(name="indexView", location = "indexView", type="tiles")
})
public String loadIndex() {
return "indexView";
}
}
Try
<constant name="struts.convention.action.packages" value="fi.fpf.mvc.*"/>
if you are using convention plugin, then you should follow the class and package name conventions. Why not just name a base package to "struts" or "struts2" and with the default package locators it will be located. Also the classes should have names that matches "Action" suffix.
You can tell the Convention plugin to ignore certain packages using
the property struts.convention.exclude.packages. You can also tell the
plugin to use different strings to locate root packages using the
property struts.convention.package.locators. Finally, you can tell the
plugin to search specific root packages using the property
struts.convention.action.packages.
See the docs.
Alternatively, you could set the base package and locator that match this package and any package under the base
<constant name="struts.convention.package.locators.basePackage" value="fi.fpf.mvc"/>
<constant name="struts.convention.package.locators" value="fi,fpf,mvc"/>
I have designed an application using struts2, and need to remove the extensions for example
www.myweb.com/register.action
How to remove the .action so when I click on register it call www.myweb.com/register without action extension?
I use the following
Register
I've found the answer. I should change the struts configuration as following:
<struts>
<constant name="struts.action.extension" value=""/>
<package name="default" extends="struts-default">
<action name="register">
<result type="tiles">register</result>
</action>
</package>
</struts>