blob: d3c02be9fba27349218ec234664384988ebc3524 [file] [log] [blame]
:virgo-name: Virgo
:version: 3.7.0.RC01
:umbrella-virgo-name: Eclipse Virgo
:tomcat-product-name: Virgo for Apache Tomcat
:tomcat-product-name-short: VTS
:jetty-product-name: Virgo Jetty Server
:jetty-product-name-short: VJS
:kernel-product-name: Virgo Kernel
:kernel-product-name-short: VK
:nano-product-name: Virgo Nano
:nano-product-name-short: VN
:user-guide: link:../../virgo-user-guide/html/index.html[User Guide]
:tooling-guide: link:../../virgo-tooling-guide/html/index.html[Tooling Guide]
:gemini-blueprint-guide:[Eclipse Gemini Blueprint Reference Guide]
:spring-framework-version: 4.2.9.RELEASE
:imagesdir: assets/images
anchor:formtags-case-study[Case Study: Migrating the Form Tags Sample Application]
== Case Study: Migrating the Form Tags Sample Application
Migrating Form Tags
In this chapter we will walk through the steps needed to migrate the
Form Tags sample application from a standard Java EE WAR to a fully
OSGi compliant *Shared Services WAR* within a PAR.
The migration involves four packaging and deployment formats:
. xref:formtags-case-study-war[Standard WAR]
. xref:formtags-case-study-war-shared-libs[Shared Libraries WAR]
. xref:formtags-case-study-war-shared-services[Shared Services WAR]
. xref:formtags-case-study-par[PAR with a shared services WAR]
Each of these migration steps will produce a web application
that can be deployed and run on the {tomcat-product-name-short}.
After summarising the process, an example `plan`
is shown which is another way of packaging and deploying the application.
The following image displays the directory structure you should have
after installing the Form Tags sample. Note however that the release
tag will typically resemble `3.0.0.RELEASE`.
The `dist` directory contains the distributables,
and the `projects` directory contains the source code and build scripts.
For simplicity, this chapter will focus on the distributables—which
are built using Virgo-Build rather than on configuring a project in an IDE.
Pre-packaged distributables are made available in the `dist` directory;
however, if you would like to modify the samples or build
them from scratch, you may do so using Virgo-Build. Take a look at
the `README.TXT` file in each of the folders under the `projects`
directory in the Form Tags sample for instructions.
=== Overview of the Form Tags Sample Application
The sample that we will be using is the Form Tags show case
which was provided with Spring 2.0. The Form Tags application
been removed from the official Spring 2.5.x distributions;
since it is relatively simple but still contains enough
to demonstrate the various considerations required during
a migration,
we have chosen to use it for these examples.
The purpose of the Form Tags show case sample was to demonstrate how
the Spring specific
tags, released
in Spring 2.0, make view development with JSPs and tag
libraries easier.
The Form Tags application consists of a single
which returns a list
. Furthermore, the application demonstrates how to list, view,
in a simple Spring MVC based web application using JSP
and JSTL.
=== Form Tags WAR
We begin with a standard WAR deployment.
The {tomcat-product-name-short} supports the standard Java EE WAR
and deployment format as a first-class citizen, and there
are many
benefits to deploying a standard WAR file on the
{tomcat-product-name-short} including,
but not limited to: tooling
support, runtime error diagnostics, FFDC
(first failure data
capture), etc.
In addition, support for standard WAR deployment
provides an easy on-ramp
for trying out the
{tomcat-product-name-short} with existing web applications.
The following screen shot displays the directory structure of the
Form Tags application using the standard WAR format. As you can see,
there is no deviation from the standard structure and layout, and as
you would expect, all of the web application's third-party
(for example: Spring, Commons Logging) are packaged as
JARs in
To deploy this application, simply copy
directory for hot deployment.
You should then see the {tomcat-product-name-short} produce
console output similar to the following:
The console output has been reformatted to fit this document.
[2009-07-01 14:54:45.135] fs-watcher
<SPDE0048I> Processing 'CREATED' event for file 'formtags-war-3.0.0.RELEASE.war'.
[2009-07-01 14:54:45.797] fs-watcher
<SPDE0010I> Deployment of 'formtags-war-3.0.0.RELEASE.war' version '0' completed.
[2009-07-01 14:54:45.797] Thread-20
<SPWE0000I> Starting web bundle '/formtags-war-3.0.0.RELEASE'.
[2009-07-01 14:54:46.380] Thread-20
<SPWE0001I> Started web bundle '/formtags-war-3.0.0.RELEASE'.
Navigate to
plus the web application context path,
which in the above case is
. Thus navigating to
should render the sample application's welcome page, as
displayed in the screen
shot below.
For WARs, the default web context path is the name of the WAR file
without the
extension. You can optionally
specify a context path using the
manifest header, which will be described in further detail
=== Form Tags Shared Libraries WAR
As mentioned above, a standard WAR file typically packages of all its
dependencies in
. The servlet container will
then add all of the JARs in
to the application's
The first step of the migration towards benefiting from an OSGi
container is to retrieve the dependencies from the
{tomcat-product-name-short}'s bundle
repository at runtime. This
can significantly reduce the time it takes to build
and deploy the
application. It also enables the enforcement of policies
regarding the
use of third-party libraries.
The way in which dependencies are declared in an OSGi environment is
via manifest headers in a bundle's
As mentioned in xref:developing-applications[], there are
three ways of expressing dependencies:
`Import-Bundle` and
The Form Tags application uses JSTL standard tag libraries.
Thus, you
need to choose a JSTL provider, for example the
Apache implementation
which comes with the {tomcat-product-name-short}. To use the
implementation of JSTL, you need to express your dependency
outlined in the following manifest listing.
Because it is a single
the simplest and therefore preferred manifest header to use.
The Form Tags application requires commons-logging and Spring.
would be very painful to have to list all the Spring packages one by
Equally, considering the number of bundles that make up the
Spring framework, it would be verbose to list each bundle. Therefore
is the preferred approach
for expressing the dependency on the Spring
How do you determine the name of a library definition provided
by the {tomcat-product-name}? Use the {ebr}.
Examine the
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-shared-libs
Import-Library: org.springframework.spring;version="[3.0.0,4.0.0)"
You can see the
directives that instruct the {tomcat-product-name-short} to add the
appropriate package imports to the bundle
classpath used by this WAR file.
Deploying the shared libraries WAR onto the
{tomcat-product-name-short} should result
in console output similar to
the following:
The console output has been reformatted to fit this document.
[2009-07-01 15:00:14.953] fs-watcher
<SPDE0048I> Processing 'CREATED' event for file 'formtags-shared-libs-3.0.0.RELEASE.war'.
[2009-07-01 15:00:15.363] fs-watcher
<SPDE0010I> Deployment of 'org.springframework.showcase.formtags_shared_libs' version '2' completed.
[2009-07-01 15:00:15.364] Thread-20
<SPWE0000I> Starting web bundle '/formtags-shared-libs-3.0.0.RELEASE'.
[2009-07-01 15:00:15.816] Thread-20
<SPWE0001I> Started web bundle '/formtags-shared-libs-3.0.0.RELEASE'.
Navigating to
should render the welcome page. Note that for the pre-packaged
should be similar to
whereas, for a local build the
may be completely
omitted. Please consult the console output,
web-based admin console, or log
to determine the exact context path
under which the web application has been deployed.
=== Form Tags Shared Services WAR
The next step in the migration is to deploy the services as a
OSGi bundle which the WAR then references.
The Form Tags
sample has a single service
This scenario has two separate deployables, the
bundle and the WAR file.
The following image shows the two separate
source trees:
Note that the WAR does not contain the
packages as these will be imported from the separate service bundle.
==== The Service Bundle
The responsibility of the first bundle (
is to provide the API of the formtags service. This includes both
domain and the service API. In the same way that imports are
in the
, so are exports.
The following is the
listing from the service bundle.
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
Export-Package: org.springframework.showcase.formtags.service,org.spri
Import-Library: org.springframework.spring;version="[3.0.0,4.0.0)"
The symbolic name of this bundle is
Note that the name of the bundle typically describes the package that the bundle primarily exports.
If you take a look at the `repository/bundles/ext` in the {tomcat-product-name-short}
directory, you'll see that
names are almost always indicative of the contents of the bundle.
For this example, however, we have also appended
in order to avoid possible clashes with other bundle symbolic
You will see later that the PAR also contains a service
In OSGi, the combination of
is used to uniquely identify
a bundle within the OSGi container.
Furthermore, when you deploy
a bundle to the {tomcat-product-name},
for example via the
directory, a bundle's filename is also used to uniquely
identify it for
the purpose of supporting
*hot deployment*
the file system.
As well as exporting types (i.e. the domain classes and service
API), the service bundle also publishes an implementation of the
. The actual implementation is
; however, that should remain an
implementation detail of this
The fact that this bundle publishes a service is not captured in
, as it is a Gemini Blueprint concept.
The following image is of
As you can see there are two Spring configuration files:
These names are abitrary; however, they follow an informal
typically bootstraps the Spring context
(usually delegating to
smaller fine grained context files inside another directory),
contains all the OSGi service exports and references.
The following is a listing of
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""
<bean id="userManager"
As you can see, this simply defines a bean called
The following is a listing of
<?xml version="1.0" encoding="UTF-8"?>
<service ref="userManager"
This single bean definition exports the
defined in
to the
OSGi service registry and makes it available under the public
The service bundle should now be ready to deploy on the
So copy
to the
Output similar to the following should appear in the
{tomcat-product-name-short}'s console:
The console output has been reformatted to fit this document.
[2009-07-01 15:05:03.511] fs-watcher
<SPDE0048I> Processing 'CREATED' event for file 'formtags-shared-services-service-2.0.0.RELEASE.jar'.
[2009-07-01 15:05:03.688] fs-watcher
<SPDE0010I> Deployment of 'org.springframework.showcase.formtags.service_shared_services' version '2.0.0.RELEASE' completed.
==== Accessing the Service and Types from the WAR
The WAR file now needs to access the types and service exported
the service bundle. The following listing is the WAR's
which imports the types
exported by the service bundle. The
statement has also been extended to import
which is necessary in order to load an OSGi-enabled
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-
Import-Package: org.springframework.showcase.formtags.domain,org.sprin
Import-Library: org.springframework.spring;version="[2.5.4,3.1.0)"
In addition to importing the exported types of the service bundle,
the WAR must also obtain a reference to the
published by the service bundle. The following image shows the
structure of the Shared Services WAR.
As you can see in the above image, the Form Tags Shared Services
directory contains a standard
deployment descriptor,
which defines the configuration
for the
, and
which defines the configuration specific to the
As is typical for Spring MVC based web applications, you configure a
to load your root
; however, to enable your
to be able to reference services from the OSGi Service Registry,
must explicitly set the
Servlet context parameter to the fully qualified
class name of a
which is OSGi-enabled. When deploying
Shared Services WARs to the
{tomcat-product-name}, you should use
This will then enable the use of Gemini Blueprint's `<reference ... />`
within your root `WebApplicationContext` (i.e., in `applicationContext.xml`).
The following listing is an excerpt from `/WEB-INF/web.xml`.
The Form Tags Shared Services WAR contains a
file which is the default configuration location used to create the
for Spring MVC's
As already mentioned, in the OSGi world, bundle configuration
place in the root
Typically Gemini Blueprint powered configuration files will live
there as well (e.g., in
In a WAR, however, the root
loaded by
and the
application context typically live in
The following is the listing of the WAR's
<?xml version="1.0" encoding="UTF-8"?>
<reference id="userManager"
The single bean declaration is retrieving a service that implements
API from the OSGi Service Registry.
You might have been expecting a reference to the service bundle,
but that isn'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
specified interface). This leads to a very loosely coupled
programming model: the WAR really doesn't care where the
comes from.
What happens if there is no service at runtime?
What if there are
multiple services that match the criteria?
Gemini Blueprint provides a lot
of configuration options, including
whether or not the reference is
how long to wait for a service reference, etc. Please consult the
{gemini-blueprint-guide} for further information.
One of the benefits of programming to interfaces is that you
decoupled from the actual implementation; Gemini Blueprint provides a
proxy. This
has enormous benefits including the ability to
dynamically refresh individual bundles without
cascading that
refresh to unrelated bundles.
To deploy the WAR, copy
to the
You should then see console output similar to the
The console output has been reformatted to fit this document.
[2009-07-01 15:09:19.819] fs-watcher
<SPDE0048I> Processing 'CREATED' event for file 'formtags-shared-services-war-3.0.0.RELEASE.war'.
[2009-07-01 15:09:20.167] fs-watcher
<SPDE0010I> Deployment of 'org.springframework.showcase.formtags.web_shared_services' version '3' completed.
[2009-07-01 15:09:20.168] Thread-20
<SPWE0000I> Starting web bundle '/formtags-shared-services-war-3.0.0.RELEASE'.
[2009-07-01 15:09:20.647] Thread-20
<SPWE0001I> Started web bundle '/formtags-shared-services-war-3.0.0.RELEASE'.
Navigating to the appropriate link should render the welcome page.
=== Form Tags PAR
The final step in the migration is that of a full blown
application with web support. The {tomcat-product-name} introduces a
new packaging and deployment format: the PAR.
A PAR is a standard JAR with a "`.par`"
file extension which contains all of the modules of your
application (e.g., service, domain, and infrastructure bundles
as well
as a WAR for web applications) in a single deployment unit.
a PAR defines both a physical and logical application boundary.
The PAR sample is comprised of four directories, as shown below.
directory is a build project that
understands how to create the PAR
from its constituent bundles.
==== Granularity of the PAR
Achieving the appropriate level of granularity for your OSGi
application is more of an art than a science. It helps to look
at the
different requirements:
.Granularity drivers
| Requirement | Description
| Domain/Technical Layering | Applications can be split either by domain (i.e.,
by use case or
) or
by their technical layers (i.e.,
Since the Form Tags application essentially has only
a single
use case, the bundles are split by technical layering
domain, service, and web).
| Refreshability | A major benefit of OSGi is that of refreshability: if one
is changed, only bundles that have a dependency upon
exported types need to be refreshed. This has a high impact
development time costs as well as production
costs. However,
this can lead to lots of smaller, fine grained
bundles. An
example of this granularity would be to
separate out the service
API and implementation into two different
bundles. This means
that a change in the implementation
wouldn't require any
other bundles to be refreshed.
Ultimately the right level of granularity will depend upon your
particular application and team.
==== Domain and Service Bundles
The service bundle is identical (except for the
) to that
in the shared-services variation of the sample.
The PAR has
also separated out the domain classes into their own bundle.
layering by technical considerations, it is again
somewhat of an
unofficial convention to have a
=== Constructing the PAR
Finally we need to construct the PAR itself.
The following are
the contents of the exploded PAR.
You can see that the PAR itself doesn't contain any
resources or
Java classes: it simply packages together a related set
of bundles
as a single, logical unit.
The PAR does however, contain its own
Manifest-Version: 1.0
Application-SymbolicName: org.springframework.showcase.formtags-par
Application-Version: 3.0.0
Application-Name: FormTags Showcase Application (PAR)
For more information on the contents of the PAR's
, please consult xref:developing-applications[].
You can now deploy the PAR on the {tomcat-product-name-short}, for
example by copying
to the {tomcat-product-name-short}'s
You should then see console output similar to the
The console output has been reformatted to fit this document.
[2009-07-01 15:13:43.306] fs-watcher
<SPDE0048I> Processing 'CREATED' event for file 'formtags-par-2.0.0.RELEASE.par'.
[2009-07-01 15:13:44.060] fs-watcher
<SPDE0010I> Deployment of 'formtags-par' version '2.0.0.RELEASE' completed.
[2009-07-01 15:13:44.068] Thread-20
<SPWE0000I> Starting web bundle '/formtags-par'.
[2009-07-01 15:13:45.212] Thread-20
<SPWE0001I> Started web bundle '/formtags-par'.
Navigate to http://localhost:8080/formtags-par to see the welcome page.
Note that the web application's context path is explicitly
defined via the
manifest header in
of the Web application bundle within the PAR.
=== Summary of the Form Tags Migration
The {tomcat-product-name} provides out-of-the-box support for
standard Java EE WAR files. In addition support for
*Shared Libraries*
*Shared Services*
WAR formats provides a logical migration path away from standard,
monolithic WARs toward OSGi-enable Web applications. The PAR
and deployment format enables truly fine-grained,
loosely-coupled, and
efficient application development. In general,
the migration steps
presented in this chapter are fairly
straightforward, but developers
should set aside time for some
up-front design of the bundles themselves.
It is recommended that you take another sample application or
indeed your own small application and go through this migration
process yourself. This will help you better understand the concepts
principles at work. In addition, it is highly recommended that you
familiarize yourself with the extensive Eclipse IDE support provided
by the Virgo Tools. See the Virgo Tools Guide for more on that.
=== Form Tags as a Plan
Plans (see xref:developing-applications-plans[])
allow us to package and deploy the Form Tags application in a more
flexible way.
Instead of packaging all the bundles of the application
into a single PAR file, each bundle can be placed in the repository
and referred to in a *plan*.
The bundles to be placed in a repository in the chain (for example,
`repository/usr`) are:
which are just those files which were part of the PAR.
Here is the contents of a suitable plan file for the Form Tags
<?xml version="1.0" encoding="UTF-8"?>
<plan name="formtags.plan" version="2.0.0" scoped="true" atomic="true"
<artifact type="bundle" name="org.springframework.showcase.formtags.domain_par" version="[3.0,3.1)"/>
<artifact type="bundle" name="org.springframework.showcase.formtags.service_par" version="[3.0,3.1)"/>
<artifact type="bundle" name="org.springframework.showcase.formtags.web_par" version="[3.0,3.1)"/>
where we have chosen to use any of the artifacts in the version range [2.0,2.1).
This plan (as a file called, for example, `formtags.plan`)
can be deployed in any of the normal ways (for example, dropped in the `pickup` directory).
When the plan is deployed, the artifacts it references are
installed from the repository and deployed in the order given in the
plan file.
Because this plan is scoped and atomic, the collection is
given an application scope and is started and stopped as a single