Here is my action class:
FirstAction.java
:
@Namespace(value = "/User")
public class FirstAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
@Action(value = "run4", results = { @Result(name = "task1", location = "task1.jsp") })
private String task1() {
return "task1";
}
@Action(value = "run5", results = { @Result(name = "task2", location = "task2.jsp") })
private String task2() {
return "task2";
}
@Action(value = "run6", results = { @Result(name = "task3", location = "task3.jsp") })
private String task3() {
return "task3";
}
}
SecondAction.java
:
@Namespace(value = "/Admin")
public class SecondAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
@Action(value = "run1", results = { @Result(name = "task1", location = "task1.jsp") })
private String task1() {
return "task1";
}
@Action(value = "run2", results = { @Result(name = "task2", location = "task2.jsp") })
private String task2() {
return "task2";
}
@Action(value = "run3", results = { @Result(name = "task3", location = "task3.jsp") })
private String task3() {
return "task3";
}
}
struts.xm
l:
<struts>
<constant name="struts.action.extension" value="html" />
<package name="default" extends="struts-default"></package>
</struts>
web.xml
:
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>com.sem4.actions</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Session Config -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
This is redirect.jsp
:
<div>
<a href='<s:url action="run1" namespace="Admin"></s:url>'>Action run1, namespace Admin</a>
<br>
<a href='<s:url action="run2" namespace="Admin"></s:url>'>Action run2, namespace Admin</a>
<br>
<a href='<s:url action="run3" namespace="Admin"></s:url>'>Action run3, namespace Admin</a>
</div>
<div>
<a href='<s:url action="run4" namespace="User"></s:url>'>Action run1, namespace User</a>
<br>
<a href='<s:url action="run5" namespace="User"></s:url>'>Action run2, namespace User</a>
<br>
<a href='<s:url action="run6" namespace="User"></s:url>'>Action run3, namespace User</a>
</div>
And my library:
antlr-2.7.6.jar
commons-collections-3.1.jar
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-lang-2.3.jar
commons-logging-1.1.jar
dom4j-1.6.1.jar
ejb3-persistence.jar
freemarker-2.3.13.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-validator.jar
hibernate3.jar
hsqldb.jar
javassist-3.9.0.GA.jar
jta-1.1.jar
junit-3.8.1.jar
log4j-1.2.15.jar
mysql-connector-java-5.0.7-bin.jar
ognl-2.6.11.jar
slf4j-api-1.5.8.jar
slf4j-log4j12-1.5.8.jar
struts2-convention-plugin-2.1.6.jar
struts2-core-2.1.6.jar
struts2-fullhibernatecore-plugin-1.4-GA.jar
xwork-2.1.2.jar
When I click a link in redirect.jsp
to call an action, ex: call action run4
in namespace "User"
, it's throwing
HTTP Status 404 - There is no Action mapped for namespace /User and action name run4
I'm trying to find what makes this wrong, but it looks like my code is fine.
The action method should be public
. Struts2 not allows to map an action on private
methods, e.g.
@Action(value = "run4", results = { @Result(name = "task1", location = "task1.jsp") })
public String task1() {
return "task1";
}
Also it's not necessary to write annotations to configure actions via convention plugin. It has already created a configuration that can be used by convention. You can see the docs page to get how to use this configuration.