http://git-wip-us.apache.org/repos/asf/struts-site/blob/c0b0f328/content/plugins/plugin-developers.html
----------------------------------------------------------------------
diff --git a/content/plugins/plugin-developers.html 
b/content/plugins/plugin-developers.html
new file mode 100644
index 0000000..1d88b8c
--- /dev/null
+++ b/content/plugins/plugin-developers.html
@@ -0,0 +1,8786 @@
+<!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>Plugins Developers Guide (WIP)</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="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.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="/downloads.html">Downloads</a></li>
+                <li><a href="/announce.html">Announcements</a></li>
+                <li><a href="http://www.apache.org/licenses/";>License</a></li>
+                <li><a 
href="http://apache.org/foundation/thanks.html";>Thanks!</a></li>
+                <li><a 
href="http://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="/maven/project-info.html">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 class="divider"></li>
+                <li><a href="/maven/struts2-core/apidocs/index.html">Struts 
Core API</a></li>
+                <li><a href="/docs/plugins.html">Plugin APIs</a></li>
+                <li><a href="/docs/tag-reference.html">Tag reference</a></li>
+                <li><a 
href="http://cwiki.apache.org/S2PLUGINS/home.html";>Plugin registry</a></li>
+                <li class="divider"></li>
+                <li><a href="/docs/tutorials.html">Tutorials - 
DEPRECATED</a></li>
+                <li><a href="/docs/faqs.html">FAQs - DEPRECATED</a></li>
+                <li><a href="/docs/guides.html">Guides - DEPRECATED</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 class="divider"></li>
+                <li><a href="/submitting-patches.html">Submitting 
patches</a></li>
+                <li><a href="/builds.html">Source Code</a></li>
+                <li><a href="/coding-standards.html">Coding standards</a></li>
+                <li class="divider"></li>
+                <li><a href="/releases.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://git-wip-us.apache.org/repos/asf?p=struts.git";>Source 
Repository</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/plugin-developers.md";
 title="Edit this page on GitHub">Edit on GitHub</a>
+    <p>#Plugin Developers Guide# {#PAGE_44163}</p>
+
+<p>Apache Struts 2 provides a simple <a href="#PAGE_13868">plugin 
architecture</a> so that developers can extend the framework just by adding a 
JAR to the application’s classpath. Since plugins are contained in a JAR, 
they are easy to share with others. Several plugins are bundled with the 
framework, and others are available from third-party sources.</p>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+      <td>+ <a href="#PAGE_13868">Plugins</a></td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+      <td>+ <em>Extending an Application with Custom Plugins</em></td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+      <td><strong>Bundled Plugins</strong></td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>| |\
+\
++ <a href="#PAGE_57904184">Bean Validation Plugin</a> (2.5+)\
+\
++ <a href="#PAGE_27842284">CDI (JSR 299) Plugin</a> (2.3.1+)\
+\
++ <a href="#PAGE_29637">Codebehind Plugin</a> (&lt; 2.5)\
+\
++ <a href="#PAGE_44185">Config Browser Plugin</a>\
+\
++ <a href="#PAGE_105613">Convention Plugin</a> (2.1.3+)\
+\
++ <a href="#PAGE_82454">DWR Plugin</a>\
+\
++ <a href="#PAGE_2852037">Embedded JSP Plugin</a> (2.1.7+)\
+\
++ <a href="#PAGE_14258">JasperReports Plugin</a>\
+\
++ <a href="#PAGE_50857342">Java 8 Support Plugin</a> (2.3.21 - 2.5.2)\
+\
++ <a href="#PAGE_105841">Javatemplates Plugin</a> (2.1.3+)\
+\
++ <a href="#PAGE_14300">JFreeChart Plugin</a>\
+\
++ <a href="#PAGE_44198">JSF Plugin</a>( &lt; 2.5)\
+\
++ <a href="#PAGE_2850922">JSON Plugin</a>  (2.1.7+)\
+\
++ <a href="#PAGE_82304">JUnit Plugin</a>\
+|\
+\
++ <a href="#PAGE_114997">OVal Plugin</a> (2.1.7+)\
+\
++ <a href="#PAGE_114995">OSGi Plugin</a> (2.1.7+)\
+\
++ <a href="#PAGE_44204">Plexus Plugin</a>\
+\
++ <a href="#PAGE_74033">Portlet Plugin</a>\
+\
++ <a href="#PAGE_30150178">Portlet Tiles Plugin</a> (2.3.5+)\
+\
++ <a href="#PAGE_70699">REST Plugin</a> (2.1.1+)\
+\
++ Deprecated: <a href="#PAGE_14137">SiteGraph Plugin</a>\
+\
++ <a href="#PAGE_14142">SiteMesh Plugin</a>\
+\
++ <a href="#PAGE_14281">Spring Plugin</a>\
+\
++ <a href="#PAGE_44227">Struts 1 Plugin</a>( &lt; 2.5)\
+\
++ <a href="#PAGE_82452">TestNG Plugin</a>\
+\
++ <a href="#PAGE_27401">Tiles Plugin</a>\
+\
++ <a href="#PAGE_30750969">Tiles 3 Plugin</a>  (&lt; 2.5)\
+|
+|————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————|———————————————————————————————————————————————————————————————————————————————————————————————————————————————â€
 
