blob: 24939dfa93e2ed866ad6b601454a6e6e94ee1d55 [file] [log] [blame]
<!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</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/extending-an-application-with-custom-plugins.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index.html" title="back to Plugins"><< back to Plugins</a>
<h1 class="no_toc" id="extending-an-application-with-custom-plugins">Extending an Application with Custom Plugins</h1>
<ul id="markdown-toc">
<li><a href="#the-interface" id="markdown-toc-the-interface">The Interface</a></li>
<li><a href="#the-plugin" id="markdown-toc-the-plugin">The Plugin</a></li>
<li><a href="#the-action" id="markdown-toc-the-action">The Action</a></li>
<li><a href="#the-jsp" id="markdown-toc-the-jsp">The JSP</a></li>
</ul>
<p>In this tutorial, we will show how easily our application can be made extensible using the Struts 2 plugin mechanism.
To keep the demonstration simple, our plugin will expose a JavaBean that writes a message. Plugins may include any
combination of JavaBeans, Actions, Interceptors, Results or other resources we’d like available to an application.</p>
<h2 id="the-interface">The Interface</h2>
<p>At runtime, plugins are retrieved and referenced via an Interface. So, first, we should define an interface that our
plugin will implement. This interface must be available to both our web application and the plugin. To reduce coupling
between the web application and the plugins, keep the interface in a separate JAR.</p>
<p><strong>IMyPlugin.java</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">example</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">IMyPlugIn</span> <span class="o">{</span>
<span class="n">String</span> <span class="nf">saySomething</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="the-plugin">The Plugin</h2>
<p>Now that we have an interface to implement we’ll create the plugin. At load time, the framework looks for JARs
containing a <code class="highlighter-rouge">struts-plugin.xml</code> file at the root of the archive. To create a plugin, all we need to do is build
a JAR and put the expected <code class="highlighter-rouge">struts-plugin.xml</code> at the root.</p>
<p>To get started, let’s create a class that implements our IMyPlugin interface.</p>
<p><strong>MyPlugin.java</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">example</span><span class="o">.</span><span class="na">impl</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">example.IMyPlugin</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyPlugin</span> <span class="kd">implements</span> <span class="n">IMyPlugin</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">saySomething</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">"We don't need no education"</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Internally, the framework utilizes a number of JavaBeans. We can use the <code class="highlighter-rouge">bean</code> element to add our own JavaBeans
to the set managed by the framework.</p>
<p><strong>struts-default.xml</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><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.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"&gt;</span>
<span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;bean</span> <span class="na">type=</span><span class="s">"example.IMyInterface"</span> <span class="na">class=</span><span class="s">"example.impl.MyPlugin"</span> <span class="na">name=</span><span class="s">"myPlugin"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<p>Finally, to install the plugin, drop the JAR file under WEB-INF/lib.</p>
<h2 id="the-action">The Action</h2>
<p>The JavaBeans configured by <code class="highlighter-rouge">bean</code> elements can be retrieved via a Container provided by XWork 2. We obtain
a reference to the Container by using the <code class="highlighter-rouge">@Inject</code> notation. (This notation is part of the Guice framework that
XWork and Struts use under the covers.) The framework predefines a Container object, and the <code class="highlighter-rouge">@Inject</code> annotation tells
the framework to set its Container object to the Action property.</p>
<p>We might want to supply a number of JavaBeans to the application this way. In the Action, we will obtain a reference
to the entire set of JavaBeans that might have been plugged in. Then, we can scroll through the set, displaying each
JavaBean’s message.</p>
<p><strong>MyAction.java</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="n">example</span><span class="o">.</span><span class="na">actions</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">example.IMyPlugin</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyAction</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span>
<span class="n">Set</span><span class="o">&lt;</span><span class="n">IMyPlugin</span><span class="o">&gt;</span> <span class="n">plugins</span><span class="o">;</span>
<span class="nd">@Inject</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setContainer</span><span class="o">(</span><span class="n">Container</span> <span class="n">container</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Set</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">names</span> <span class="o">=</span> <span class="n">container</span><span class="o">.</span><span class="na">getInstanceNames</span><span class="o">(</span><span class="n">IMyPlugin</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="n">plugins</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashSet</span><span class="o">&lt;</span><span class="n">IMyPlugin</span><span class="o">&gt;();</span>
<span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">name</span> <span class="o">:</span> <span class="n">names</span><span class="o">)</span> <span class="o">{</span>
<span class="n">plugins</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">container</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="n">IMyPlugin</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">name</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">Set</span><span class="o">&lt;</span><span class="n">IMyPlugin</span><span class="o">&gt;</span> <span class="nf">getPlugins</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">plugins</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>As seen by the Action class code, it’s important to define a unique interface for any beans that we plugin, so that
we can identify our beans later.</p>
<p>In the same way that we plugged in this JavaBean, we could also plugin and configure Action classes, Interceptors,
Results, or any other JAR-able resource that an application might utilize.</p>
<h2 id="the-jsp">The JSP</h2>
<p>Let’s do something with those plugins:</p>
<p><strong>Page.jsp</strong></p>
<pre><code class="language-jsp">&lt;s:iterator id="plugin" value="plugins"&gt;
&lt;s:property value="#plugin.saySomething()"/&gt;
&lt;/s:iterator&gt;
</code></pre>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 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>