Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
titleA Logon Action
<action name="Logon" class="tutorial.Logon">
  <result type="redirectAction">Menu</result>
  <result name="input">/Logon.jsp</result>
</action> 

 

When using Convention Plugin the action mapping can be configured with annotations:

...

title
Code Block
titleA Hello Form
<s:form action="Hello">
    <s:textfield label="Please enter your name" name="name"/>
    <s:submit/>
</s:form>
Info

Action Names With Slashes

If your action names have slashes in them (for example, <action name="admin/home" class="tutorial.Admin"/>) you need to specifically allow slashes in your action names via a constant in the struts.xml file by specifying <constant name="struts.enable.SlashesInActionNames" value="true"/>. See JIRA Issue WW-1383 for discussion as there are side effects to setting this property to true.

...

Action Names with Dots and Dashes

Although action naming is pretty flexible, one should pay attention when using dots (eg. create.user) and/or dashes (eg. my-action). While the dot notation has no known side effects at this time, the dash notation will cause problems with the generated JavaScript for certain tags and themes. Use with caution, and always try to use camelcase action names (eg. createUser) or underscores (eg. my_action).

Action Methods

The default entry method to the handler class is defined by the Action interface.

Code Block
titleAction interface
public interface Action {
    public String execute() throws Exception;
}

(info) Implementing the Action interface is optional. If Action is not implemented, the framework will use reflection to look for an execute method.

Sometimes, developers like to create more than one entry point to an Action. For example, in the case of a data-access Action, a developer might want separate entry-points for create, retrieve, update, and delete. A different entry point can be specified by the method attribute.

...

<action name="delete" class="example.CrudAction" method="delete">
    ...

Allowed action names

DefaultActionMapper is using pre-defined RegEx to check if action name matches allowed names. The default RegEx is defined as follow: [a-zA-Z0-9._!/\-]* - if at some point this doesn't match your action naming schema you can define your own RegEx and override the default using constant named struts.allowed.action.names, e.g.:

Code Block
xml
xml
<struts>
  <constant name="struts.allowed.action.names" value="[a-z{}]"*/>
  ...
</struts>

NOTE: Please be aware that action names not matching the RegEx will rise an exception.

Action Methods

The default entry method to the handler class is defined by the Action interface.

Code Block
titleAction interface
public interface Action {
    public String execute() throws Exception;
}

(info) Implementing the Action interface is optional. If Action is not implemented, the framework will use reflection to look for an execute method.

Sometimes, developers like to create more than one entry point to an Action. For example, in the case of a data-access Action, a developer might want separate entry-points for create, retrieve, update, and delete. A different entry point can be specified by the method attribute.

Code Block
xml
xml
<action name="delete" class="example.CrudAction" method="delete">
    ...

(warning) If there is no execute method and no other method specified in the configuration the framework will throw an exception.

 

Convention Plugin allows that by annotating methods:

Code Block
titleAnnotated action method
@Action("crud")
public class CrudAction {
	@Action("delete")
	public String delete() {
		...

Wildcard Method

Many times, a set of action mappings will share a common pattern. For example, all your edit actions might start with the word "edit", and call the edit method on the Action class. The delete actions might use the same pattern, but call the delete method instead.

Rather than code a separate mapping for each action class that uses

(warning) If there is no execute method and no other method specified in the configuration the framework will throw an exception.

 

Convention Plugin allows that by annotating methods:

Code Block
titleAnnotated action method
@Action("crud")
public class CrudAction {
	@Action("delete")
	public String delete() {
		...

Wildcard Method

Many times, a set of action mappings will share a common pattern. For example, all your edit actions might start with the word "edit", and call the edit method on the Action class. The delete actions might use the same pattern, but call the delete method instead.

Rather than code a separate mapping for each action class that uses this pattern, you can write it once as a wildcard mapping.

...

In Struts 2.5 the Strict DMI was extended and it's called "Strict Method Invocation" aka  aka SMI. You can imagine that the DMI is a "border police", where SMI is a "tax police" and keeps eye on internals. With this version, SMI is enabled by default (strict-method-invocation attribute is set to true by default in struts-default package), you have option to disable it per package - there is no global switch to disable SMI for the whole application. To gain advantage of new configuration option please use the latest DTD definition:

Code Block
languagexml
titleStruts 2.5 DTD
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
...
</struts>

SMI works in the following way:

...

        "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
...
</struts>

SMI works in the following way:

  • <allowed-methods> / @AllowedMethods is defined per action - SMI works without switching it on but just for those actions (plus adding <global-allowed-methods/>)
  • SMI is enabled but no <allowed-methods> / @AllowedMethods are defined - SMI works but only with <global-allowed-methods/>
  • SMI is disabled - call to any action method is allowed that matches the default RegEx - ([A-Za-z0-9_$]*)

You can redefine the default RegEx by using a constant as follow <constant name="struts.strictMethodInvocation.methodRegex" value="([a-zA-Z]*)"/>

Note

When using wildcard mapping in actions' definitions SMI works in two ways:

  • SMI is disabled - any wildcard will be substituted with the default RegEx, ie.: <action name="Person*" method="perform*"> will be translated into allowedMethod = "regex:perform([A-Za-z0-9_$]*)".
  • SMI is enabled - no wildcard substitution will happen, you must strictly define which methods can be accessed by annotations or <allowed-method/> tag.

...

You can configure SMI per <action/> usinf  using <allowed-methods/> tag or via @AllowedMethod annotation plus using per <package/> <global-allowed-methods/>, see the examples below:

...

Code Block
languagejava
titleSMI via annotation on package level (in package-info.java)
@org.apache.struts2.convention.annotation.AllowedMethods({"home", "start"})
package org.apache.struts2.convention.actions.allowedmethods;

Allowed methods can be defined as:

  • literals ie.

     execute,cancel

    in xml: execute,cancel or in annotation: {"execute", "cancel"}

  • patterns when using with wildcard mapping, i.e <action ... method="do{2}"/>
  • RegExs using regex: prefix, ie: <global-allowed-methods>execute,input,cancel,regex:user([A-Z]*)</global-allowed-methods>

...

Note

Please be aware when using your own Configurationprovider that the logic to set allowed methods is defined in built-in providers - XmlConfigurationProvider and PackageBasedActionConfigBuilder - and you must replicate it such logic in your code as by default only execute method is allowed, even when SMI is disabled.

...

ActionSupport Default

If the class attribute in an action mapping is left blank, the com.opensymphony.xwork2.ActionSupport class is used as a default.

...