blob: ae176d2226e0a7a09c84d801c20950991b71bf7a [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>OSGi Plugin</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/highlighter/github-theme.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
</head>
<body>
<a href="http://github.com/apache/struts" class="github-ribbon">
<img style="position: absolute; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2021.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/osgi/index.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="../" title="back to Plugins"><< back to Plugins</a>
<h1 id="osgi-plugin">OSGi Plugin</h1>
<h2 id="overview">Overview</h2>
<p>This plugin is only experimental and can change in the future.</p>
<p>This plugin provides support for starting an instance of Apache Felix inside a web application, and scanning installed bundles for Struts configuration. An admin bundle is also provided. It can be used with Glassfish 3 as well (Glassfish 3 based on Apache Felix as well), but in such a way <code class="highlighter-rouge">struts.osgi.host</code> must be defined.</p>
<h2 id="features">Features</h2>
<ul>
<li>
<p>GUI for bundle administration</p>
</li>
<li>
<p>Web access to Felix Shell</p>
</li>
<li>
<p>Application packages can be divided into bundles</p>
</li>
<li>
<p>Supports Velocity and FreeMarker templates</p>
</li>
<li>
<p>Supports Struts Spring integration</p>
</li>
<li>
<p>Supports integration with the Convention plugin</p>
</li>
</ul>
<h2 id="missing-features">Missing Features</h2>
<ul>
<li>
<p>Probably can’t access application classes from bundles, including Spring classes</p>
</li>
<li>
<p><em>constant</em> declarations in the bundled XML config files are ignored, these constants need to be set in the application XML config files (struts.xml)</p>
</li>
</ul>
<h2 id="about-run-levels">About Run levels</h2>
<p>There are two ways of organizing bundles. If third party bundles will not be used, then the application bundles can just be placed under <code class="highlighter-rouge">/WEB-INF/classes/bundles</code>. Bundles in this dir will be started in run level 2, the Apache Felix framework’s bundles will be loaded in run level 1. If third parties bundles will be used, or you need to start bundles on different run level, create sub dirs under <code class="highlighter-rouge">/WEB-INF/classes/bundles</code> with numeric names (starting from “2” because “1” is reserved for Felix), which correspond to the run level number. For example bundles under <code class="highlighter-rouge">/WEB-INF/classes/bundles/2</code> will be started in run level 2, and bundles under <code class="highlighter-rouge">/WEB-INF/classes/bundles/3</code> will be started in run level 3.</p>
<h2 id="simple-usage">Simple Usage</h2>
<p>Add these lines to MANIFEST.MF:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Struts2-Enabled: true
Export-Package: com.mycompany.myapp.actions
Bundle-Version: 1.0.0
Bundle-SymbolicName: foo.actions
Import-Package: com.opensymphony.xwork2
</code></pre></div></div>
<p>Now the jar is ready to be deployed. Drop the jar into the <code class="highlighter-rouge">/WEB-INF/classes/bundles</code> directory and it will automatically be installed when the application starts up.</p>
<h2 id="using-spring">Using Spring</h2>
<p>By default Spring OSGi loads its xml config files asynchronously, which causes the OSGi plugin to fail while starting. To fix this add this line to MANIFEST.MF:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Spring-Context:*;create-asynchronously:=false
</code></pre></div></div>
<p>Or if using The Apache Felix maven plugin (see below for details):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Spring-Context&gt;</span>*;create-asynchronously:=false<span class="nt">&lt;/Spring-Context&gt;</span>
</code></pre></div></div>
<p>Please note that you <strong>do not</strong> need to have the Struts Spring plugin in your application, in order to use Spring with the OSGi plugin.</p>
<p>If you want to use the Spring as the object factory for your actions, then follow these steps:</p>
<ol>
<li>
<p>Place your Spring xml files under <code class="highlighter-rouge">/META-INF/spring</code> in the <strong>bundle</strong> jar file</p>
</li>
<li>
<p>Place your Spring xml files under <code class="highlighter-rouge">/spring</code> (they must be in the classpath, if you are using maven, put thme under /src/resources/spring) in the <strong>application</strong></p>
</li>
<li>
<p>Copy all the bundle jar files into <code class="highlighter-rouge">/WEB-INF/classes/bundles</code> in your <strong>application</strong></p>
</li>
<li>
<p>Make sure that the following properties are set in struts.xml or struts.properties in your <strong>application</strong>:</p>
</li>
</ol>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.objectFactory"</span> <span class="na">value=</span><span class="s">"osgi"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.objectFactory.delegate"</span> <span class="na">value=</span><span class="s">"springOsgi"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<ol start="5">
<li>Configure your <strong>web.xml</strong> like:</li>
</ol>
<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="nt">&lt;web-app</span> <span class="na">id=</span><span class="s">"WebApp_9"</span> <span class="na">version=</span><span class="s">"2.4"</span> <span class="na">xmlns=</span><span class="s">"http://java.sun.com/xml/ns/j2ee"</span>
<span class="na">xmlns:xsi=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="na">xsi:schemaLocation=</span><span class="s">"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"</span><span class="nt">&gt;</span>
<span class="nt">&lt;display-name&gt;</span>Struts Blank<span class="nt">&lt;/display-name&gt;</span>
<span class="nt">&lt;filter&gt;</span>
<span class="nt">&lt;filter-name&gt;</span>struts2-prepare<span class="nt">&lt;/filter-name&gt;</span>
<span class="nt">&lt;filter-class&gt;</span>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter<span class="nt">&lt;/filter-class&gt;</span>
<span class="nt">&lt;/filter&gt;</span>
<span class="nt">&lt;filter&gt;</span>
<span class="nt">&lt;filter-name&gt;</span>struts2-execute<span class="nt">&lt;/filter-name&gt;</span>
<span class="nt">&lt;filter-class&gt;</span>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter<span class="nt">&lt;/filter-class&gt;</span>
<span class="nt">&lt;/filter&gt;</span>
<span class="nt">&lt;filter-mapping&gt;</span>
<span class="nt">&lt;filter-name&gt;</span>struts2-prepare<span class="nt">&lt;/filter-name&gt;</span>
<span class="nt">&lt;url-pattern&gt;</span>/*<span class="nt">&lt;/url-pattern&gt;</span>
<span class="nt">&lt;/filter-mapping&gt;</span>
<span class="nt">&lt;filter-mapping&gt;</span>
<span class="nt">&lt;filter-name&gt;</span>struts2-execute<span class="nt">&lt;/filter-name&gt;</span>
<span class="nt">&lt;url-pattern&gt;</span>/*<span class="nt">&lt;/url-pattern&gt;</span>
<span class="nt">&lt;/filter-mapping&gt;</span>
<span class="nt">&lt;listener&gt;</span>
<span class="nt">&lt;listener-class&gt;</span>org.apache.struts2.osgi.StrutsOsgiListener<span class="nt">&lt;/listener-class&gt;</span>
<span class="nt">&lt;/listener&gt;</span>
<span class="nt">&lt;listener&gt;</span>
<span class="nt">&lt;listener-class&gt;</span>org.apache.struts2.dispatcher.ng.listener.StrutsListener<span class="nt">&lt;/listener-class&gt;</span>
<span class="nt">&lt;/listener&gt;</span>
<span class="nt">&lt;listener&gt;</span>
<span class="nt">&lt;listener-class&gt;</span>org.springframework.web.context.ContextLoaderListener<span class="nt">&lt;/listener-class&gt;</span>
<span class="nt">&lt;/listener&gt;</span>
<span class="nt">&lt;context-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>contextClass<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/context-param&gt;</span>
<span class="nt">&lt;context-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>contextConfigLocation<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>osgibundle:/META-INF/spring/*.xml<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/context-param&gt;</span>
<span class="nt">&lt;context-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>parentContextKey<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>parent-context-bean<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/context-param&gt;</span>
<span class="nt">&lt;/web-app&gt;</span>
</code></pre></div></div>
<ol start="6">
<li>Add the Spring OSGi, and Spring Web dependencies to your web app, if you are using maven:</li>
</ol>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependencies&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>org.springframework<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>spring-web<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>2.5.5<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>org.springframework.osgi<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>spring-osgi-web<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>1.1.2<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;/dependencies&gt;</span>
</code></pre></div></div>
<ol start="7">
<li>Download Spring OSGi and copy all the required bundles under <strong>/classes/bundles/2</strong>. For Struts OSGi 1.1.2, these are the required bundles:</li>
</ol>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
org.springframework.aop-2.5.5.A.jar
org.springframework.beans-2.5.5.A.jar
org.springframework.context-2.5.5.A.jar
org.springframework.core-2.5.5.A.jar
org.springframework.osgi.core-1.1.2.A.jar
org.springframework.osgi.extender-1.1.2.A.jar
org.springframework.osgi.io-1.1.2.A.jar
org.springframework.osgi.web-1.1.2.A.jar
org.springframework.web-2.5.5.A.jar
</code></pre></div></div>
<ol start="8">
<li>Put your bundles under <strong>/classes/bundles/3</strong></li>
</ol>
<h2 id="using-velocity">Using Velocity</h2>
<p>If you are going to use Velocity results, then add Velocity and Common Digester jars to your application. Using maven:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;depndencies&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>velocity<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>velocity<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>1.5<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>velocity-tools<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>velocity-tools<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>1.3<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>commons-digester<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>commons-digester<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>1.8<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;/depndencies&gt;</span>
</code></pre></div></div>
<h2 id="using-the-convention-plugin">Using The Convention Plugin</h2>
<p>The Convention plugin will discover actions in bundles in the same way that it discovers them in normal applications. The Convention plugin expects result templates to be (by default) stored under <em>/WEB-INF/content</em> . When packaging actions inside bundles, there won’t be a <em>WEB-INF</em> folder, so you must let Convention know where the templates are located. There are two ways of doing so(assuming the templates are under <em>/content</em> ):</p>
<ol>
<li>Set the templates location constant in struts.xml (in the application struts.xml, not a bundled struts.xml)</li>
</ol>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.convention.result.path"</span> <span class="na">value=</span><span class="s">"/content/"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<ol start="2">
<li>Using the ResultPath annotation</li>
</ol>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@ResultPath</span><span class="o">(</span><span class="s">"/content"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorldAction</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span>
<span class="c1">//...</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="the-osgi-interceptor">The OSGi interceptor</h2>
<p>The OSGi plugins defines the <code class="highlighter-rouge">osgi</code> interceptor and <code class="highlighter-rouge">osgiStack</code>(<code class="highlighter-rouge">defaultStack</code> plus the <code class="highlighter-rouge">osgi</code> interceptor) in the package <code class="highlighter-rouge">osgi-default</code>. This interceptor will check the action and if it implements <code class="highlighter-rouge">org.apache.struts2.osgi.interceptor.BundleContextAware</code>, it will invoke setBundleContext(BundleContext bundleContext) on the action, passing the BundleContext of the OSGi container. The interceptor also checks if the class implements <code class="highlighter-rouge">org.apache.struts2.osgi.interceptor.ServiceAware&lt;T&gt;</code>, if it does, setServices(List&lt;T&gt; services) will be called, where T is the type of a service published in the OSGi container. For example, lets assume an installed bundle publishes a service with the interface <code class="highlighter-rouge">BookPriceLookup</code>, to get all the instances of this service, an action would look like:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BookPriceAction</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="kd">implements</span> <span class="n">ServiceAware</span><span class="o">&lt;</span><span class="n">BookPriceLookup</span><span class="o">&gt;</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">BookPriceLookup</span><span class="o">&gt;</span> <span class="n">services</span><span class="o">;</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setServices</span><span class="o">(</span><span class="n">List</span><span class="o">&lt;</span><span class="n">BookPriceLookup</span><span class="o">&gt;</span> <span class="n">services</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">services</span> <span class="o">=</span> <span class="n">services</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Keep in mind that the interceptor is not defined in the default struts package, so when using Convention, you need to specify the parent package as “osgi-default”, either using annotations (@ParentPackage), or XML(<strong>this XML fragment must be in the struts XML config file in the application, not the bundle’s</strong>, this is a current limitation of the OSGi plugin):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.convention.default.parent.package"</span> <span class="na">value=</span><span class="s">"osgi-default"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<h2 id="admin-bundle">Admin bundle</h2>
<p>An admin bundle is distributed with struts, which provides a simple interface to list the installed bundles. Using this interface the bundles can be stopped, started and updated (reloaded from the file system). This interface also provides information on the installed bundles, like OSGi metadata, and a list of packages and actions loaded from each bundle. An interactive AJAX shell is also available, which is just a web interface to the Apache Felix Shell. To use this bundle, just copy the jar file to /bundles (same place where the application bundles are installed) and open http://localhost:PORT/CONTEXT/osgi/admin/ (replace <em>PORT</em> and <em>context</em> )</p>
<h2 id="about-stoppingstarting-bundles">About stopping/starting bundles</h2>
<p>When a bundle is started, the OSGi plugin will check for the header <code class="highlighter-rouge">Struts2-Enabled</code> in it. If it is set to “true”, the bundle will be scanned for XML config and Convention config. When a bundle is stopped, any actions that were loaded from it will be removed from the runtime configuration.</p>
<h2 id="settings">Settings</h2>
<p>The following settings can be customized. See the <a href="/core-developers/configuration-files.html">developer guide</a>.</p>
<table>
<thead>
<tr>
<th>Setting</th>
<th>Description</th>
<th>Default</th>
<th>Possible Values</th>
</tr>
</thead>
<tbody>
<tr>
<td>struts.objectFactory.delegate</td>
<td>The alias of the ObjectFactory to wrap</td>
<td>struts</td>
<td>Any configured alias</td>
</tr>
</tbody>
</table>
<p>The following setting must be set as context parameters in <em>web.xml</em> , because they are used by the StrutsOsgiListener, for example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;context-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>struts.osgi.clearBundleCache<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>false<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/context-param&gt;</span>
</code></pre></div></div>
<p>If you are running your application on Glassfish 3 (which already contains Apache Felix) you must specify <code class="highlighter-rouge">struts.osgi.host</code>, like below:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;context-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>struts.osgi.host<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>Glassfish<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/context-param&gt;</span>
</code></pre></div></div>
<table>
<thead>
<tr>
<th>Setting</th>
<th>Description</th>
<th>Default</th>
<th>Possible Values</th>
</tr>
</thead>
<tbody>
<tr>
<td>struts.osgi.clearBundleCache</td>
<td>Delete all installed bundles when the container starts</td>
<td>true</td>
<td>true or false</td>
</tr>
<tr>
<td>struts.osgi.runLevel</td>
<td>Run level to start the container</td>
<td>3</td>
<td>&gt;=3</td>
</tr>
<tr>
<td>struts.osgi.logLevel</td>
<td>Log level for Apache Felix</td>
<td>1 (Error)</td>
<td>1 = error, 2 = warning, 3 = information, and 4 = debug</td>
</tr>
</tbody>
</table>
<h2 id="building-bundles-with-maven">Building bundles with Maven</h2>
<p>Jar files can be turned into bundles using the <a href="http://cwiki.apache.org/FELIX/bundle-plugin-for-maven-bnd.html">Maven Bundle Plugin</a> like:</p>
<p><strong>Maven Bundle Plugin Example</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;build&gt;</span>
<span class="nt">&lt;plugins&gt;</span>
<span class="nt">&lt;plugin&gt;</span>
<span class="nt">&lt;groupId&gt;</span>org.apache.felix<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>maven-bundle-plugin<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;extensions&gt;</span>true<span class="nt">&lt;/extensions&gt;</span>
<span class="nt">&lt;version&gt;</span>2.0.0<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;configuration&gt;</span>
<span class="nt">&lt;instructions&gt;</span>
<span class="nt">&lt;manifestLocation&gt;</span>META-INF<span class="nt">&lt;/manifestLocation&gt;</span>
<span class="nt">&lt;Struts2-Enabled&gt;</span>true<span class="nt">&lt;/Struts2-Enabled&gt;</span>
<span class="nt">&lt;Export-Package&gt;</span>org.apache.struts2.osgi.demo<span class="nt">&lt;/Export-Package&gt;</span>
<span class="nt">&lt;Import-Package&gt;</span>*,com.opensymphony.xwork2<span class="nt">&lt;/Import-Package&gt;</span>
<span class="nt">&lt;Spring-Context&gt;</span>*;create-asynchronously:=false<span class="nt">&lt;/Spring-Context&gt;</span>
<span class="nt">&lt;/instructions&gt;</span>
<span class="nt">&lt;/configuration&gt;</span>
<span class="nt">&lt;/plugin&gt;</span>
<span class="nt">&lt;/plugins&gt;</span>
<span class="nt">&lt;/build&gt;</span>
</code></pre></div></div>
<h2 id="struts-osgi--spring-osgi-diagram">Struts OSGi + Spring OSGi diagram</h2>
<p><img src="../attachments/att10437_struts-osgi.jpg" alt="struts-osgi.jpg" /></p>
<h2 id="resources">Resources</h2>
<ul>
<li>
<p><a href="http://www.osgi.org">OSGi</a></p>
</li>
<li>
<p><a href="http://felix.apache.org">Apache Felix</a></p>
</li>
<li>
<p><a href="http://www.springsource.org/osgi">Spring OSGi </a></p>
</li>
</ul>
</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>