In the following piece of code about Struts action class,
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content") // Default.
public final class TestAction extends ActionSupport implements Serializable
{
private static final long serialVersionUID = 1L;
private static final String SUCCESS = "success";
private String name;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
@Action(value="test",results={@Result(name="success",location="Test.jsp")})
public String execute() throws Exception
{
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
// Some annotations to map this method to <s:submit>
public String postAction()
{
System.out.println("postAction() invoked.");
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
}
I want to invoke the postAction()
method on the given submit button like so,
<s:form action="test">
<s:textfield id="name" name="name" label="Enter your name"/>
<s:textfield id="email" name="email" label="Enter your email"/>
<s:submit value="Submit" method="postAction"/>
</s:form>
I have seen some questions like this one but all of them use XML configurations in struts.xml
.
How to make it possible using convention plugin?
Different methods are achievable by:
moving the @Action
annotation from method-level to class-level:
@Action(value="test",results={@Result(name="success",location="Test.jsp")})
public final class TestAction extends ActionSupport implements Serializable {
renaming the execute()
method into something else, eg. test()
:
public String test() throws Exception {
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
public String postAction() {
System.out.println("postAction() invoked.");
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
From the documentation:
Applying @Action and @Actions at the class level
There are circumstances when this is desired, like when using Dynamic Method Invocation. If an execute method is defined in the class, then it will be used for the action mapping, otherwise the method to be used will be determined when a request is made (by Dynamic Method Invocation for example)
, and obviously by enabling Dynamic Method Invocation in Struts.xml.
But this should be avoided; read this article to understand why: Making Struts2 app more secure: disable DMI. Note that Struts2 Maven archetypes already has DMI set to false, because it is discouraged.
Then, you should turn off DMI, and start using multiple Actions instead of multiple methods, by simply annotating the other Action's methods too, and using different action
attributes in the <s:submit/>
button :
@Action(value="test",results={@Result(name="success",location="Test.jsp")})
public String test() throws Exception {
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
@Action(value="postAction",results={@Result(name="success",location="Test.jsp")})
public String postAction() {
System.out.println("postAction() invoked.");
System.out.println("name = "+name);
System.out.println("email = "+email);
return SUCCESS;
}
and in JSP:
<s:form namespace="/admin_side">
<s:textfield id="name" name="name" label="Enter your name" />
<s:textfield id="email" name="email" label="Enter your email" />
<s:submit value="Submit to test()" action="test" />
<s:submit value="Submit to postAction()" action="postAction" />
</s:form>
EDIT: Since Struts 2.3.15.3
, you need to explicitly enable the action:
suffix with:
<constant name="struts.mapper.action.prefix.enabled" value="true"/>
Because it won't work by default.