blob: 1c7e681a4bb38ff65c5491618a5e6835fd546344 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.4&nbsp;Form Tags Shared Services WAR</title><link rel="stylesheet" href="css/stylesheet.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"><link rel="home" href="index.html" title="Virgo Programmer Guide"><link rel="up" href="ch06.html" title="6.&nbsp;Case Study: Migrating the Form Tags Sample Application"><link rel="prev" href="ch06s03.html" title="6.3&nbsp;Form Tags Shared Libraries WAR"><link rel="next" href="ch06s05.html" title="6.5&nbsp;Form Tags PAR"><!--Begin Google Analytics code--><script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
var pageTracker = _gat._getTracker("UA-2728886-3");
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
</script><!--End Google Analytics code--></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.4&nbsp;Form Tags Shared Services WAR</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch06s03.html">Prev</a>&nbsp;</td><th width="60%" align="center">6.&nbsp;Case Study: Migrating the Form Tags Sample Application</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ch06s05.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="formtags-case-study-war-shared-services"></a>6.4&nbsp;Form Tags Shared Services WAR</h2></div></div></div><p>
The next step in the migration is to deploy the services as a separate
OSGi bundle which the WAR then references.
The Form Tags sample has a single service <code class="literal">UserManager</code>.
</p><p>
This scenario has two separate deployables, the <code class="literal">service</code> bundle and the WAR file.
The following image shows the two separate source trees:
</p><p>
<img src="images/formtags-case-study-shared-services-eclipse.png">
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">Note that the WAR does not contain the <code class="literal">.domain</code> or
<code class="literal">.service</code> packages as these will be imported from the separate service bundle.
</td></tr></table></div><p>
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="formtags-case-study-war-shared-services-service"></a>The Service Bundle</h3></div></div></div><p>
The responsibility of the first bundle (<code class="literal">formtags-shared-services-service</code>)
is to provide the API of the formtags service. This includes both the
domain and the service API. In the same way that imports are defined
in the <code class="literal">/META-INF/MANIFEST.MF</code>, so are exports.
The following is the <code class="literal">/META-INF/MANIFEST.MF</code> listing from the service bundle.
</p><pre class="programlisting">
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.5.0_13-119 (Apple Inc.)
Bundle-ManifestVersion: 2
Bundle-Name: FormTags Service (and implementation)
Bundle-SymbolicName: org.springframework.showcase.formtags.service-shared-services
<span class="bold"><strong>Export-Package</strong></span>: org.springframework.showcase.formtags.service,org.spri
ngframework.showcase.formtags.domain
Import-Library: org.springframework.spring;version="[3.0.0,4.0.0)"
</pre><p>
</p><p>
The symbolic name of this bundle is
<code class="literal">org.springframework.showcase.formtags.service-shared-services</code>.
Note that the name of the bundle typically describes the package
that the bundle primarily exports.
If you take a look at the <code class="literal">repository/bundles/ext</code> in the VTS
directory, you&#8217;ll see that names are almost always indicative of the contents of the bundle.
For this example, however, we have also appended
"<code class="literal">-shared-services</code>"
in order to avoid possible clashes with other bundle symbolic names.
You will see later that the PAR also contains a service bundle.
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
In OSGi, the combination of <code class="literal">Bundle-SymbolicName</code>
and <code class="literal">Bundle-Version</code> is used to uniquely identify
a bundle within the OSGi container. Furthermore, when you deploy
a bundle to the Virgo Tomcat Server, for example via the <code class="literal">pickup</code>
directory, a bundle&#8217;s filename is also used to uniquely identify it for
the purpose of supporting <span class="emphasis"><em>hot deployment</em></span> via
the file system.
</td></tr></table></div><p>
</p><p>
As well as exporting types (i.e. the domain classes and service
API), the service bundle also publishes an implementation of the
<code class="literal">UserManager</code>. The actual implementation is
<code class="literal">StubUserManager</code>; however, that should remain an
implementation detail of this bundle.
</p><p>
The fact that this bundle publishes a service is not captured in
the <code class="literal">/META-INF/MANIFEST.MF</code>, as it is a Spring-DM concept.
The following image is of <code class="literal">src/main/resources/spring</code>.
</p><p><img src="images/formtags-case-study-shared-services-service-resources.png"></p><p>
As you can see there are two Spring configuration files: <code class="literal">module-context.xml</code> and
<code class="literal">osgi-context.xml</code>.
</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.gif"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top">
These names are abitrary; however, they follow an informal convention:
<code class="literal">module-context.xml</code> typically bootstraps the Spring context
(usually delegating to smaller fine grained context files inside another directory), whilst
<code class="literal">osgi-context.xml</code> contains all the OSGi service exports and references.
</td></tr></table></div><p>
The following is a listing of <code class="literal">module-context.xml</code>.
</p><pre class="programlisting">
&lt;<span class="hl-tag">?xml version="1.0" encoding="UTF-8"?</span>&gt;
&lt;<span class="hl-tag">beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"</span>&gt;
&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userManager"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.showcase.formtags.service.internal.StubUserManager"</span>/&gt;
&lt;<span class="hl-tag">/beans</span>&gt;
</pre><p>
As you can see, this simply defines a bean called <code class="literal">userManager</code>.
The following is a listing of <code class="literal">osgi-context.xml</code>.
</p><pre class="programlisting">
&lt;<span class="hl-tag">?xml version="1.0" encoding="UTF-8"?</span>&gt;
&lt;<span class="hl-tag">beans:beans</span>
<span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/osgi"</span>
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute">xmlns:beans</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"</span>&gt;
&lt;<span class="hl-tag">service</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"userManager"</span>
<span class="hl-attribute">interface</span>=<span class="hl-value">"org.springframework.showcase.formtags.service.UserManager"</span>/&gt;
&lt;<span class="hl-tag">/beans:beans</span>&gt;
</pre><p>
This single bean definition exports the <code class="literal">userManager</code>
defined in <code class="literal">module-context.xml</code> to the
OSGi service registry and makes it available under the public
<code class="literal">org.springframework.showcase.formtags.service.UserManager</code> API.
</p><p>
The service bundle should now be ready to deploy on the VTS.
So copy <code class="literal">/dist/formtags-shared-services-services*</code>
to the <code class="literal">SERVER_HOME/pickup</code> directory.
Output similar to the following should appear in the VTS&#8217;s console:
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The console output has been reformatted to fit this document.</p></td></tr></table></div><pre class="programlisting">
[2009-07-01 15:05:03.511] fs-watcher
&lt;SPDE0048I&gt; Processing 'CREATED' event for file 'formtags-shared-services-service-2.0.0.RELEASE.jar'.
[2009-07-01 15:05:03.688] fs-watcher
&lt;SPDE0010I&gt; Deployment of 'org.springframework.showcase.formtags.service_shared_services' version '2.0.0.RELEASE' completed.
</pre></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="formtags-case-study-war-shared-services-war"></a>Accessing the Service and Types from the WAR</h3></div></div></div><p>
The WAR file now needs to access the types and service exported
by the service bundle. The following listing is the WAR&#8217;s
<code class="literal">/META-INF/MANIFEST.MF</code> which imports the types
exported by the service bundle. The <code class="literal">Import-Bundle</code>
statement has also been extended to import <code class="literal">org.springframework.osgi.core</code>,
which is necessary in order to load an OSGi-enabled <code class="literal">WebApplicationContext</code>.
</p><pre class="programlisting">
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.5.0_13-119 (Apple Inc.)
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.springframework.showcase.formtags.web-shared-
services
<span class="bold"><strong>Import-Package</strong></span>: org.springframework.showcase.formtags.domain,org.sprin
gframework.showcase.formtags.service, org.eclipse.virgo.web.dm;version="[1.0,2.1)"
Import-Library: org.springframework.spring;version="[2.5.4,3.1.0)"
Import-Bundle: com.springsource.org.apache.taglibs.standard;version="1
.1.2",<span class="bold"><strong>org.springframework.osgi.core</strong></span>
</pre><p>
</p><p>
In addition to importing the exported types of the service bundle,
the WAR must also obtain a reference to the <code class="literal">UserManager</code>
published by the service bundle. The following image shows the directory
structure of the Shared Services WAR.
</p><p><img src="images/formtags-case-study-shared-services-war-resources.png"></p><p>
As you can see in the above image, the Form Tags Shared Services WAR&#8217;s
<code class="literal">/WEB-INF/web.xml</code> directory contains a standard <code class="literal">web.xml</code>
deployment descriptor, <code class="literal">applicationContext.xml</code> which defines the configuration
for the <span class="emphasis"><em>root</em></span> <code class="literal">WebApplicationContext</code>, and
<code class="literal">formtags-servlet.xml</code> which defines the configuration specific to the
configured <span class="emphasis"><em>formtags</em></span> <code class="literal">DispatcherServlet</code>.
</p><p>
As is typical for Spring MVC based web applications, you configure a <code class="literal">ContextLoaderListener</code>
in <code class="literal">web.xml</code> to load your root <code class="literal">WebApplicationContext</code>; however, to enable your
<code class="literal">WebApplicationContext</code> to be able to reference services from the OSGi Service Registry,
you must explicitly set the <code class="literal">contextClass</code> Servlet context parameter to the fully qualified
class name of a <code class="literal">ConfigurableWebApplicationContext</code> which is OSGi-enabled. When deploying
Shared Services WARs to the Virgo Tomcat Server, you should use
<code class="literal">org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</code>. This will
then enable the use of Spring-DM&#8217;s <code class="literal">&lt;reference ... /&gt;</code> within your root
<code class="literal">WebApplicationContext</code> (i.e., in <code class="literal">applicationContext.xml</code>).
The following listing is an excerpt from <code class="literal">/WEB-INF/web.xml</code>.
</p><pre class="programlisting">
&lt;<span class="hl-tag">context-param</span>&gt;
&lt;<span class="hl-tag">param-name</span>&gt;contextClass&lt;<span class="hl-tag">/param-name</span>&gt;
&lt;<span class="hl-tag">param-value</span>&gt;org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext&lt;<span class="hl-tag">/param-value</span>&gt;
&lt;<span class="hl-tag">/context-param</span>&gt;
&lt;<span class="hl-tag">listener</span>&gt;
&lt;<span class="hl-tag">listener-class</span>&gt;org.springframework.web.context.ContextLoaderListener&lt;<span class="hl-tag">/listener-class</span>&gt;
&lt;<span class="hl-tag">/listener</span>&gt;
</pre><p>
The Form Tags Shared Services WAR contains a <code class="literal">/WEB-INF/applicationContext.xml</code>
file which is the default configuration location used to create the <span class="emphasis"><em>root</em></span>
<code class="literal">WebApplicationContext</code> for Spring MVC&#8217;s <code class="literal">ContextLoaderListener</code>.
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
As already mentioned, in the OSGi world, bundle configuration
takes place in the root <code class="literal">/META-INF/</code> directory.
Typically Spring-DM powered configuration files will live
there as well (e.g., in <code class="literal">/META-INF/spring/*.xml</code>).
In a WAR, however, the root <code class="literal">WebApplicationContext</code>
loaded by <code class="literal">ContextLoaderListener</code> and the <code class="literal">DispatcherServlet&#8217;s</code>
application context typically live in <code class="literal">/WEB-INF/</code>.
</td></tr></table></div><p>
The following is the listing of the WAR&#8217;s <code class="literal">/WEB-INF/applicationContext.xml</code>.
</p><pre class="programlisting">
&lt;<span class="hl-tag">?xml version="1.0" encoding="UTF-8"?</span>&gt;
&lt;<span class="hl-tag">beans:beans</span>
<span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/osgi"</span>
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute">xmlns:beans</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"</span>&gt;
&lt;<span class="hl-tag">reference</span> <span class="hl-attribute">id</span>=<span class="hl-value">"userManager"</span>
<span class="hl-attribute">interface</span>=<span class="hl-value">"org.springframework.showcase.formtags.service.UserManager"</span>/&gt;
&lt;<span class="hl-tag">/beans:beans</span>&gt;
</pre><p>
The single bean declaration is retrieving a service that implements
the <code class="literal">org.springframework.showcase.formtags.service.UserManager</code>
API from the OSGi Service Registry.
</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.gif"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top">
You might have been expecting a reference to the service bundle,
but that isn&#8217;t how OSGi works. OSGi provides a service
registry, and this bean definition is accessing a service in that
registry that meets the specified restriction (i.e. implements
the specified interface). This leads to a very loosely coupled
programming model: the WAR really doesn&#8217;t care where the implementation
comes from.
</td></tr></table></div><p>
</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.gif"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top">
What happens if there is no service at runtime?
What if there are multiple services that match the criteria?
Spring-DM provides a lot of configuration options, including
whether or not the reference is <span class="emphasis"><em>mandatory</em></span>,
how long to wait for a service reference, etc. Please consult the
<a class="ulink" href="http://www.springframework.org/osgi/" target="_top">Spring Dynamic Modules for OSGi</a>
home page for further information.
</td></tr></table></div><p>
</p><p>
One of the benefits of programming to interfaces is that you are
decoupled from the actual implementation; Spring-DM provides a proxy. This
has enormous benefits including the ability to dynamically refresh individual bundles without
cascading that refresh to unrelated bundles.
</p><p>
</p><p>
To deploy the WAR, copy <code class="literal">/dist/formtags-shared-services-war*</code>
to the <code class="literal">SERVER_HOME/pickup</code> directory.
You should then see console output similar to the following:
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.gif"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The console output has been reformatted to fit this document.</p></td></tr></table></div><pre class="programlisting">
[2009-07-01 15:09:19.819] fs-watcher
&lt;SPDE0048I&gt; Processing 'CREATED' event for file 'formtags-shared-services-war-3.0.0.RELEASE.war'.
[2009-07-01 15:09:20.167] fs-watcher
&lt;SPDE0010I&gt; Deployment of 'org.springframework.showcase.formtags.web_shared_services' version '3' completed.
[2009-07-01 15:09:20.168] Thread-20
&lt;SPWE0000I&gt; Starting web bundle '/formtags-shared-services-war-3.0.0.RELEASE'.
[2009-07-01 15:09:20.647] Thread-20
&lt;SPWE0001I&gt; Started web bundle '/formtags-shared-services-war-3.0.0.RELEASE'.
</pre>
Navigating to the appropriate link should render the welcome page.
</div></div><!--Begin LoopFuse code--><script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript"></script><script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script><!--End LoopFuse code--><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch06s03.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ch06.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ch06s05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.3&nbsp;Form Tags Shared Libraries WAR&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;6.5&nbsp;Form Tags PAR</td></tr></table></div></body></html>