| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"/> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
| <meta name="Date-Revision-yyyymmdd" content="20140918"/> |
| <meta http-equiv="Content-Language" content="en"/> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| |
| <title>Convention plugin</title> |
| |
| <link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css"> |
| <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> |
| <link href="/css/main.css" rel="stylesheet"> |
| <link href="/css/custom.css" rel="stylesheet"> |
| <link href="/highlighter/github-theme.css" rel="stylesheet"> |
| |
| <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> |
| <script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script> |
| <script type="text/javascript" src="/js/community.js"></script> |
| </head> |
| <body> |
| |
| <a href="http://github.com/apache/struts" class="github-ribbon"> |
| <img style="position: absolute; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub"> |
| </a> |
| |
| <header> |
| <nav> |
| <div role="navigation" class="navbar navbar-default navbar-fixed-top"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle"> |
| Menu |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a> |
| </div> |
| <div id="struts-menu" class="navbar-collapse collapse"> |
| <ul class="nav navbar-nav"> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Home<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/index.html">Welcome</a></li> |
| <li><a href="/download.cgi">Download</a></li> |
| <li><a href="/releases.html">Releases</a></li> |
| <li><a href="/announce.html">Announcements</a></li> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Support<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/mail.html">User Mailing List</a></li> |
| <li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li> |
| <li><a href="/security.html">Reporting Security Issues</a></li> |
| <li class="divider"></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li> |
| <li class="divider"></li> |
| <li><a href="/maven/project-info.html">Maven Project Info</a></li> |
| <li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li> |
| <li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Documentation<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/birdseye.html">Birds Eye</a></li> |
| <li><a href="/primer.html">Key Technologies</a></li> |
| <li><a href="/kickstart.html">Kickstart FAQ</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li> |
| <li class="divider"></li> |
| <li><a href="/getting-started/">Getting Started</a></li> |
| <li><a href="/security/">Security Guide</a></li> |
| <li><a href="/core-developers/">Core Developers Guide</a></li> |
| <li><a href="/tag-developers/">Tag Developers Guide</a></li> |
| <li><a href="/maven-archetypes/">Maven Archetypes</a></li> |
| <li><a href="/plugins/">Plugins</a></li> |
| <li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li> |
| <li><a href="/tag-developers/tag-reference.html">Tag reference</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li> |
| <li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Contributing<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/youatstruts.html">You at Struts</a></li> |
| <li><a href="/helping.html">How to Help FAQ</a></li> |
| <li><a href="/dev-mail.html">Development Lists</a></li> |
| <li><a href="/contributors/">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/submitting-patches.html">Submitting patches</a></li> |
| <li><a href="/builds.html">Source Code and Builds</a></li> |
| <li><a href="/coding-standards.html">Coding standards</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Contributors+Guide">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/release-guidelines.html">Release Guidelines</a></li> |
| <li><a href="/bylaws.html">PMC Charter</a></li> |
| <li><a href="/volunteers.html">Volunteers</a></li> |
| <li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li> |
| <li><a href="/updating-website.html">Updating the website</a></li> |
| </ul> |
| </li> |
| <li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </nav> |
| </header> |
| |
| |
| <article class="container"> |
| <section class="col-md-12"> |
| <a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/plugins/convention/index.md" title="Edit this page on GitHub">Edit on GitHub</a> |
| |
| <a href="../" title="back to Plugins"><< back to Plugins</a> |
| |
| <h1 class="no_toc" id="convention-plugin">Convention Plugin</h1> |
| |
| <ul id="markdown-toc"> |
| <li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li> |
| <li><a href="#setup" id="markdown-toc-setup">Setup</a></li> |
| <li><a href="#converting-a-codebehind-based-application-to-convention" id="markdown-toc-converting-a-codebehind-based-application-to-convention">Converting a Codebehind based application to Convention</a></li> |
| <li><a href="#hello-world" id="markdown-toc-hello-world">Hello world</a></li> |
| <li><a href="#code-behind-hello-world" id="markdown-toc-code-behind-hello-world">Code behind hello world</a></li> |
| <li><a href="#results-and-result-codes" id="markdown-toc-results-and-result-codes">Results and result codes</a></li> |
| <li><a href="#multiple-names" id="markdown-toc-multiple-names">Multiple names</a></li> |
| <li><a href="#xwork-packages" id="markdown-toc-xwork-packages">XWork packages</a></li> |
| <li><a href="#annotation-reference" id="markdown-toc-annotation-reference">Annotation reference</a> <ul> |
| <li><a href="#action-annotation" id="markdown-toc-action-annotation">Action annotation</a> <ul> |
| <li><a href="#applying-action-and-actions-at-the-class-level" id="markdown-toc-applying-action-and-actions-at-the-class-level">Applying <code class="highlighter-rouge">@Action</code> and <code class="highlighter-rouge">@Actions</code> at the class level</a></li> |
| </ul> |
| </li> |
| <li><a href="#interceptorref-annotation" id="markdown-toc-interceptorref-annotation">InterceptorRef annotation</a></li> |
| <li><a href="#result-annotation" id="markdown-toc-result-annotation">Result annotation</a></li> |
| <li><a href="#namespace-annotation" id="markdown-toc-namespace-annotation">Namespace annotation</a></li> |
| <li><a href="#resultpath-annotation" id="markdown-toc-resultpath-annotation">ResultPath annotation</a></li> |
| <li><a href="#parentpackage-annotation" id="markdown-toc-parentpackage-annotation">ParentPackage annotation</a></li> |
| <li><a href="#exceptionmapping-annotation" id="markdown-toc-exceptionmapping-annotation">ExceptionMapping Annotation</a></li> |
| </ul> |
| </li> |
| <li><a href="#actions-in-jar-files" id="markdown-toc-actions-in-jar-files">Actions in jar files</a></li> |
| <li><a href="#automatic-configuration-reloading" id="markdown-toc-automatic-configuration-reloading">Automatic configuration reloading</a></li> |
| <li><a href="#jboss" id="markdown-toc-jboss">JBoss</a></li> |
| <li><a href="#jetty-embedded" id="markdown-toc-jetty-embedded">Jetty (embedded)</a></li> |
| <li><a href="#troubleshooting" id="markdown-toc-troubleshooting">Troubleshooting</a> <ul> |
| <li><a href="#tips" id="markdown-toc-tips">Tips</a></li> |
| <li><a href="#common-errors" id="markdown-toc-common-errors">Common Errors</a></li> |
| </ul> |
| </li> |
| <li><a href="#overwriting-plugin-classes" id="markdown-toc-overwriting-plugin-classes">Overwriting plugin classes</a></li> |
| <li><a href="#configuration-reference" id="markdown-toc-configuration-reference">Configuration reference</a></li> |
| </ul> |
| |
| <h2 id="introduction">Introduction</h2> |
| |
| <p>The Convention Plugin is bundled with Struts since 2.1 and replaces the <em>Codebehind Plugin</em> and Zero Config plugins. |
| It provides the following features:</p> |
| |
| <ul> |
| <li>Action location by package naming conventions</li> |
| <li>Result (JSP, FreeMarker, etc) location by naming conventions</li> |
| <li>Class name to URL naming convention</li> |
| <li>Package name to namespace convention</li> |
| <li>SEO compliant URLs (i.e. <code class="highlighter-rouge">my-action</code> rather than <code class="highlighter-rouge">MyAction</code>)</li> |
| <li>Action name overrides using annotations</li> |
| <li>Interceptor overrides using annotations</li> |
| <li>Namespace overrides using annotations</li> |
| <li>XWork package overrides using annotations</li> |
| <li>Default action and result handling (i.e. <code class="highlighter-rouge">/products</code> will try <code class="highlighter-rouge">com.example.actions.Products</code> as well as |
| <code class="highlighter-rouge">com.example.actions.products.Index</code>)</li> |
| </ul> |
| |
| <p>The Convention Plugin should require no configuration to use. Many of the conventions can be controlled using |
| configuration properties and many of the classes can be extended or overridden.</p> |
| |
| <h2 id="setup">Setup</h2> |
| |
| <p>In order to use the Convention plugin, you first need to add the JAR file to the <code class="highlighter-rouge">WEB-INF/lib</code> directory of your |
| application or include the dependency in your project’s Maven POM file.</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><dependency></span> |
| <span class="nt"><groupId></span>org.apache.struts<span class="nt"></groupId></span> |
| <span class="nt"><artifactId></span>struts2-convention-plugin<span class="nt"></artifactId></span> |
| <span class="nt"><version></span>X.X.X<span class="nt"></version></span> |
| <span class="nt"></dependency></span> |
| </code></pre></div></div> |
| |
| <p>Where <code class="highlighter-rouge">X.X.X</code> is the current version of Struts 2. Please remember that the Convention Plugin is available from |
| version 2.1.6.</p> |
| |
| <h2 id="converting-a-codebehind-based-application-to-convention">Converting a Codebehind based application to Convention</h2> |
| |
| <p>See <a href="converting.html">this page</a> for the required changes and tips.</p> |
| |
| <p>If you are using REST with the Convention plugin, make sure you set these constants in <code class="highlighter-rouge">struts.xml</code>:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.action.suffix"</span> <span class="na">value=</span><span class="s">"Controller"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.action.mapAllMatches"</span> <span class="na">value=</span><span class="s">"true"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.default.parent.package"</span> <span class="na">value=</span><span class="s">"rest-default"</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h2 id="hello-world">Hello world</h2> |
| |
| <p>Now that the Convention plugin has been added to your application, let’s start with a very simple example. This example |
| will use an actionless result that is identified by the URL. By default, the Convention plugin assumes that all |
| of the results are stored in <strong>WEB-INF/content</strong>. This can be changed by setting the property |
| <code class="highlighter-rouge">struts.convention.result.path</code> in the Struts properties file to the new location. Don’t worry about trailing slashes, |
| the Convention plugin handles this for you. Here is our hello world JSP:</p> |
| |
| <pre><code class="language-jsp"><html> |
| <body> |
| Hello world! |
| </body> |
| </html> |
| </code></pre> |
| |
| <p>If you start Tomcat (or whichever J2EE container you are using) and type in |
| <a href="http://localhost:8080/hello-world">http://localhost:8080/hello-world</a> (assuming that your context path is <code class="highlighter-rouge">/</code>, |
| ie. starting application from Eclipse) into your browser you should get this result:</p> |
| |
| <p><strong>WEB-INF/content/hello-world.jsp</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hello world! |
| </code></pre></div></div> |
| |
| <p>This illustrates that the Convention plugin will find results even when no action exists and it is all based on the URL |
| passed to Struts.</p> |
| |
| <h2 id="code-behind-hello-world">Code behind hello world</h2> |
| |
| <p>Let’s expand on this example and add a code behind class. In order to do this we need to ensure that the Convention |
| plugin is able to find our action classes. By default, the Convention plugin will find all action classes that implement |
| <code class="highlighter-rouge">com.opensymphony.xwork2.Action</code> or whose name ends with the word <strong>Action</strong> in specific packages.</p> |
| |
| <p>These packages are located by the Convention plugin using a search methodology. First the Convention plugin finds |
| packages named <code class="highlighter-rouge">struts</code>, <code class="highlighter-rouge">struts2</code>, <code class="highlighter-rouge">action</code> or <code class="highlighter-rouge">actions</code>. Any packages that match those names are considered the root |
| packages for the Convention plugin. Next, the plugin looks at all of the classes in those packages as well |
| as sub-packages and determines if the classes implement <code class="highlighter-rouge">com.opensymphony.xwork2.Action</code> or if their name ends with |
| <strong>Action</strong> (i.e. <code class="highlighter-rouge">FooAction</code>). Here’s an example of a few classes that the Convention plugin will find:</p> |
| |
| <p><strong>Classes</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com.example.actions.MainAction |
| com.example.actions.products.Display (implements com.opensymphony.xwork2.Action) |
| com.example.struts.company.details.ShowCompanyDetailsAction |
| </code></pre></div></div> |
| |
| <p>Each of the action classes that the plugin finds will be configured to respond to specific URLs. The URL is based on |
| the package name that the class is defined in and the class name itself. First the plugin determines the namespace of |
| the URL using the package names between the root package and the package the class is defined in. For our examples above, |
| the namespaces would be:</p> |
| |
| <p><strong>Namespaces</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com.example.actions.MainAction -> / |
| com.example.actions.products.Display -> /products |
| com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details |
| </code></pre></div></div> |
| |
| <p>Next, the plugin determines the URL of the resource using the class name. It first removes the word <strong>Action</strong> from the end of the class name and then converts camel case names to dashes. In our example the full URLs would be:</p> |
| |
| <p><strong>Full URLs</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com.example.actions.MainAction -> /main |
| com.example.actions.products.Display -> /products/display |
| com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details/show-company-details |
| </code></pre></div></div> |
| |
| <p>You can tell the Convention plugin to ignore certain packages using the property <code class="highlighter-rouge">struts.convention.exclude.packages</code>. |
| You can also tell the plugin to use different strings to locate root packages using the property |
| <code class="highlighter-rouge">struts.convention.package.locators</code>. Finally, you can tell the plugin to search specific root packages using |
| the property <code class="highlighter-rouge">struts.convention.action.packages</code>.</p> |
| |
| <p>Here is our code behind action class:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="kd">private</span> <span class="n">String</span> <span class="n">message</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">getMessage</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">message</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="n">message</span> <span class="o">=</span> <span class="s">"Hello World!"</span><span class="o">;</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>If you compile this class and place it into your application in the WEB-INF/classes, the Convention plugin will find |
| the class and map the URL <strong>/hello-world</strong> to it. Next, we need to update our JSP to print out the message we setup in |
| the action class. Here is the new JSP:</p> |
| |
| <p><strong>WEB-INF/content/hello-world.jsp</strong></p> |
| |
| <pre><code class="language-jsp"><html> |
| <body> |
| The message is ${message} |
| </body> |
| </html> |
| </code></pre> |
| |
| <blockquote> |
| <p>Please notice that the expression <code class="highlighter-rouge">${message}</code> will work without adding JSP directive <code class="highlighter-rouge">isELIgnored="false"</code>.</p> |
| </blockquote> |
| |
| <p>If start up the application server and open up <a href="http://localhost:8080/hello-world">http://localhost:8080/hello-world</a> |
| in our browser, we should get this result:</p> |
| |
| <p><strong>Result</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The message is Hello World! |
| </code></pre></div></div> |
| |
| <h2 id="results-and-result-codes">Results and result codes</h2> |
| |
| <p>The Convention Plugin will pre-configure all of your action classes when Struts is started. By default, this |
| configuration will also contain results for any JSPs that it can find within the application. The JSPs have |
| an additional feature that allows different JSPs to be used based on the result code of the action. Since action |
| methods return Strings and these Strings are traditionally used to locate results for the action, the Convention plugin |
| allows you to define different results based on the result code.</p> |
| |
| <p>Building on our example from above, let’s say we want to provide a different result if the result code from our action |
| is the String <code class="highlighter-rouge">zero</code> rather than <code class="highlighter-rouge">success</code>. First, we update the action class to return different result codes:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="kd">private</span> <span class="n">String</span> <span class="n">message</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">getMessage</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">message</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">if</span> <span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">()</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span> |
| <span class="n">message</span> <span class="o">=</span> <span class="s">"It's 0"</span><span class="o">;</span> |
| <span class="k">return</span> <span class="s">"zero"</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="n">message</span> <span class="o">=</span> <span class="s">"It's 1"</span><span class="o">;</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>Next, we add a new JSP to the application named <code class="highlighter-rouge">WEB-INF/content/hello-world-zero.jsp</code>. Notice that the first part |
| of the file name is the same as the URL of the action and the last part of the name is the result code. This is |
| the convention that the plugin uses to determine which results to render. Here is our new JSP:</p> |
| |
| <p><strong>WEB-INF/content/hello-world.jsp</strong></p> |
| |
| <pre><code class="language-jsp"><html> |
| <body> |
| The error message is ${message} |
| </body> |
| </html> |
| </code></pre> |
| |
| <p>Now, if you compile the action and restart the application, based on the current time, you’ll either see the result from |
| <code class="highlighter-rouge">WEB-INF/content/hello-world.jsp</code> or <code class="highlighter-rouge">WEB-INF/content/hello-world-zero.jsp</code>.</p> |
| |
| <p>The result type is based on the extension of the file. The supported extensions are: jsp,ftl,vm,html,html. |
| Examples of Action and Result to Template mapping:</p> |
| |
| <table> |
| <thead> |
| <tr> |
| <th>URL</th> |
| <th>Result</th> |
| <th>File that could match</th> |
| <th>Result Type</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>/hello</td> |
| <td>success</td> |
| <td>/WEB-INF/content/hello.jsp</td> |
| <td>Dispatcher</td> |
| </tr> |
| <tr> |
| <td>/hello</td> |
| <td>success</td> |
| <td>/WEB-INF/content/hello-success.htm</td> |
| <td>Dispatcher</td> |
| </tr> |
| <tr> |
| <td>/hello</td> |
| <td>success</td> |
| <td>/WEB-INF/content/hello.ftl</td> |
| <td>FreeMarker</td> |
| </tr> |
| <tr> |
| <td>/hello-world</td> |
| <td>input</td> |
| <td>/WEB-INF/content/hello-world-input.vm</td> |
| <td>Velocity</td> |
| </tr> |
| <tr> |
| <td>/test1/test2/hello</td> |
| <td>error</td> |
| <td>/WEB-INF/content/test/test2/hello-error.html</td> |
| <td>Dispatcher</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <h2 id="multiple-names">Multiple names</h2> |
| |
| <p>It is possible to define multiple names for the same result:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Action</span><span class="o">(</span><span class="n">results</span> <span class="o">=</span> <span class="o">{</span> |
| <span class="nd">@Result</span><span class="o">(</span><span class="n">name</span><span class="o">={</span><span class="s">"error"</span><span class="o">,</span> <span class="s">"input"</span><span class="o">},</span> <span class="n">location</span><span class="o">=</span><span class="s">"input-form.jsp"</span><span class="o">),</span> |
| <span class="nd">@Result</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"success"</span><span class="o">,</span> <span class="n">location</span><span class="o">=</span><span class="s">"success.jsp"</span><span class="o">)</span> |
| <span class="o">})</span> |
| </code></pre></div></div> |
| |
| <p>Such functionality was added in Struts version 2.5.</p> |
| |
| <p>##Chaining</p> |
| |
| <p>If one action returns the name of another action in the same package, they will be chained together, if the first action |
| doesn’t have any result defined for that code. In the following example:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloAction</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"foo"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">foo</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="s">"bar"</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"foo-bar"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">bar</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The “foo” action will be executed, because no result is found, the Convention plugin tries to find an action named |
| “foo-bar” on the same package where “foo” is defined. If such an action is found, it will be invoked using |
| the “chain” result.</p> |
| |
| <h2 id="xwork-packages">XWork packages</h2> |
| |
| <p>Actions are placed on a custom XWork package which prevents conflicts. The name of this package is based on the Java |
| package the action is defined in, the namespace part of the URL for the action and the parent XWork package for |
| the action. The parent XWork package is determined based on the property named <code class="highlighter-rouge">struts.convention.default.parent.package</code> |
| (defaults to <code class="highlighter-rouge">convention-default</code>), which is a custom XWork package that extends <code class="highlighter-rouge">struts-default</code>.</p> |
| |
| <p>Therefore the naming for XWork packages used by the Convention plugin are in the form:</p> |
| |
| <p><strong>XWork package naming</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code><java-package>#<namespace>#<parent-package> |
| </code></pre></div></div> |
| |
| <p>Using our example from above, the XWork package for our action would be:</p> |
| |
| <p><strong>XWork package naming</strong></p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com.example.actions#/#conventionDefault |
| </code></pre></div></div> |
| |
| <h2 id="annotation-reference">Annotation reference</h2> |
| |
| <p>The Convention plugin uses a number of different annotations to override the default conventions that are used to map |
| actions to URLs and locate results. In addition, you can modify the parent XWork package that actions are configured with.</p> |
| |
| <h3 id="action-annotation">Action annotation</h3> |
| |
| <p>The Convention plugin allows action classes to change the URL that they are mapped to using the <strong>Action</strong> annotation. |
| This annotation can also be used inside the <strong>Actions</strong> annotation to allow multiple URLs to map to a single action |
| class. This annotation must be defined on action methods like this:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/different/url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>Our action class will now map to the URL <code class="highlighter-rouge">/different/url</code> rather than <code class="highlighter-rouge">/hello-world</code>. If no <code class="highlighter-rouge">@Result</code> (see next section) |
| is specified, then the namespace of the action will be used as the path to the result, on our last example it would be |
| <code class="highlighter-rouge">/WEB-INF/content/different/url.jsp</code>.</p> |
| |
| <p>A single method within an action class can also map to multiple URLs using the <strong>Actions</strong> annotation like this:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Actions</span><span class="o">({</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/different/url"</span><span class="o">),</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/another/url"</span><span class="o">)</span> |
| <span class="o">})</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>Another usage of the <strong>Action</strong> or <strong>Actions</strong> annotation is to define multiple action methods within a single action |
| class, each of which respond to a different URL. Here is an example of multiple action methods:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/different/url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| |
| |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The previous example defines a second URL that is not fully qualified. This means that the namespace for the URL |
| is determined using the Java package name rather than the Action annotation.</p> |
| |
| <p>Interceptor and interceptor stacks can be specified using the <code class="highlighter-rouge">interceptorRefs</code> attribute. The following example applies |
| the <code class="highlighter-rouge">validation</code> interceptor and the <code class="highlighter-rouge">defaultStack</code> interceptor stack to the action:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">interceptorRefs</span><span class="o">={</span><span class="nd">@InterceptorRef</span><span class="o">(</span><span class="s">"validation"</span><span class="o">),</span> <span class="nd">@InterceptorRef</span><span class="o">(</span><span class="s">"defaultStack"</span><span class="o">)})</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>Parameters can be passed to results using the <strong>params</strong> attribute. The value of this attribute is a string array with |
| an even number of elements in the form <code class="highlighter-rouge">{"key0", "value0, "key1", "value1" ... "keyN", "valueN"}</code>. For example:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">interceptorRefs</span><span class="o">=</span><span class="nd">@InterceptorRef</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"validation"</span><span class="o">,</span><span class="n">params</span><span class="o">={</span><span class="s">"programmatic"</span><span class="o">,</span> <span class="s">"false"</span><span class="o">,</span> <span class="s">"declarative"</span><span class="o">,</span> <span class="s">"true})) |
| public String execute() { |
| return SUCCESS; |
| } |
| |
| @Action("</span><span class="n">url</span><span class="err">"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>If interceptors are not specified, the default stack is applied.</p> |
| |
| <blockquote> |
| <p>You can specify className parameter which can be especially useful when Spring Framework is used to instantiate actions.</p> |
| </blockquote> |
| |
| <h4 id="applying-action-and-actions-at-the-class-level">Applying <code class="highlighter-rouge">@Action</code> and <code class="highlighter-rouge">@Actions</code> at the class level</h4> |
| |
| <p>There are circumstances when this is desired, like when using <em>Dynamic Method Invocation</em> . If an <code class="highlighter-rouge">execute</code> 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)</p> |
| |
| <h3 id="interceptorref-annotation">InterceptorRef annotation</h3> |
| |
| <p>Interceptors can be specified at the method level, using the <strong>Action</strong> annotation or at the class level using |
| the <code class="highlighter-rouge">InterceptorRefs</code> annotation. Interceptors specified at the class level will be applied to all actions defined |
| on that class. In the following example:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| |
| <span class="nd">@InterceptorRefs</span><span class="o">({</span> |
| <span class="nd">@InterceptorRef</span><span class="o">(</span><span class="s">"interceptor-1"</span><span class="o">),</span> |
| <span class="nd">@InterceptorRef</span><span class="o">(</span><span class="s">"defaultStack"</span><span class="o">)</span> |
| <span class="o">})</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"action1"</span><span class="o">,</span> <span class="n">interceptorRefs</span><span class="o">=</span><span class="nd">@InterceptorRef</span><span class="o">(</span><span class="s">"validation"</span><span class="o">))</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"action2"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The following interceptors will be applied to “action1”: <code class="highlighter-rouge">interceptor-1</code>, all interceptors from <code class="highlighter-rouge">defaultStack</code>, |
| and <code class="highlighter-rouge">validation</code>. For “action2”, <code class="highlighter-rouge">interceptor-1</code> and all interceptors from <code class="highlighter-rouge">defaultStack</code> will be applied to “action2”.</p> |
| |
| <blockquote> |
| <p>If you get errors like “Unable to find interceptor class referenced by ref-name XYZ”. This means that the package |
| where Convention is placing your actions, does not extend the package where the interceptor is defined. To fix this |
| problem either 1)Use @ParentPackage annotation(or struts.convention.default.parent.package) passing the name of the |
| package that defines the interceptor, or 2) Create a package in XML that extends the package that defines the |
| interceptor, and use @ParentPackage(or struts.convention.default.parent.package) to point to it.</p> |
| </blockquote> |
| |
| <h3 id="result-annotation">Result annotation</h3> |
| |
| <p>The Convention plugin allows action classes to define different results for an action. Results fall into two categories, |
| global and local. Global results are shared across all actions defined within the action class. These results are |
| defined as annotations on the action class. Local results apply only to the action method they are defined on. Here is |
| an example of the different types of result annotations:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Result</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Results</span><span class="o">;</span> |
| |
| <span class="nd">@Results</span><span class="o">({</span> |
| <span class="nd">@Result</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"failure"</span><span class="o">,</span> <span class="n">location</span><span class="o">=</span><span class="s">"fail.jsp"</span><span class="o">)</span> |
| <span class="o">})</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"/different/url"</span><span class="o">,</span> |
| <span class="n">results</span><span class="o">={</span><span class="nd">@Result</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"success"</span><span class="o">,</span> <span class="n">location</span><span class="o">=</span><span class="s">"http://struts.apache.org"</span><span class="o">,</span> <span class="n">type</span><span class="o">=</span><span class="s">"redirect"</span><span class="o">)}</span> |
| <span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/another/url"</span><span class="o">)</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>Parameters can be passed to results using the <strong>params</strong> attribute. The value of this attribute is a string array with |
| an even number of elements in the form <code class="highlighter-rouge">{"key0", "value0, "key1", "value1" ... "keyN", "valueN"}</code>. For example:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Actions</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Result</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Results</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"/different/url"</span><span class="o">,</span> |
| <span class="n">results</span><span class="o">={</span><span class="nd">@Result</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"success"</span><span class="o">,</span> <span class="n">type</span><span class="o">=</span><span class="s">"httpheader"</span><span class="o">,</span> <span class="n">params</span><span class="o">={</span><span class="s">"status"</span><span class="o">,</span> <span class="s">"500"</span><span class="o">,</span> <span class="s">"errorMessage"</span><span class="o">,</span> <span class="s">"Internal Error"</span><span class="o">})}</span> |
| <span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/another/url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>From 2.1.7 on, global results (defined on the class level) defined using annotations will be inherited. Child classes |
| can override the inherited result(s) by redefining it. Also, results defined at the method level take precedence |
| (overwrite), over results with the same name at the action level.</p> |
| |
| <h3 id="namespace-annotation">Namespace annotation</h3> |
| |
| <p>The namespace annotation allows the namespace for action classes to be changed instead of using the convention of the Java |
| package name. This annotation can be placed on an action class or within the package-info.java class that allows |
| annotations to be placed on Java packages. When this annotation is put on an action class, it applies to all actions |
| defined in the class, that are not fully qualified action URLs. When this annotation is place in the <code class="highlighter-rouge">package-info.java</code> |
| file, it changes the default namespace for all actions defined in the Java package. Here is an example of the annotation |
| on an action class:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Namespace</span><span class="o">;</span> |
| |
| <span class="nd">@Namespace</span><span class="o">(</span><span class="s">"/custom"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"/different/url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"url"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">doSomething</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>In this example, the action will respond to two different URLs <code class="highlighter-rouge">/different/url</code> and <code class="highlighter-rouge">/custom/url</code>. Here is an example |
| of using this annotation in the package-info.java file:</p> |
| |
| <p><strong>com/example/actions/package-info.java</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@org</span><span class="o">.</span><span class="na">apache</span><span class="o">.</span><span class="na">struts2</span><span class="o">.</span><span class="na">convention</span><span class="o">.</span><span class="na">annotation</span><span class="o">.</span><span class="na">Namespace</span><span class="o">(</span><span class="s">"/custom"</span><span class="o">)</span> |
| <span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| </code></pre></div></div> |
| |
| <p>This changes the default namespace for all actions defined in the package <code class="highlighter-rouge">com.example.actions</code>. This annotation however |
| doesn’t apply to sub-packages.</p> |
| |
| <h3 id="resultpath-annotation">ResultPath annotation</h3> |
| |
| <p>The ResultPath annotation allows applications to change the location where results are stored. This annotation can be |
| placed on an action class and also in the package-info.java file. Here is an example of using this annotation:</p> |
| |
| <p><strong>com.example.actions.HelloWorl</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.ResultPath</span><span class="o">;</span> |
| |
| <span class="nd">@ResultPath</span><span class="o">(</span><span class="s">"/WEB-INF/jsps"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The result for this class will be located in <code class="highlighter-rouge">WEB-INF/jsps</code> rather than the default of <code class="highlighter-rouge">WEB-INF/content</code>.</p> |
| |
| <h3 id="parentpackage-annotation">ParentPackage annotation</h3> |
| |
| <p>The ParentPackage annotation allows applications to define different parent Struts package for specific action classes |
| or Java packages. Here is an example of using the annotation on an action class:</p> |
| |
| <p><strong>com.example.actions.HelloWorld</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span> |
| |
| <span class="kn">import</span> <span class="nn">com.opensymphony.xwork2.ActionSupport</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.Action</span><span class="o">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.struts2.convention.annotation.ParentPackage</span><span class="o">;</span> |
| |
| <span class="nd">@ParentPackage</span><span class="o">(</span><span class="s">"customXWorkPackage"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>To apply this annotation to all actions in a package (and subpackages), add it to package-info.java. An alternative |
| to this annotation is to set <code class="highlighter-rouge">struts.convention.default.parent.package</code> in XML.</p> |
| |
| <h3 id="exceptionmapping-annotation">ExceptionMapping Annotation</h3> |
| |
| <p>This annotation can be used to define exception mappings to actions. See the <em>exception mapping documentation</em> for more |
| details. These mappings can be applied to the class level, in which case they will be applied to all actions defined |
| on that class:</p> |
| |
| <p><strong>ExceptionsActionLevelAction.java</strong></p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@ExceptionMappings</span><span class="o">({</span> |
| <span class="nd">@ExceptionMapping</span><span class="o">(</span><span class="n">exception</span> <span class="o">=</span> <span class="s">"java.lang.NullPointerException"</span><span class="o">,</span> <span class="n">result</span> <span class="o">=</span> <span class="s">"success"</span><span class="o">,</span> <span class="n">params</span> <span class="o">=</span> <span class="o">{</span><span class="s">"param1"</span><span class="o">,</span> <span class="s">"val1"</span><span class="o">})</span> |
| <span class="o">})</span> |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">ExceptionsActionLevelAction</span> <span class="o">{</span> |
| |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="kc">null</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The parameters defined by <code class="highlighter-rouge">params</code> are passed to the result. Exception mappings can also be applied to the action level:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ExceptionsMethodLevelAction</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"exception1"</span><span class="o">,</span> <span class="n">exceptionMappings</span> <span class="o">=</span> <span class="o">{</span> |
| <span class="nd">@ExceptionMapping</span><span class="o">(</span><span class="n">exception</span> <span class="o">=</span> <span class="s">"java.lang.NullPointerException"</span><span class="o">,</span> <span class="n">result</span> <span class="o">=</span> <span class="s">"success"</span><span class="o">,</span> <span class="n">params</span> <span class="o">=</span> <span class="o">{</span><span class="s">"param1"</span><span class="o">,</span> <span class="s">"val1"</span><span class="o">})</span> |
| <span class="o">})</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">run1</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="kc">null</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <h2 id="actions-in-jar-files">Actions in jar files</h2> |
| |
| <p>By default the Convention plugin will <strong>not</strong> scan jar files for actions. For a jar to be scanned, its URL needs |
| to match at least one of the regular expressions in <code class="highlighter-rouge">struts.convention.action.includeJars</code> . In this example |
| <code class="highlighter-rouge">myjar1.jar</code> and <code class="highlighter-rouge">myjar2.jar</code> will be scanned:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.action.includeJars"</span> <span class="na">value=</span><span class="s">".*?/myjar1.*?jar(!/)?,.*?/myjar2*?jar(!/)?"</span> |
| </code></pre></div></div> |
| |
| <p>Note that <strong>the regular expression will be evaluated against the URL of the jar, and not the file name</strong>, the jar URL |
| can contain a path to the jar file and a trailing <code class="highlighter-rouge">!/</code>.</p> |
| |
| <h2 id="automatic-configuration-reloading">Automatic configuration reloading</h2> |
| |
| <p>The Convention plugin can automatically reload configuration changes, made in classes the contain actions, without |
| restarting the container. This is a similar behavior to the automatic xml configuration reloading. To enable this |
| feature, add this to your <code class="highlighter-rouge">struts.xml</code> file:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.devMode"</span> <span class="na">value=</span><span class="s">"true"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.classes.reload"</span> <span class="na">value=</span><span class="s">"true"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>This feature is experimental and has not been tested on all container, and it is <strong>strongly</strong> advised not to use it |
| in production environments.</p> |
| |
| <h2 id="jboss">JBoss</h2> |
| |
| <p>When using this plugin with JBoss, you need to set the following constants:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.exclude.parentClassLoader"</span> <span class="na">value=</span><span class="s">"true"</span> <span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.action.fileProtocols"</span> <span class="na">value=</span><span class="s">"jar,vfsfile,vfszip"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>You can also check the <em>JBoss 5</em> page for more details.</p> |
| |
| <h2 id="jetty-embedded">Jetty (embedded)</h2> |
| |
| <p>When using this plugin with Jetty in embedded mode, you need to set the following constants:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.exclude.parentClassLoader"</span> <span class="na">value=</span><span class="s">"false"</span> <span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.action.fileProtocols"</span> <span class="na">value=</span><span class="s">"jar,code-source"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h2 id="troubleshooting">Troubleshooting</h2> |
| |
| <h3 id="tips">Tips</h3> |
| |
| <ul> |
| <li> |
| <p>Make sure the namespace of the action is matched by one of the locators. The rest of the namespace after the locator, |
| will be the namespace of the action, and will be used to find the results. For example, a class called “ViewAction” in |
| the package “my.example.actions.orders” will be mapped to the URL /orders/view.action, and the results must be under |
| /WEB-INF/content/orders, like /WEB-INF/content/orders/view-success.jsp.</p> |
| </li> |
| <li> |
| <p>Add the <em>Config Browser Plugin</em> plugin to the lib folder or maven dependencies, and then visit: |
| <a href="http://localhost:8080/CONTEXT/config-browser/index.action">http://localhost:8080/CONTEXT/config-browser/index.action</a>, |
| to see the current action mappings.</p> |
| </li> |
| <li> |
| <p>The Convention plugin can generate a rather verbose output when set to debug mode for logging. Use “Trace” logging |
| level if you are using the JDK logger. If you are using Log4J, you can do something like: |
| log4j.logger.org.apache.struts2.convention=DEBUG</p> |
| </li> |
| </ul> |
| |
| <h3 id="common-errors">Common Errors</h3> |
| |
| <ol> |
| <li> |
| <p>I get an error like “There is no Action mapped for namespace /orders and action name view.”. This means that the URL |
| <code class="highlighter-rouge">/orders/view.action</code> is not mapping to any action class. Check the namespace and the name of the action.</p> |
| </li> |
| <li> |
| <p>I get an error like “No result defined for action my.example.actions.orders.ViewAction and result success”. This |
| means that the action was mapped to the right URL, but the Convention plugin was unable to find a <code class="highlighter-rouge">success</code> result |
| for it. Check that the result file exists, like <code class="highlighter-rouge">/WEB-INF/content/orders/view-success.jsp</code>.</p> |
| </li> |
| <li> |
| <p>I get lots of errors like “java.lang.Exception: Could not load org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.class”. |
| This happens when <code class="highlighter-rouge">struts.convention.action.includeJars</code> is matching jar URLs from external jars.</p> |
| </li> |
| <li> |
| <p>I am using a custom interceptor stack and I get an error like “Unable to find interceptor class referenced by ref-name XYZ”. |
| This means that the package where Convention is placing your actions, does not extend the package where the interceptor |
| is defined. To fix this problem either 1)Use @ParentPackage annotation (or <code class="highlighter-rouge">struts.convention.default.parent.package</code>) |
| passing the name of the package that defines the interceptor, or 2) Create a package in XML that extends the package |
| that defines the interceptor, and use @ParentPackage (or <code class="highlighter-rouge">struts.convention.default.parent.package</code>) to point to it.</p> |
| </li> |
| </ol> |
| |
| <h2 id="overwriting-plugin-classes">Overwriting plugin classes</h2> |
| |
| <p>The Convention plugin can be extended in the same fashion that Struts does. The following beans are defined by default:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.ActionConfigBuilder"</span> <span class="na">name=</span><span class="s">"convention"</span> |
| <span class="na">class=</span><span class="s">"org.apache.struts2.convention.PackageBasedActionConfigBuilder"</span><span class="nt">/></span> |
| <span class="c"><!-- |
| This interface defines how the action configurations for the current web application can be constructed. This must |
| find all actions that are not specifically defined in the struts XML files or any plugins. Furthermore, it must make |
| every effort to locate all action results as well. |
| --></span> |
| |
| <span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.ActionNameBuilder"</span> <span class="na">name=</span><span class="s">"convention"</span> |
| <span class="na">class=</span><span class="s">"org.apache.struts2.convention.SEOActionNameBuilder"</span><span class="nt">/></span> |
| <span class="c"><!-- |
| This interface defines the method that is used to create action names based on the name of a class. |
| --></span> |
| |
| <span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.ResultMapBuilder"</span> <span class="na">name=</span><span class="s">"convention"</span> |
| <span class="na">class=</span><span class="s">"org.apache.struts2.convention.DefaultResultMapBuilder"</span><span class="nt">/></span> |
| <span class="c"><!-- |
| This interface defines how results are constructed for an Action. The action information is supplied and the result is |
| a mapping of ResultConfig instances to the result name. |
| --></span> |
| |
| <span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.InterceptorMapBuilder"</span> <span class="na">name=</span><span class="s">"convention"</span> |
| <span class="na">class=</span><span class="s">"org.apache.struts2.convention.DefaultInterceptorMapBuilder"</span><span class="nt">/></span> |
| <span class="c"><!-- |
| This interface defines how interceptors are built from annotations. |
| --></span> |
| |
| <span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.ConventionsService"</span> <span class="na">name=</span><span class="s">"convention"</span> |
| <span class="na">class=</span><span class="s">"org.apache.struts2.convention.ConventionsServiceImpl"</span><span class="nt">/></span> |
| <span class="c"><!-- |
| This interface defines the conventions that are used by the convention plugin. In most cases the methods on this class |
| will provide the best default for any values and also handle locating overrides of the default via the annotations that |
| are part of the plugin. |
| --></span> |
| |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.actionConfigBuilder"</span> <span class="na">value=</span><span class="s">"convention"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.actionNameBuilder"</span> <span class="na">value=</span><span class="s">"convention"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.resultMapBuilder"</span> <span class="na">value=</span><span class="s">"convention"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.interceptorMapBuilder"</span> <span class="na">value=</span><span class="s">"convention"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.conventionsService"</span> <span class="na">value=</span><span class="s">"convention"</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>To plugin a different implementation for one of these classes, implement the interface, define a bean for it, and set |
| the appropriate constant’s value with the name of the new bean, for example:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.convention.ActionNameBuilder"</span> <span class="na">name=</span><span class="s">"MyActionNameBuilder"</span> <span class="na">class=</span><span class="s">"example.SultansOfSwingNameBuilder"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.actionNameBuilder"</span> <span class="na">value=</span><span class="s">"MyActionNameBuilder"</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h2 id="configuration-reference">Configuration reference</h2> |
| |
| <p>Add a <strong>constant</strong> element to your struts config file to change the value of a configuration setting, like:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.convention.result.path"</span> <span class="na">value=</span><span class="s">"/WEB-INF/mytemplates/"</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <table> |
| <thead> |
| <tr> |
| <th>Name</th> |
| <th>Default Value</th> |
| <th>Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>struts.convention.action.alwaysMapExecute</td> |
| <td>true</td> |
| <td>Set to false, to prevent Convention from creating a default mapping to “execute” when there are other methods annotated as actions in the class</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.includeJars</td> |
| <td> </td> |
| <td>Comma separated list of regular expressions of jar URLs to be scanned. eg. “.<strong>myJar-0\.2.</strong>, .<strong>thirdparty-0\.1.</strong>”</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.packages</td> |
| <td> </td> |
| <td>An optional list of action packages that this should create configuration for (they don’t need to match a locator pattern)</td> |
| </tr> |
| <tr> |
| <td>struts.convention.result.path</td> |
| <td>/WEB-INF/content/</td> |
| <td>Directory where templates are located</td> |
| </tr> |
| <tr> |
| <td>struts.convention.result.flatLayout</td> |
| <td>true</td> |
| <td>If set to false, the result can be put in its own directory: resultsRoot/namespace/actionName/result.extension</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.suffix</td> |
| <td>Action</td> |
| <td>Suffix used to find actions based on class names</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.disableScanning</td> |
| <td>false</td> |
| <td>Scan packages for actions</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.mapAllMatches</td> |
| <td>false</td> |
| <td>Create action mappings, even if no @Action is found</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.checkImplementsAction</td> |
| <td>true</td> |
| <td>Check if an action implements com.opensymphony.xwork2.Action to create an action mapping</td> |
| </tr> |
| <tr> |
| <td>struts.convention.default.parent.package</td> |
| <td>convention-default</td> |
| <td>Default parent package for action mappins</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.name.lowercase</td> |
| <td>true</td> |
| <td>Convert action name to lowercase</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.name.separator</td> |
| <td>-</td> |
| <td>Separator used to build the action name, MyAction -> my-action. This character is also used as the separator between the action name and the result in templates, like action-result.jsp</td> |
| </tr> |
| <tr> |
| <td>struts.convention.package.locators</td> |
| <td>action,actions,struts,struts2</td> |
| <td>Packages whose name end with one of these strings will be scanned for actions</td> |
| </tr> |
| <tr> |
| <td>struts.convention.package.locators.disable</td> |
| <td>false</td> |
| <td>Disable the scanning of packages based on package locators</td> |
| </tr> |
| <tr> |
| <td>struts.convention.exclude.packages</td> |
| <td><code class="highlighter-rouge">org.apache.struts.\*</code>, <code class="highlighter-rouge">org.apache.struts2.\*</code>, <code class="highlighter-rouge">org.springframework.web.struts.\*</code>, <code class="highlighter-rouge">org.springframework.web.struts2.\*</code>, <code class="highlighter-rouge">org.hibernate.\*</code></td> |
| <td>Packages excluded from the action scanning, packages already excluded cannot be included in other way, eg. org.demo.actions.exclude is specified as a part of the struts.convention.exclude.packages so all packages below are also excluded, eg. org.demo.actions.exclude.include even if <strong>include</strong> is specified as a struts.convention.package.locators or struts.convention.action.packages</td> |
| </tr> |
| <tr> |
| <td>struts.convention.package.locators.basePackage</td> |
| <td> </td> |
| <td>If set, only packages that start with its value will be scanned for actions</td> |
| </tr> |
| <tr> |
| <td>struts.convention.relative.result.types</td> |
| <td>dispatcher,velocity,freemarker</td> |
| <td>The list of result types that can have locations that are relative and the result location (which is the resultPath plus the namespace) prepended to them</td> |
| </tr> |
| <tr> |
| <td>struts.convention.redirect.to.slash</td> |
| <td>true</td> |
| <td>A boolean parameter that controls whether or not this will handle unknown actions in the same manner as Apache, Tomcat and other web servers. This handling will send back a redirect for URLs such as /foo to /foo/ if there doesn’t exist an action that responds to /foo</td> |
| </tr> |
| <tr> |
| <td>struts.convention.classLoader.excludeParent</td> |
| <td>true</td> |
| <td>Exclude URLs found by the parent class loader from the list of URLs scanned to find actions (needs to be set to false for JBoss 5)</td> |
| </tr> |
| <tr> |
| <td>struts.convention.action.eagerLoading</td> |
| <td>false</td> |
| <td>If set, found action classes will be instantiated by the ObjectFactory to accelerate future use, setting it up can clash with Spring managed beans</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| </section> |
| </article> |
| |
| |
| <footer class="container"> |
| <div class="col-md-12"> |
| Copyright © 2000-2018 <a href="http://www.apache.org/">The Apache Software Foundation </a>. |
| All Rights Reserved. |
| </div> |
| <div class="col-md-12"> |
| Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are |
| trademarks of The Apache Software Foundation. |
| </div> |
| <div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div> |
| </footer> |
| |
| <script>!function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (!d.getElementById(id)) { |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//platform.twitter.com/widgets.js"; |
| fjs.parentNode.insertBefore(js, fjs); |
| } |
| }(document, "script", "twitter-wjs");</script> |
| <script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script> |
| |
| <div id="fb-root"></div> |
| |
| <script>(function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (d.getElementById(id)) return; |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1"; |
| fjs.parentNode.insertBefore(js, fjs); |
| }(document, 'script', 'facebook-jssdk'));</script> |
| |
| |
| </body> |
| </html> |