”————————————————————————————————————————————————————————————————————–|</p>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+      <td>(ok)  For a complete list of bundled and third-party plugins, visit 
the <a href="http://cwiki\.apache\.org/S2PLUGINS/home\.html";>Plugin 
Registry.</a>^[http://cwiki.apache.org/S2PLUGINS/home.html].</td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>###Next:###</p>
+
+<p>##Bean Validation Plugin## {#PAGE_57904184}</p>
+
+<p>###Bean Validation###</p>
+
+<p>The Bean Validation plugin implements a bridge to use Bean Validation in 
struts actions. Bean Validation has been specified in JSR 303 and is part of 
the JavaEE platform. Full-fledged application servers already bring validation 
providers which can be leveraged by this plugin. The plugin integrates with 
other struts features like:</p>
+
+<ul>
+  <li>
+    <p>i18n</p>
+  </li>
+  <li>
+    <p>model driven</p>
+  </li>
+  <li>
+    <p>AJAX Validation</p>
+  </li>
+  <li>
+    <p>workflow</p>
+  </li>
+</ul>
+
+<p>###Setup###</p>
+
+<p>In order to use the Bean Validation plugin, you first need to add the JAR 
file to the </p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>WEB-INF/lib
+</code></pre>
+</div>
+<p> directory of your application or include the dependency in your 
project’s Maven POM file.</p>
+
+<p><strong>pom.xml</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;dependency&gt;
+    &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
+    &lt;artifactId&gt;struts2-bean-validation-plugin&lt;/artifactId&gt;
+    &lt;version&gt;X.X.X&lt;/version&gt;
+&lt;/dependency&gt;
+
+</code></pre>
+</div>
+
+<p>Where X.X.X is the current version of Struts 2. Please remember that the 
Bean Validation Plugin is available from version 2.5.</p>
+
+<p>###Configuration###</p>
+
+<p>This sample shows the configuration constants the plugin provides. It also 
shows how to enable bean-validation by extending your own application package 
from </p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts-bean-validation
+</code></pre>
+</div>
+<p>which comes along with the plugin.</p>
+
+<p><strong>struts.xml</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>    &lt;constant 
name="struts.beanValidation.providerClass" 
value="org.hibernate.validator.HibernateValidator"/&gt;
+    &lt;constant name="struts.beanValidation.ignoreXMLConfiguration" 
value="false"/&gt;
+    &lt;constant name="struts.beanValidation.convertMessageToUtf" 
value="false"/&gt;
+    &lt;constant name="struts.beanValidation.convertMessageFromEncoding" 
value="ISO-8859-1"/&gt;
+ 
+       &lt;package name="my-bean-validation" 
extends="struts-bean-validation"&gt;
+       &lt;/package&gt;
+</code></pre>
+</div>
+
+<p>Here is another example that shows how you can combine bean-validation with 
other plugins by configuring your own Interceptor-Stack (note: this is just a 
very short example. In a real app you should take more care about your stack). 
You can combine bean validation with classic struts validation (or disable 
either) by putting the according interceptors in your stack (or by removing 
them from your stack).</p>
+
+<p><strong>struts.xml</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>   &lt;package 
name="my-app-package" extends="struts-default"&gt;
+               &lt;interceptors&gt;
+                       &lt;interceptor
+                                name="beanValidation"
+                                
class="org.apache.struts.beanvalidation.validation.interceptor.BeanValidationInterceptor"/&gt;
+
+                       &lt;interceptor-stack name="appDefaultStack"&gt;
+                               &lt;interceptor-ref name="beanValidation"/&gt;
+                               &lt;interceptor-ref name="defaultStack"/&gt;
+                       &lt;/interceptor-stack&gt;
+               &lt;/interceptors&gt;
+       &lt;/package&gt;
+</code></pre>
+</div>
+
+<p> </p>
+
+<p>###Bean Validation Example###</p>
+
+<p>Here is an example Action that makes use of bean validation. Note that some 
of the validation annotations are taken from</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>javax
+</code></pre>
+</div>
+<p>package (which is defined in the JSR) while others are taken from the 
validaton provider (in this case:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>hibernate
+</code></pre>
+</div>
+<p>). You can specifiy own text keys in the</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>message
+</code></pre>
+</div>
+<p>attribute of the annotations. If you do that the whole struts i18n 
mechanism kicks in to resolve those text keys.</p>
+
+<p><strong>com.example.actions.BeanValidationAction</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.beanvalidation.constraints.FieldMatch;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Namespace;
+import org.apache.struts2.convention.annotation.ParentPackage;
+import org.apache.struts2.convention.annotation.Result;
+import org.apache.struts2.interceptor.validation.SkipValidation;
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotBlank;
+import org.hibernate.validator.constraints.ScriptAssert;
+import org.hibernate.validator.constraints.URL;
+import javax.validation.constraints.*;
+import java.util.Date;
+
+
+@Namespace("/bean-validation")
+@ParentPackage("my-bean-validation")
+@Action(results = {
+        @Result(name = "input", location = "bean-validation.jsp"),
+        @Result(name = "success", location = 
"/WEB-INF/validation/successFieldValidatorsExample.jsp")
+})
+@FieldMatch(first = "fieldExpressionValidatorField", second = 
"requiredValidatorField", message = "requiredValidatorField and 
fieldExpressionValidatorField are not matching")
+@ScriptAssert(lang = "javascript", script = "_this.dateValidatorField != null 
&amp;&amp; _this.dateValidatorField.before(new java.util.Date())", message = 
"Date need to before now")
+public class BeanValidationExampleAction extends ActionSupport {
+    @NotNull
+    private String requiredValidatorField = null;
+
+    @NotBlank
+    private String requiredStringValidatorField = null;
+
+    @NotNull(message="your.text.key.here")
+    @Min(1)
+    @Max(10)
+    private Integer integerValidatorField = null;
+
+    @NotNull
+    private Date dateValidatorField = null;
+
+    @NotNull
+    @Size(min = 4, max = 64)
+    @Email
+
+    private String emailValidatorField = null;
+
+    @NotNull
+    @Size(min = 4, max = 64)
+    @URL
+    private String urlValidatorField = null;
+
+    @NotNull
+    @Size(min = 2, max = 4)
+    private String stringLengthValidatorField = null;
+
+    @Pattern(regexp = "[^&lt;&gt;]+")
+    private String regexValidatorField = null;
+
+    private String fieldExpressionValidatorField = null;
+
+
+ public Date getDateValidatorField() {
+
+        return dateValidatorField;
+    }
+    public void setDateValidatorField(Date dateValidatorField) {
+        this.dateValidatorField = dateValidatorField;
+    }
+    public String getEmailValidatorField() {
+        return emailValidatorField;
+    }
+    public void setEmailValidatorField(String emailValidatorField) {
+        this.emailValidatorField = emailValidatorField;
+    }
+    public Integer getIntegerValidatorField() {
+        return integerValidatorField;
+    }
+    public void setIntegerValidatorField(Integer integerValidatorField) {
+        this.integerValidatorField = integerValidatorField;
+    }
+    public String getRegexValidatorField() {
+        return regexValidatorField;
+    }
+    public void setRegexValidatorField(String regexValidatorField) {
+        this.regexValidatorField = regexValidatorField;
+    }
+    public String getRequiredStringValidatorField() {
+        return requiredStringValidatorField;
+    }
+    public void setRequiredStringValidatorField(String 
requiredStringValidatorField) {
+        this.requiredStringValidatorField = requiredStringValidatorField;
+    }
+    public String getRequiredValidatorField() {
+        return requiredValidatorField;
+    }
+    public void setRequiredValidatorField(String requiredValidatorField) {
+        this.requiredValidatorField = requiredValidatorField;
+    }
+    public String getStringLengthValidatorField() {
+        return stringLengthValidatorField;
+    }
+    public void setStringLengthValidatorField(String 
stringLengthValidatorField) {
+        this.stringLengthValidatorField = stringLengthValidatorField;
+    }
+    public String getFieldExpressionValidatorField() {
+        return fieldExpressionValidatorField;
+    }
+    public void setFieldExpressionValidatorField(
+            String fieldExpressionValidatorField) {
+        this.fieldExpressionValidatorField = fieldExpressionValidatorField;
+    }
+    public String getUrlValidatorField() {
+        return urlValidatorField;
+    }
+    public void setUrlValidatorField(String urlValidatorField) {
+        this.urlValidatorField = urlValidatorField;
+    }
+}
+</code></pre>
+</div>
+
+<p>##CDI Plugin## {#PAGE_27842284}</p>
+
+<p>###Overview###</p>
+
+<p>CDI - short for Contexts and Dependency Injection - is the new standard for 
Java EE (though not limited to it) dependency injection frameworks. It was 
introduced as <a href="http://jcp\.org/en/jsr/summary?id=299";>JSR 
299</a>^[http://jcp.org/en/jsr/summary?id=299], being a part of the <a 
href="http://jcp\.org/en/jsr/detail?id=316";>Java EE 
6</a>^[http://jcp.org/en/jsr/detail?id=316] umbrella specification. It is also 
important to note that it builds on top of JSR 330 (Dependency Injection for 
Java SE), often referenced as <a 
href="http://jcp\.org/en/jsr/summary?id=330";>@Inject</a>^[http://jcp.org/en/jsr/summary?id=330].</p>
+
+<p>It can be used as standalone solution packed with your web applications to 
run in lightweight servlet containers such as Apache Tomcat or Jetty, utilizing 
standalone CDI implementations such as <a 
href="http://seamframework\.org/Weld";>JBoss 
Weld</a>^[http://seamframework.org/Weld] (the JSR 299 reference implementation) 
or <a href="http://openwebbeans\.apache\.org/";>Apache 
OpenWebBeans</a>^[http://openwebbeans.apache.org/]. On the other hand, each JEE 
6 compliant application server such as <a 
href="http://glassfish\.java\.net/";>Glassfish</a>^[http://glassfish.java.net/], 
<a href="http://www\.jboss\.org/jbossas";>JBoss 
AS</a>^[http://www.jboss.org/jbossas] or <a 
href="http://openejb\.apache\.org/apache\-tomee\.html";>Apache 
TomEE</a>^[http://openejb.apache.org/apache-tomee.html] is required to have a 
CDI container on board, making it easy for developers to pack lightweight web 
or enterprise archives while being able to use a compelling dependency 
injection feature set.</p>
+
+<p>With the Struts 2 CDI plugin, your application is open to be embedded into 
this modern, comprehensive and type safe framework and take full use of it.</p>
+
+<p>###Setup###</p>
+
+<p>As with all Struts 2 plugins, usage of the CDI plugin is as easy as 
delivering the right jars with your web application. The plugin then registers 
itself as the standard ObjectFactory for your Struts 2 application.</p>
+
+<p><strong>(i) Don’t mess up Object Factory Providers</strong></p>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+  <p>Struts 2 delivers integration into all relevant dependency injection 
containers via plugins, such as the <a href="#PAGE_14281">Spring Plugin</a> or 
the externally provided <a 
href="http://code\.google\.com/p/google\-guice/wiki/Struts2Integration";>Guice 
Struts 2 
Plugin</a>^[http://code.google.com/p/google-guice/wiki/Struts2Integration]. Be 
aware that the central feature of all those, as well as the CDI plugin, is to 
register itself as Struts 2 Object factory. Usually you will want to use 
<strong>exactly one of those plugins</strong> in your application, since there 
will only be <strong>one ObjectFactory</strong> implementation for Struts 2 to 
chose. If you pack more than one of those plugins, the factory to be chosen 
will be undetermined. One will win in the end, but who knows which ...</p>
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<p>####Maven Setup####</p>
+
+<p>The most easy and recommended way use is to simply add a maven dependency 
for it, along with a dependency to the CDI API for development time usage:</p>
+
+<p><strong>pom.xml</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+&lt;dependencies&gt;
+    ...
+    &lt;dependency&gt;
+        &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
+        &lt;artifactId&gt;struts2-cdi-plugin&lt;/artifactId&gt;
+        &lt;version&gt;${struts2.version}&lt;/version&gt;
+    &lt;/dependency&gt;
+    &lt;dependency&gt;
+        &lt;groupId&gt;javax.enterprise&lt;/groupId&gt;
+        &lt;artifactId&gt;cdi-api&lt;/artifactId&gt;
+        &lt;version&gt;1.0-SP1&lt;/version&gt;
+        &lt;scope&gt;provided&lt;/scope&gt;
+    &lt;/dependency&gt;
+    ...
+&lt;/dependencies&gt;
+
+</code></pre>
+</div>
+
+<p>whereas</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>${struts2.version}
+</code></pre>
+</div>
+
+<p>should be set either as a property in your pom (recommended) or substituted 
by a concrete version information, such as 2.3.2 by the time of writing of this 
document. If you want to use CDI without an application server providing it, 
you may also want to add a dependency to a CDI implementation of your choice, 
for example Weld:</p>
+
+<p><strong>pom.xml with CDI implementation</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+&lt;dependencies&gt;
+    ...
+    &lt;dependency&gt;
+        &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
+        &lt;artifactId&gt;struts2-cdi-plugin&lt;/artifactId&gt;
+        &lt;version&gt;${struts2.version}&lt;/version&gt;
+    &lt;/dependency&gt;
+    &lt;dependency&gt;
+        &lt;groupId&gt;javax.enterprise&lt;/groupId&gt;
+        &lt;artifactId&gt;cdi-api&lt;/artifactId&gt;
+        &lt;version&gt;1.0-SP1&lt;/version&gt;
+        &lt;scope&gt;provided&lt;/scope&gt;
+    &lt;/dependency&gt;
+    &lt;dependency&gt;
+        &lt;groupId&gt;org.jboss.weld&lt;/groupId&gt;
+        &lt;artifactId&gt;weld-core&lt;/artifactId&gt;
+        &lt;version&gt;1.0.1-Final&lt;/version&gt;
+    &lt;/dependency&gt;
+    &lt;dependency&gt;
+        &lt;groupId&gt;org.jboss.weld&lt;/groupId&gt;
+        &lt;artifactId&gt;weld-se&lt;/artifactId&gt;
+        &lt;version&gt;1.0.1-Final&lt;/version&gt;
+    &lt;/dependency&gt;
+    ...
+&lt;/dependencies&gt;
+
+</code></pre>
+</div>
+
+<p>####Manual Integration####</p>
+
+<p>Ensure that the struts2-cdi-plugin jar matching your used Struts 2 
framework version - it is part of the <a 
href="http://struts\.apache\.org/download\.cgi";>Struts 2 
distribution</a>^[http://struts.apache.org/download.cgi] - is packed within the 
application archive that will be delivered. If a CDI implementation is provided 
within your container, no other dependencies are needed. If the latter is not 
the case, you may want to install a CDI container into your container (as 
commmon installation or packed with your app) according to the installation 
instructions of the CDI provider of choice.</p>
+
+<p>For IDE integration, be sure to add both the struts2-cdi-plugin-VERSION.jar 
as well as the cdi-api.jar to your project setup. Remember, the API jar should 
not be delivered with your application archive since you will have the API 
provided by the CDI container your application will be running with.</p>
+
+<p>####Configuration####</p>
+
+<p>Not much to see here. The CDI specification requires the CDI container to 
be exposed via JNDI context, and the CDI plugin will pick it up just there. 
Nevertheless, since there are different JNDI namespaces in use, the plugin will 
try to automatically find the right one among known references, that is</p>
+
+<ul>
+  <li>
+    <p>java:comp/BeanManager as the CDI docs point out</p>
+  </li>
+  <li>
+    <p>java:app/BeanManager as the Weld docs point out</p>
+  </li>
+  <li>
+    <p>java:comp/env/BeanManager for containers limited to that namespace, 
such as tomcat</p>
+  </li>
+</ul>
+
+<p>If your container of choice uses other naming references, the plugin has a 
single configuration option to point to the right name. Just add a constant 
like this to your struts.xml to be on the happy path again:</p>
+
+<p><strong>struts.xml</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+    &lt;constant name="struts.objectFactory.cdi.jndiKey" 
value="java:comp/some/weird/BeanManagerReference" /&gt;
+
+</code></pre>
+</div>
+
+<p>###Usage###</p>
+
+<p>CDI has an extremely rich feature set, and this section is not intended as 
a replacement for the CDI reference documentation or the excellent 
documentation found on the <a href="http://seamframework\.org/Weld";>JBoss 
Weld</a>^[http://seamframework.org/Weld] homepage. The whole Struts 2 CDI 
integration works just as you would think it works, using JSR-299 and JSR-330 
Annotations in your Struts 2 actions or interceptors. Be aware of the 
following, though:</p>
+
+<table>
+  <tbody>
+    <tr>
+      <td>CDI is designed to act in a type safe and modern way, thus using 
annotations for all aspects of the framework. Nevertheless, you are allowed to 
eternalize configuration into a XML file called beans.xml to be placed in your 
WEB-INF directory. Even if you don’t intend to use such external 
configuration, it is an <strong>inevitable requirement to provide at least an 
empty beans.xml in WEB-INF !</strong></td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>####Example Usage####</p>
+
+<p>Implement your Struts 2 actions or interceptors just as usual, enriched 
with CDI and @Inject annotations:</p>
+
+<p><strong>NumberGuess.java</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+package org.apache.struts2.example.cdi;
+
+import com.opensymphony.xwork2.ActionSupport;
+import javax.inject.Inject;
+
+public class NumberGuess extends ActionSupport {
+
+    @Inject
+    Game game;
+
+    public Game getGame() {
+        return game;
+    }
+
+    @Override
+    public String execute() throws Exception {
+        return SUCCESS;
+    }
+
+    public String guess() throws Exception {
+        final String errorMessage = game.check();
+        addActionError(errorMessage);
+
+        if (Game.CORRECT.equals(errorMessage)) {
+            game.reset();
+        } else if (game.getRemainingGuesses() == 0) {
+            addActionError("The correct guess was " + game.getGuess() + ". 
Game is reset.");
+            game.reset();
+        }
+
+
+        return SUCCESS;
+    }
+
+
+}
+
+</code></pre>
+</div>
+
+<p>See the @Inject annotation from javax.inject.Inject? While you could use 
all the other nice stuff, we usually would - following the separation of 
concerns principle - use @Inject most of the time only in our actions, keeping 
the more fancy stuff in the business layer as shown below. Using @Inject brings 
us to the most common pitfall when using Struts 2 together with JSR-330 / 
CDI:</p>
+
+<p><strong>(i) Use the right @Inject</strong></p>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+  <p>Struts 2 and it’s core component XWork use it’s own internal 
dependency injection container. Interestingly, you could name it JSR-330’s 
grandma, since it is an early pre-release version of <a 
href="http://code\.google\.com/p/google\-guice/";>Google 
Guice</a>^[http://code.google.com/p/google-guice/] once developed by <a 
href="http://blog\.crazybob\.org/";>Crazybob Lee</a>^[http://blog.crazybob.org/] 
- the same Bob Lee that, together with SpringSource’s Rod Johnson, lead the 
JSR-330 specification.</p>
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+  <p>That said, you will find the @Inject annotation both as 
com.opensymphony.xwork2.inject.Inject and javax.inject.Inject. <strong>Don’t 
mix up those two - javax.inject.Inject is the one you want to use with your 
Struts 2 CDI plugin and CDI integration in general!</strong> While you could 
use Struts’ internal annotation as well, the effect may be strange to 
undefined - so check your imports!</p>
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<p>Now that you are aware of that, here is the rest of the inevitable 
NumberGuess CDI example in Struts 2 flavour. Add a JSP view similar to this:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+<span class="err">&lt;</span>%@ page contentType="text/html; charset=UTF-8" 
%&gt;
+<span class="err">&lt;</span>%@ taglib prefix="s" uri="/struts-tags" %&gt;
+<span class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;head&gt;</span>
+    <span class="nt">&lt;title&gt;</span>Numberguess<span 
class="nt">&lt;/title&gt;</span>
+<span class="nt">&lt;/head&gt;</span>
+
+<span class="nt">&lt;body&gt;</span>
+<span class="nt">&lt;h2&gt;</span>Numberguess Game - Struts 2 CDI Example<span 
class="nt">&lt;/h2&gt;</span>
+
+<span class="nt">&lt;h3&gt;</span>I've picked a number between <span 
class="nt">&lt;s:property</span> <span class="na">value=</span><span 
class="s">"game.smallest"</span><span class="nt">/&gt;</span> and <span 
class="nt">&lt;s:property</span> <span class="na">value=</span><span 
class="s">"game.biggest"</span><span class="nt">/&gt;</span>.
+    You have <span class="nt">&lt;s:property</span> <span 
class="na">value=</span><span class="s">"game.remainingGuesses"</span><span 
class="nt">/&gt;</span>remaining guesses.<span class="nt">&lt;/h3&gt;</span>
+
+<span class="nt">&lt;s:form</span> <span class="na">action=</span><span 
class="s">"guess"</span><span class="nt">&gt;</span>
+    <span class="nt">&lt;s:textfield</span> <span class="na">name=</span><span 
class="s">"game.guess"</span> <span class="na">label=</span><span 
class="s">"Your Guess"</span><span class="nt">/&gt;</span>
+    <span class="nt">&lt;s:submit/&gt;</span>
+<span class="nt">&lt;/s:form&gt;</span>
+<span class="nt">&lt;p/&gt;</span>
+<span class="nt">&lt;s:actionerror/&gt;</span>
+
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+
+</code></pre>
+</div>
+
+<p>along - if not using the fabulous and recommended Struts 2 <a 
href="#PAGE_105613">Convention Plugin</a> - with a struts.xml like this</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+<span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
+<span class="cp">&lt;!DOCTYPE struts PUBLIC
+          "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"    
   
+          "http://struts.apache.org/dtds/struts-2.3.dtd"&gt;</span>
+<span class="nt">&lt;struts&gt;</span>
+  <span class="nt">&lt;constant</span> <span class="na">name=</span><span 
class="s">"struts.enable.DynamicMethodInvocation"</span> <span 
class="na">value=</span><span class="s">"false"</span><span 
class="nt">/&gt;</span>
+  <span class="nt">&lt;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">/&gt;</span>
+  
+    <span class="nt">&lt;package</span> <span class="na">name=</span><span 
class="s">"numberguess"</span> <span class="na">extends=</span><span 
class="s">"struts-default"</span><span class="nt">&gt;</span>
+
+        <span class="nt">&lt;action</span> <span class="na">name=</span><span 
class="s">"NumberGuess"</span> <span class="na">class=</span><span 
class="s">"org.apache.struts2.example.cdi.NumberGuess"</span><span 
class="nt">&gt;</span>
+            <span 
class="nt">&lt;result&gt;</span>/WEB-INF/pages/NumberGuess.jsp<span 
class="nt">&lt;/result&gt;</span>
+        <span class="nt">&lt;/action&gt;</span>
+
+        <span class="nt">&lt;action</span> <span class="na">name=</span><span 
class="s">"guess"</span> <span class="na">class=</span><span 
class="s">"org.apache.struts2.example.cdi.NumberGuess"</span> <span 
class="na">method=</span><span class="s">"guess"</span><span 
class="nt">&gt;</span>
+            <span 
class="nt">&lt;result&gt;</span>/WEB-INF/pages/NumberGuess.jsp<span 
class="nt">&lt;/result&gt;</span>
+        <span class="nt">&lt;/action&gt;</span>
+
+    <span class="nt">&lt;/package&gt;</span>
+
+<span class="nt">&lt;/struts&gt;</span>
+
+</code></pre>
+</div>
+
+<p>Now you can add the business logic we want to be managed and injected by 
CDI. Start with two qualifier annotations:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+package org.apache.struts2.example.cdi;
+
+import javax.inject.Qualifier;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.*;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@Qualifier
+public @interface Random {}
+
+</code></pre>
+</div>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+package org.apache.struts2.example.cdi;
+
+import javax.inject.Qualifier;
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.*;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@Qualifier
+public @interface MaxNumber {}
+
+</code></pre>
+</div>
+
+<p>Now on to the actual business beans, the Game and the Generator bean:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+package org.apache.struts2.example.cdi;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@Named
+@SessionScoped
+public class Game implements Serializable {
+
+    public static final String CORRECT = "Correct !!!";
+    public static final String WRONG = "Sorry, wrong number !!!";
+
+    private int number;
+    private int guess;
+    private int smallest;
+
+    @MaxNumber
+    @Inject
+    private int maxNumber;
+
+    private int biggest;
+    private int remainingGuesses;
+
+    @Random
+    @Inject
+    Instance&lt;Integer&gt; randomNumber;
+
+    public Game() {
+    }
+
+    public int getNumber() {
+        return number;
+    }
+
+    public int getGuess() {
+        return guess;
+    }
+
+    public void setGuess( int guess ) {
+        this.guess = guess;
+    }
+
+    public int getSmallest() {
+        return smallest;
+    }
+
+    public int getBiggest() {
+        return biggest;
+    }
+
+    public int getRemainingGuesses() {
+        return remainingGuesses;
+    }
+
+    public String check() throws InterruptedException {
+        if (guess &gt; number) {
+            biggest = guess - 1;
+        }
+        if (guess &lt; number) {
+            smallest = guess + 1;
+        }
+        if (guess == number) {
+            return CORRECT;
+        }
+        remainingGuesses--;
+        return WRONG;
+    }
+
+    @PostConstruct
+    public void reset() {
+        this.smallest = 0;
+        this.guess = 0;
+        this.remainingGuesses = 10;
+        this.biggest = maxNumber;
+        this.number = randomNumber.get();
+    }
+
+}
+
+</code></pre>
+</div>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>
+package org.apache.struts2.example.cdi;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import java.io.Serializable;
+
+@ApplicationScoped
+public class Generator implements Serializable {
+   
+   private java.util.Random random = new java.util.Random( 
System.currentTimeMillis() );
+   
+   private int maxNumber = 100;
+   
+   java.util.Random getRandom() {
+      return random;
+   }
+   
+   @Produces @Random int next() { 
+      return getRandom().nextInt(maxNumber); 
+   }
+   
+   @Produces @MaxNumber int getMaxNumber() {
+      return maxNumber;
+   }
+
+} 
+
+</code></pre>
+</div>
+
+<p>If you understand that code at a glance, you are either already an CDI 
expert or profit from the readable, natural language oriented way the CDI stack 
works. If neither of this is the case, now it’s time to check the CDI and 
Weld documentation. Remember, this is a trivial example - there is much more to 
know about CDI.</p>
+
+<p>Ready you are now - use the Force!</p>
+
+<p>##Codebehind Plugin## {#PAGE_29637}</p>
+
+<p><strong>(!) Deprecated Plugin</strong></p>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+  <p>Since 2.1 this plugin has been deprecated in favor of the <a 
href="#PAGE_105613">Convention Plugin</a>. See <a href="#PAGE_106500">this 
page</a> for details on how to port your application to the Convention 
plugin.</p>
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<p>The Codebehind Plugin</p>
+
+<p>reduces mundane configuration by adding “Page Controller” 
conventions</p>
+
+<p>There are two common situations where the plugin applies convention over 
configuration:</p>
+
+<ol>
+  <li>
+    <p><strong>Default mappings</strong> - (or “pages with no mappings”) 
These are cases where the page is mostly static and doesn’t require an Action 
class to execute logic.  Common examples are index pages and those that heavily 
use JSP tags or JSF components.</p>
+  </li>
+  <li>
+    <p><strong>Default results</strong> - The purpose of most Actions is to 
execute code to prepare the data for a specific page. The name of this page is 
often the same as the Action itself.</p>
+  </li>
+</ol>
+
+<p>To improve the first case, the plugin will detect the presence of a page 
with no corresponding Struts mapping and automatically substitute a mapping 
that uses the default Action class for the package, which is usually 
ActionSupport, a NO-OP Action.</p>
+
+<p>For the problem of default results, the plugin will make it unnecessary to 
define those results by detecting the presence of a page for that Action and 
creating the appropriate configuration on-the-fly.</p>
+
+<p>In these two ways, the plugin encourages a page-based development style, 
handling the linking of Struts actions with pages and pages with Results in a 
common way.</p>
+
+<p>(ok)  To see the plugin in action, review the “Person Manager” example 
in the Showcase application.</p>
+
+<p>####Features####</p>
+
+<ul>
+  <li>
+    <p>Provides default mappings for pages that don’t have Actions</p>
+  </li>
+  <li>
+    <p>Provides default results by auto-discovering pages</p>
+  </li>
+</ul>
+
+<p>####Usage####</p>
+
+<p>To use this plugin, simply copy its jar into your application.  The plugin 
can be used to find default mappings and results.</p>
+
+<p>#####Default Mappings#####</p>
+
+<p>To better facilitate a code-behind development approach, the plugin will 
detect the case where the request has no defined Struts action mapping, yet 
there exists a corresponding page.  It will then create a dummy action mapping 
referencing the default Action class (usually ActionSupport), allowing the page 
to be displayed normally.  Additionally, the default interceptor stack for the 
configured package will be applied, bringing the workflow benefits of 
interceptor stacks to simple pages.</p>
+
+<p>When no explicitly configured Action can be found for a request, the plugin 
searches the web application for a likely page. Specifically, the following 
pattern is used to locate a page:</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/NAMESPACE/ACTION.(jsp|vm|ftl)
+</code></pre>
+</div>
+
+<p>For example, if the request is for</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>http://www.company.com/myapp/member/login.action
+</code></pre>
+</div>
+<p>, the plugin will look for the following pages, in this order:</p>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.jsp
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.vm
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.ftl
+</code></pre>
+</div>
+
+<p>If any of those pages are found, the plugin will construct an ActionConfig 
object on the fly, using the ActionSupport class for the Action and a single 
Result that points to the discovered page.  The ActionConfig will be put in the 
configured package, meaning that it will inherit the default Interceptor stack 
for that package.  The default package is</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>codebehind-default
+</code></pre>
+</div>
+<p>, however, it can be configured in any <em>configuration file</em>  via 
the</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.codebehind.defaultPackage
+</code></pre>
+</div>
+<p>constant.</p>
+
+<p>#####Default Results#####</p>
+
+<p>In many applications, a majority of Results could have the same root name 
as the action mapping.  To reduce this unnecessary configuration, the Struts 
plugin will try to guess the appropriate Result, if none is explicitly 
configured.  This technique works for any result code, including</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>success
+</code></pre>
+</div>
+<p>. When combined with the <em>Zero Configuration</em>  style, the amount of 
configuration in an application dwindles to next to nothing.</p>
+
+<p>When no explicitly configured Result is found for an Action’s result 
code, the plugin, again, searches the web application for a matching page. 
Specifically, the following patterns, in the following order, are used to 
locate a page:</p>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/NAMESPACE/ACTION-RESULT_CODE.(jsp|vm|ftl)
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/NAMESPACE/ACTION.(jsp|vm|ftl)
+</code></pre>
+</div>
+
+<p>These two patterns are searched for each of the three default page 
extensions: jsp, vm, and ftl.  For example, if the request is for</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>http://www.company.com/myapp/member/login.action
+</code></pre>
+</div>
+<p>, so that the action name is</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>login
+</code></pre>
+</div>
+<p>and the namespace is</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>member
+</code></pre>
+</div>
+<p>, and the Action class returned a code of</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>success
+</code></pre>
+</div>
+<p>, the plugin will look for the following pages, in this order:</p>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/member/login-success.jsp
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.jsp
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/member/login-success.vm
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.vm
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/member/login-success.ftl
+</code></pre>
+</div>
+
+<ol>
+  <li></li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/member/login.ftl
+</code></pre>
+</div>
+
+<p>If any of those pages are found, the appropriate Result will be constructed 
and processed.</p>
+
+<p>#####Settings#####</p>
+
+<p>The following settings can be customized.  See the <a 
href="http://cwiki\.apache\.org/confluence/display/WW/Configuration\+Files";>developer
 
guide</a>^[http://cwiki.apache.org/confluence/display/WW/Configuration+Files].</p>
+
+<table>
+  <thead>
+    <tr>
+      <th>Setting</th>
+      <th>Description</th>
+      <th>Default</th>
+      <th>Possible Values</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>struts.codebehind.defaultPackage</td>
+      <td>The default package to use for created Action mappings</td>
+      <td>codebehind-default</td>
+      <td>Any existing package name</td>
+    </tr>
+    <tr>
+      <td>struts.configuration.classpath.disableActionScanning</td>
+      <td>Whether to disable scanning the classpath for Action classes or 
not</td>
+      <td>false</td>
+      <td>true or false</td>
+    </tr>
+  </tbody>
+</table>
+
+<p>#####Installation#####</p>
+
+<p>This plugin can be installed by copying the plugin jar into your 
application’s</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/WEB-INF/lib
+</code></pre>
+</div>
+<p>directory.  No other files need to be copied or created.</p>
+
+<p>##Config Browser Plugin## {#PAGE_44185}</p>
+
+<p>The Config Browser Plugin is</p>
+
+<p>a simple tool to help view an application’s configuration at runtime</p>
+
+<p>This plugin should be used only during development phase and access to it 
should be strictly restricted!</p>
+
+<blockquote>
+
+</blockquote>
+
+<p>####Features####</p>
+
+<ul>
+  <li>
+    <p>Browsable view of loaded configuration</p>
+  </li>
+  <li>
+    <p>Shows all accessible action URLs</p>
+  </li>
+</ul>
+
+<p>####Usage####</p>
+
+<p>To use the plugin, simply copy the jar into your application.  Once 
installed, you can access the tool by opening to the action named 
<em>index</em>  in the <em>config-browser</em>  namespace.</p>
+
+<p>(information) In most cases (if you are using the default 
<em>ActionMapper</em> ), the URL is something like <a 
href="http://localhost:8080/starter/config\-browser/index\.action";>http://localhost:8080/starter/config-browser/index.action</a>
 or <a 
href="http://localhost:8080/starter/config\-browser/index";>http://localhost:8080/starter/config-browser/index</a>.</p>
+
+<p>#####Example#####</p>
+
+<p><img 
src="/Users/lukaszlenart/Projects/Apache/struts\-site/target/md/attachments/att30966155\_config\-browser\-example\.png"
 alt="config-browser-example.png" /></p>
+
+<p>#####Settings#####</p>
+
+<p>This plugin provides no customizable settings.</p>
+
+<p>#####Installation#####</p>
+
+<p>This plugin can be installed by copying the plugin jar into your 
application’s</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/WEB-INF/lib
+</code></pre>
+</div>
+<p>directory.  No other files need to be copied or created.</p>
+
+<p>##Convention Plugin## {#PAGE_105613}</p>
+
+<p>This page is DEPRECATED, please refer to the new source <a 
href="http://struts\.apache\.org/plugins/convention/";>http://struts.apache.org/plugins/convention/</a></p>
+
+<blockquote>
+
+</blockquote>
+
+<p>###Introduction###</p>
+
+<p>The Convention Plugin is bundled with Struts since 2.1 and replaces the <a 
href="#PAGE_29637">Codebehind Plugin</a> and Zero Config plugins. It provides 
the following features:</p>
+
+<ul>
+  <li>
+    <p>Action location by package naming conventions</p>
+  </li>
+  <li>
+    <p>Result (JSP, FreeMarker, etc) location by naming conventions</p>
+  </li>
+  <li>
+    <p>Class name to URL naming convention</p>
+  </li>
+  <li>
+    <p>Package name to namespace convention</p>
+  </li>
+  <li>
+    <p>SEO compliant URLs (i.e. my-action rather than MyAction)</p>
+  </li>
+  <li>
+    <p>Action name overrides using annotations</p>
+  </li>
+  <li>
+    <p>Interceptor overrides using annotations</p>
+  </li>
+  <li>
+    <p>Namespace overrides using annotations</p>
+  </li>
+  <li>
+    <p>XWork package overrides using annotations</p>
+  </li>
+  <li>
+    <p>Default action and result handling (i.e. /products will try 
com.example.actions.Products as well as com.example.actions.products.Index)</p>
+  </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>
+
+<p>###Setup###</p>
+
+<p>In order to use the Convention plugin, you first need to add the JAR file 
to the</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>WEB-INF/lib
+</code></pre>
+</div>
+<p>directory of your application or include the dependency in your project’s 
Maven POM file.</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;dependency&gt;
+    &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
+    &lt;artifactId&gt;struts2-convention-plugin&lt;/artifactId&gt;
+    &lt;version&gt;X.X.X&lt;/version&gt;
+&lt;/dependency&gt;
+
+</code></pre>
+</div>
+
+<p>Where X.X.X is the current version of Struts 2. Please remember that the 
Convention Plugin is available from version 2.1.6.</p>
+
+<p>###Converting a Codebehind based application to Convention###</p>
+
+<p>See <a href="#PAGE_106500">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 struts.xml:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;constant 
name="struts.convention.action.suffix" value="Controller"/&gt;
+&lt;constant name="struts.convention.action.mapAllMatches" value="true"/&gt;
+&lt;constant name="struts.convention.default.parent.package" 
value="rest-default"/&gt;
+
+</code></pre>
+</div>
+
+<p>###Hello world###</p>
+
+<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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.result.path
+</code></pre>
+</div>
+<p>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>
+
+<div class="highlighter-rouge"><pre class="highlight"><code><span 
class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+Hello world!
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+
+</code></pre>
+</div>
+
+<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 “</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/
+</code></pre>
+</div>
+<p>”, 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"><pre class="highlight"><code>Hello world!
+
+</code></pre>
+</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>
+
+<p>###Code behind hello world###</p>
+
+<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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>com.opensymphony.xwork2.Action
+</code></pre>
+</div>
+<p>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</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>struts
+</code></pre>
+</div>
+<p>,</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>struts2
+</code></pre>
+</div>
+<p>,</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>action
+</code></pre>
+</div>
+<p>or</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>actions
+</code></pre>
+</div>
+<p>. 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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>com.opensymphony.xwork2.Action
+</code></pre>
+</div>
+<p>or if their name ends with <strong>Action</strong> (i.e. FooAction). 
Here’s an example of a few classes that the Convention plugin will find:</p>
+
+<p><strong>Classes</strong></p>
+
+<div class="highlighter-rouge"><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>
+
+<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"><pre 
class="highlight"><code>com.example.actions.MainAction -&gt; /
+com.example.actions.products.Display -&gt; /products
+com.example.struts.company.details.ShowCompanyDetailsAction -&gt; 
/company/details
+
+</code></pre>
+</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"><pre 
class="highlight"><code>com.example.actions.MainAction -&gt; /main
+com.example.actions.products.Display -&gt; /products/display
+com.example.struts.company.details.ShowCompanyDetailsAction -&gt; 
/company/details/show-company-details
+
+</code></pre>
+</div>
+
+<p>You can tell the Convention plugin to ignore certain packages using the 
property</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.exclude.packages
+</code></pre>
+</div>
+<p>. You can also tell the plugin to use different strings to locate root 
packages using the property</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.package.locators
+</code></pre>
+</div>
+<p>. Finally, you can tell the plugin to search specific root packages using 
the property</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.action.packages
+</code></pre>
+</div>
+<p>.</p>
+
+<p>Here is our code behind action class:</p>
+
+<p><strong>com.example.actions.HelloWorld</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class HelloWorld extends ActionSupport {
+  private String message;
+
+  public String getMessage() {
+    return message;
+  }
+
+  public String execute() {
+    message = "Hello World!";
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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>
+
+<div class="highlighter-rouge"><pre class="highlight"><code><span 
class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+The message is ${message}
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+
+</code></pre>
+</div>
+
+<table>
+  <tbody>
+    <tr>
+      <td>Please notice that the expression ${message}  will work without 
adding JSP directive isELIgnored=”false”.</td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p> </p>
+
+<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"><pre class="highlight"><code>The message is 
Hello World!
+
+</code></pre>
+</div>
+
+<p>###Results and result codes###</p>
+
+<p>The Convention Plugin will pre-configure all of you 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</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>zero
+</code></pre>
+</div>
+<p>rather than</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>success
+</code></pre>
+</div>
+<p>. First, we update the action class to return different result codes:</p>
+
+<p><strong>com.example.actions.HelloWorld</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class HelloWorld extends ActionSupport {
+  private String message;
+
+  public String getMessage() {
+    return message;
+  }
+
+  public String execute() {
+    if (System.currentTimeMillis() % 2 == 0) {
+      message = "It's 0";
+      return "zero";
+    }
+
+    message = "It's 1";
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>Next, we add a new JSP to the application named</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>WEB-INF/content/hello-world-zero.jsp
+</code></pre>
+</div>
+<p>. 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>
+
+<div class="highlighter-rouge"><pre class="highlight"><code><span 
class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+The error message is ${message}
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+
+</code></pre>
+</div>
+
+<p>Now, if you compile the action and restart the application, based on the 
current time, you’ll either see the result from</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>WEB-INF/content/hello-world.jsp
+</code></pre>
+</div>
+<p>or</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>WEB-INF/content/hello-world-zero.jsp
+</code></pre>
+</div>
+<p>.</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>
+
+<p>#####Multiple names#####</p>
+
+<p>It is possible to define multiple names for the same result:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>@Action(results = {
+    @Result(name={"error", "input"}, location="input-form.jsp"),
+    @Result(name="success", location="success.jsp")
+})
+</code></pre>
+</div>
+
+<p>Such functionality was added in Struts 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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionSupport;
+
+public class HelloAction extends ActionSupport {
+    @Action("foo")
+    public String foo() {
+        return "bar";
+    }
+
+    @Action("foo-bar")
+    public String bar() {
+        return SUCCESS;
+    }
+}
+
+</code></pre>
+</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>
+
+<p>###XWork packages###</p>
+
+<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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.default.parent.package
+</code></pre>
+</div>
+<p>(defaults to</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>convention-default
+</code></pre>
+</div>
+<p>), which is a custom XWork package that extends</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>struts-default
+</code></pre>
+</div>
+<p>.</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"><pre 
class="highlight"><code>&lt;java-package&gt;#&lt;namespace&gt;#&lt;parent-package&gt;
+
+</code></pre>
+</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"><pre 
class="highlight"><code>com.example.actions#/#conventionDefault
+
+</code></pre>
+</div>
+
+<p>###Annotation reference###</p>
+
+<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>
+
+<p>####Action annotation####</p>
+
+<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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+
+public class HelloWorld extends ActionSupport {
+  @Action("/different/url")
+  public String execute() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>Our action class will now map to the URL</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/different/url
+</code></pre>
+</div>
+<p>rather than</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/hello-world
+</code></pre>
+</div>
+<p>. If no</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>@Result
+</code></pre>
+</div>
+<p>(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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/WEB-INF/content/different/url.jsp
+</code></pre>
+</div>
+<p>.</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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+
+public class HelloWorld extends ActionSupport {
+  @Actions({
+    @Action("/different/url"),
+    @Action("/another/url")
+  })
+  public String execute() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+
+public class HelloWorld extends ActionSupport {
+  @Action("/different/url")
+  public String execute() {
+    return SUCCESS;
+
+
+  }
+
+  @Action("url")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>interceptorRefs
+</code></pre>
+</div>
+<p>attribute. The following example applies the</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>validation
+</code></pre>
+</div>
+<p>interceptor and the</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>defaultStack
+</code></pre>
+</div>
+<p>interceptor stack to the action:</p>
+
+<p><strong>com.example.actions.HelloWorld</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+
+public class HelloWorld extends ActionSupport {
+  @Action(interceptorRefs={@InterceptorRef("validation"), 
@InterceptorRef("defaultStack")})
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action("url")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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 {“key0”, “value0, “key1”, “value1” ... 
“keyN”, “valueN”}. For example:</p>
+
+<p><strong>com.example.actions.HelloWorld</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+
+public class HelloWorld extends ActionSupport {
+  
@Action(interceptorRefs=@InterceptorRef(value="validation",params={"programmatic",
 "false", "declarative", "true}))
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action("url")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>If interceptors are not specified, the default stack is applied.</p>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<blockquote>
+  <p>You can specify className parameter which can be especially useful when 
Spring Framework is used to instantiate actions.</p>
+</blockquote>
+
+<blockquote>
+
+</blockquote>
+
+<p>#####Applying @Action and @Actions at the class level#####</p>
+
+<p>There are circumstances when this is desired, like when using <em>Dynamic 
Method Invocation</em> . If an</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>execute
+</code></pre>
+</div>
+<p>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>
+
+<p>####InterceptorRef annotation####</p>
+
+<p>Interceptors can be specified at the method level, using the 
<strong>Action</strong> annotation or at the class level using the</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>InterceptorRefs
+</code></pre>
+</div>
+<p>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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+
+@InterceptorRefs({
+    @InterceptorRef("interceptor-1"),
+    @InterceptorRef("defaultStack")
+})
+public class HelloWorld extends ActionSupport {
+  @Action(value="action1", interceptorRefs=@InterceptorRef("validation"))
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action(value="action2")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>The following interceptors will be applied to “action1”:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>interceptor-1
+</code></pre>
+</div>
+<p>, all interceptors from</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>defaultStack
+</code></pre>
+</div>
+<p>,</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>validation
+</code></pre>
+</div>
+<p>.
+ All interceptors from</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>defaultStack
+</code></pre>
+</div>
+<p>will be applied to “action2”.</p>
+
+<table>
+  <tbody>
+    <tr>
+      <td>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.</td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>####Result annotation####</p>
+
+<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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+import org.apache.struts2.convention.annotation.Result;
+import org.apache.struts2.convention.annotation.Results;
+
+@Results({
+  @Result(name="failure", location="fail.jsp")
+})
+public class HelloWorld extends ActionSupport {
+  @Action(value="/different/url",
+    results={@Result(name="success", location="http://struts.apache.org";, 
type="redirect")}
+  )
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action("/another/url")
+
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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 {“key0”, “value0, “key1”, “value1” ... 
“keyN”, “valueN”}. For example:</p>
+
+<p><strong>com.example.actions.HelloWorld</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Actions;
+import org.apache.struts2.convention.annotation.Result;
+import org.apache.struts2.convention.annotation.Results;
+
+public class HelloWorld extends ActionSupport {
+  @Action(value="/different/url",
+    results={@Result(name="success", type="httpheader", params={"status", 
"500", "errorMessage", "Internal Error"})}
+  )
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action("/another/url")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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>
+
+<p>####Namespace annotation####</p>
+
+<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 package-info.java 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.HelloWorl</strong></p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.Namespace;
+
+@Namespace("/custom")
+public class HelloWorld extends ActionSupport {
+  @Action("/different/url")
+  public String execute() {
+    return SUCCESS;
+  }
+
+  @Action("url")
+  public String doSomething() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>In this example, the action will respond to two different URLs</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/different/url
+</code></pre>
+</div>
+<p>and</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/custom/url
+</code></pre>
+</div>
+<p>.</p>
+
+<p>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="highlighter-rouge"><pre 
class="highlight"><code>@org.apache.struts2.convention.annotation.Namespace("/custom")
+package com.example.actions;
+
+</code></pre>
+</div>
+
+<p>This changes the default namespace for all actions defined in the 
package</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>com.example.actions
+</code></pre>
+</div>
+<p>. This annotation however doesn’t apply to sub-packages.</p>
+
+<p>####ResultPath annotation####</p>
+
+<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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.ResultPath;
+
+@ResultPath("/WEB-INF/jsps")
+public class HelloWorld extends ActionSupport {
+  public String execute() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</div>
+
+<p>The result for this class will be located in</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>WEB-INF/jsps
+</code></pre>
+</div>
+<p>rather than the default of</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>WEB-INF/content
+</code></pre>
+</div>
+<p>.</p>
+
+<p>####ParentPackage annotation####</p>
+
+<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="highlighter-rouge"><pre class="highlight"><code>package 
com.example.actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.ParentPackage;
+
+@ParentPackage("customXWorkPackage")
+public class HelloWorld extends ActionSupport {
+  public String execute() {
+    return SUCCESS;
+  }
+}
+
+</code></pre>
+</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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.default.parent.package
+</code></pre>
+</div>
+<p>in XML.</p>
+
+<p>####ExceptionMapping Annotation####</p>
+
+<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="highlighter-rouge"><pre 
class="highlight"><code>@ExceptionMappings({
+    @ExceptionMapping(exception = "java.lang.NullPointerException", result = 
"success", params = {"param1", "val1"})
+})
+public class ExceptionsActionLevelAction {
+
+    public String execute() throws Exception {
+        return null;
+    }
+}
+
+</code></pre>
+</div>
+
+<p>The parameters defined by</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>params
+</code></pre>
+</div>
+<p>are passed to the result. Exception mappings can also be applied to the 
action level:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>public class 
ExceptionsMethodLevelAction {
+    @Action(value = "exception1", exceptionMappings = {
+            @ExceptionMapping(exception = "java.lang.NullPointerException", 
result = "success", params = {"param1", "val1"})
+    })
+    public String run1() throws Exception {
+        return null;
+    }
+}
+
+</code></pre>
+</div>
+
+<p>###Actions in jar files###</p>
+
+<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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.action.includeJars
+</code></pre>
+</div>
+<p>. In this example</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>myjar1.jar
+</code></pre>
+</div>
+<p>and</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>myjar2.jar
+</code></pre>
+</div>
+<p>will be scanned:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;constant 
name="struts.convention.action.includeJars" 
value=".*?/myjar1.*?jar(!/)?,.*?/myjar2*?jar(!/)?"
+
+</code></pre>
+</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 “!/”.</p>
+
+<p>###Automatic configuration reloading###</p>
+
+<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</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>struts.xml
+</code></pre>
+</div>
+<p>file:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;constant 
name="struts.devMode" value="true"/&gt;
+&lt;constant name="struts.convention.classes.reload" value="true" /&gt;
+
+</code></pre>
+</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>
+
+<p>###JBoss###</p>
+
+<p>When using this plugin with JBoss, you need to set the following 
constants:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;constant 
name="struts.convention.exclude.parentClassLoader" value="true" /&gt;
+&lt;constant name="struts.convention.action.fileProtocols" 
value="jar,vfsfile,vfszip" /&gt;
+
+</code></pre>
+</div>
+
+<p>You can also check the <em>JBoss 5</em>  page for more details.</p>
+
+<p>###Jetty (embedded)###</p>
+
+<p>When using this plugin with Jetty in embedded mode, you need to set the 
following constants:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;constant 
name="struts.convention.exclude.parentClassLoader" value="false" /&gt;
+&lt;constant name="struts.convention.action.fileProtocols" 
value="jar,code-source" /&gt;
+
+</code></pre>
+</div>
+
+<p>###Troubleshooting###</p>
+
+<p>####Tips####</p>
+
+<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>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>Add the <a href="#PAGE_44185">Config Browser Plugin</a> 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>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<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:</p>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+      <td>log4j.logger.org.apache.struts2.convention=DEBUG</td>
+    </tr>
+  </tbody>
+</table>
+
+<table>
+  <tbody>
+    <tr>
+    </tr>
+  </tbody>
+</table>
+
+<p>####Common Errors####</p>
+
+<ol>
+  <li>I get an error like “There is no Action mapped for namespace /orders 
and action name view.”. This means that the URL</li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>/orders/view.action
+</code></pre>
+</div>
+<p>is not mapping to any action class. Check the namespace and the name of the 
action.</p>
+
+<ol>
+  <li>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</li>
+</ol>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>success
+</code></pre>
+</div>
+<p>result for it. Check that the result file exists, like</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>/WEB-INF/content/orders/view-success.jsp
+</code></pre>
+</div>
+<p>.</p>
+
+<ol>
+  <li>I get lots of errors like “java.lang.Exception: Could not load 
org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.class”. 
This happens when</li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.action.includeJars
+</code></pre>
+</div>
+<p>is matching jar URLs from external jars.</p>
+
+<ol>
+  <li>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</li>
+</ol>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.default.parent.package
+</code></pre>
+</div>
+<p>) 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</p>
+
+<div class="highlighter-rouge"><pre 
class="highlight"><code>struts.convention.default.parent.package
+</code></pre>
+</div>
+<p>) to point to it.</p>
+
+<p>###Overwriting plugin classes###</p>
+
+<p>The Convention plugin can be extended in the same fashion that Struts does. 
The following beans are defined by default:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>&lt;bean 
type="org.apache.struts2.convention.ActionConfigBuilder" name="convention" 
class="org.apache.struts2.convention.PackageBasedActionConfigBuilder"/&gt;
+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.
+
+&lt;bean type="org.apache.struts2.convention.ActionNameBu

<TRUNCATED>

Reply via email to