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: https://www.eclipse.org/gemini/blueprint/documentation/reference/2.0.0.RELEASE/html/index.html[Eclipse Gemini Blueprint Reference Guide]
:spring-framework-version: 4.2.9.RELEASE
:homepage: https://www.eclipse.org/virgo
:ebr: http://www.eclipse.org/ebr[EBR]
: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`.
image:formtags-case-study-sample-layout.png[]
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.
[TIP]
--
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.
--
anchor:formtags-case-study-introduction[]
=== Overview of the Form Tags Sample Application
The sample that we will be using is the Form Tags show case
sample
which was provided with Spring 2.0. The Form Tags application
has
been removed from the official Spring 2.5.x distributions;
however,
since it is relatively simple but still contains enough
ingredients
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
`form:`
tags, released
in Spring 2.0, make view development with JSPs and tag
libraries easier.
The Form Tags application consists of a single
`UserService`
which returns a list
of
`Users`
. Furthermore, the application demonstrates how to list, view,
and
edit
`Users`
in a simple Spring MVC based web application using JSP
and JSTL.
anchor:formtags-case-study-war[]
=== Form Tags WAR
We begin with a standard WAR deployment.
[NOTE]
--
The {tomcat-product-name-short} supports the standard Java EE WAR
packaging
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
dependencies
(for example: Spring, Commons Logging) are packaged as
JARs in
`WEB-INF/lib`
.
image:formtags-case-study-exploded-war.png[]
To deploy this application, simply copy
`dist/formtags-war-3.0.0.*.war`
to
the
`SERVER_HOME/pickup`
directory for hot deployment.
You should then see the {tomcat-product-name-short} produce
console output similar to the following:
[NOTE]
--
The console output has been reformatted to fit this document.
--
[source,txt]
----
[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
`http://localhost:8080/`
plus the web application context path,
which in the above case is
`formtags-war-3.0.0.RELEASE`
. Thus navigating to
`http://localhost:8080/formtags-war-3.0.0.RELEASE`
should render the sample application's welcome page, as
displayed in the screen
shot below.
[TIP]
--
For WARs, the default web context path is the name of the WAR file
without the
`.war`
extension. You can optionally
specify a context path using the
`Web-ContextPath`
bundle
manifest header, which will be described in further detail
later.
--
image:formtags-case-study-war-webpage.png[]
anchor:formtags-case-study-war-shared-libs[]
=== Form Tags Shared Libraries WAR
As mentioned above, a standard WAR file typically packages of all its
required
dependencies in
`WEB-INF/lib`
. The servlet container will
then add all of the JARs in
`WEB-INF/lib`
to the application's
classpath.
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
`/META-INF/MANIFEST.MF`
.
As mentioned in xref:developing-applications[], there are
three ways of expressing dependencies:
`Import-Package`,
`Import-Bundle` and
`Import-Library`.
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
Apache
implementation of JSTL, you need to express your dependency
as
outlined in the following manifest listing.
Because it is a single
bundle,
`Import-Bundle`
is
the simplest and therefore preferred manifest header to use.
The Form Tags application requires commons-logging and Spring.
It
would be very painful to have to list all the Spring packages one by
one.
Equally, considering the number of bundles that make up the
Spring framework, it would be verbose to list each bundle. Therefore
`Import-Library`
is the preferred approach
for expressing the dependency on the Spring
framework.
[TIP]
--
How do you determine the name of a library definition provided
by the {tomcat-product-name}? Use the {ebr}.
--
Examine the
`/META-INF/MANIFEST.MF`
in
`/dist/formtags-shared-libs-*.war`:
[source,txt]
----
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)"
Import-Bundle: com.springsource.org.apache.taglibs.standard;version="1
.1.2"
----
You can see the
`Import-Library`
and
`Import-Bundle`
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:
[NOTE]
--
The console output has been reformatted to fit this document.
--
[source,txt]
----
[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
`http://localhost:8080/formtags-shared-libs-BUILDTAG
`
should render the welcome page. Note that for the pre-packaged
distributable,
the
`BUILDTAG`
should be similar to
`3.0.0.RELEASE`
;
whereas, for a local build the
`-BUILDTAG`
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.
anchor:formtags-case-study-war-shared-services[]
=== Form Tags Shared Services WAR
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
`UserManager`.
This scenario has two separate deployables, the
`service`
bundle and the WAR file.
The following image shows the two separate
source trees:
image:formtags-case-study-shared-services-eclipse.png[]
[NOTE]
--
Note that the WAR does not contain the
`.domain`
or
`.service`
packages as these will be imported from the separate service bundle.
--
anchor:formtags-case-study-war-shared-services-service[]
==== The Service Bundle
The responsibility of the first bundle (
`formtags-shared-services-service`
)
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
`/META-INF/MANIFEST.MF`
, so are exports.
The following is the
`/META-INF/MANIFEST.MF`
listing from the service bundle.
[source,txt]
----
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
ngframework.showcase.formtags.domain
Import-Library: org.springframework.spring;version="[3.0.0,4.0.0)"
----
The symbolic name of this bundle is
`org.springframework.showcase.formtags.service-shared-services`.
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
"`-shared-services`"
in order to avoid possible clashes with other bundle symbolic
names.
You will see later that the PAR also contains a service
bundle.
[NOTE]
--
In OSGi, the combination of
`Bundle-SymbolicName`
and
`Bundle-Version`
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
`pickup`
directory, a bundle's filename is also used to uniquely
identify it for
the purpose of supporting
*hot deployment*
via
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
`UserManager`
. The actual implementation is
`StubUserManager`
; however, that should remain an
implementation detail of this
bundle.
The fact that this bundle publishes a service is not captured in
the
`/META-INF/MANIFEST.MF`
, as it is a Gemini Blueprint concept.
The following image is of
`src/main/resources/spring`.
image:formtags-case-study-shared-services-service-resources.png[]
As you can see there are two Spring configuration files:
`module-context.xml`
and
`osgi-context.xml`.
[TIP]
--
These names are abitrary; however, they follow an informal
convention:
`module-context.xml`
typically bootstraps the Spring context
(usually delegating to
smaller fine grained context files inside another directory),
whilst
`osgi-context.xml`
contains all the OSGi service exports and references.
--
The following is a listing of
`module-context.xml`
.
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="userManager"
class="org.springframework.showcase.formtags.service.internal.StubUserManager"/>
</beans>
----
As you can see, this simply defines a bean called
`userManager`
.
The following is a listing of
`osgi-context.xml`.
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<service ref="userManager"
interface="org.springframework.showcase.formtags.service.UserManager"/>
</beans:beans>
----
This single bean definition exports the
`userManager`
defined in
`module-context.xml`
to the
OSGi service registry and makes it available under the public
`org.springframework.showcase.formtags.service.UserManager
`
API.
The service bundle should now be ready to deploy on the
{tomcat-product-name-short}.
So copy
`/dist/formtags-shared-services-services*`
to the
`SERVER_HOME/pickup`
directory.
Output similar to the following should appear in the
{tomcat-product-name-short}'s console:
[NOTE]
--
The console output has been reformatted to fit this document.
--
[source,txt]
----
[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.
----
anchor:formtags-case-study-war-shared-services-war[]
==== Accessing the Service and Types from the WAR
The WAR file now needs to access the types and service exported
by
the service bundle. The following listing is the WAR's
`/META-INF/MANIFEST.MF`
which imports the types
exported by the service bundle. The
`Import-Bundle`
statement has also been extended to import
`org.springframework.osgi.core`
,
which is necessary in order to load an OSGi-enabled
`WebApplicationContext`
.
[source,txt]
----
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
Import-Package: 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",org.springframework.osgi.core
----
In addition to importing the exported types of the service bundle,
the WAR must also obtain a reference to the
`UserManager`
published by the service bundle. The following image shows the
directory
structure of the Shared Services WAR.
image:formtags-case-study-shared-services-war-resources.png[]
As you can see in the above image, the Form Tags Shared Services
WAR's
`/WEB-INF/web.xml`
directory contains a standard
`web.xml`
deployment descriptor,
`applicationContext.xml`
which defines the configuration
for the
*root*
`WebApplicationContext`
, and
`formtags-servlet.xml`
which defines the configuration specific to the
configured
*formtags*
`DispatcherServlet`
.
As is typical for Spring MVC based web applications, you configure a
`ContextLoaderListener`
in
`web.xml`
to load your root
`WebApplicationContext`
; however, to enable your
`WebApplicationContext`
to be able to reference services from the OSGi Service Registry,
you
must explicitly set the
`contextClass`
Servlet context parameter to the fully qualified
class name of a
`ConfigurableWebApplicationContext`
which is OSGi-enabled. When deploying
Shared Services WARs to the
{tomcat-product-name}, you should use
`org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext`.
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`.
[source,xml]
----
<context-param>
<param-name>contextClass</param-name>
<param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
----
The Form Tags Shared Services WAR contains a
`/WEB-INF/applicationContext.xml`
file which is the default configuration location used to create the
*root*
`WebApplicationContext`
for Spring MVC's
`ContextLoaderListener`.
[NOTE]
--
As already mentioned, in the OSGi world, bundle configuration
takes
place in the root
`/META-INF/`
directory.
Typically Gemini Blueprint powered configuration files will live
there as well (e.g., in
`/META-INF/spring/*.xml`
).
In a WAR, however, the root
`WebApplicationContext`
loaded by
`ContextLoaderListener`
and the
`DispatcherServlet's`
application context typically live in
`/WEB-INF/`.
--
The following is the listing of the WAR's
`/WEB-INF/applicationContext.xml`.
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<reference id="userManager"
interface="org.springframework.showcase.formtags.service.UserManager"/>
</beans:beans>
----
The single bean declaration is retrieving a service that implements
the
`org.springframework.showcase.formtags.service.UserManager
`
API from the OSGi Service Registry.
[TIP]
--
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
the
specified interface). This leads to a very loosely coupled
programming model: the WAR really doesn't care where the
implementation
comes from.
--
[TIP]
--
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
*mandatory*
,
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
are
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
`/dist/formtags-shared-services-war*`
to the
`SERVER_HOME/pickup`
directory.
You should then see console output similar to the
following:
[NOTE]
--
The console output has been reformatted to fit this document.
--
[source,txt]
[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.
anchor:formtags-case-study-par[]
=== Form Tags PAR
The final step in the migration is that of a full blown
OSGi
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.
Moreover,
a PAR defines both a physical and logical application boundary.
The PAR sample is comprised of four directories, as shown below.
image:formtags-case-study-par-sample.png[]
The
`formtags-par`
directory is a build project that
understands how to create the PAR
from its constituent bundles.
anchor:formtags-case-study-par-granularity[]
==== 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:
[options="header",cols="2,3"]
.Granularity drivers
|=======================================================================
| Requirement | Description
| Domain/Technical Layering | Applications can be split either by domain (i.e.,
by use case or
*vertically*
) or
by their technical layers (i.e.,
*horizontally*
).
Since the Form Tags application essentially has only
a single
use case, the bundles are split by technical layering
(i.e.,
domain, service, and web).
| Refreshability | A major benefit of OSGi is that of refreshability: if one
bundle
is changed, only bundles that have a dependency upon
the
exported types need to be refreshed. This has a high impact
on
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.
anchor:formtags-case-study-par-domain-and-service[]
==== Domain and Service Bundles
The service bundle is identical (except for the
`Bundle-SymbolicName`
) to that
in the shared-services variation of the sample.
The PAR has
also separated out the domain classes into their own bundle.
When
layering by technical considerations, it is again
somewhat of an
unofficial convention to have a
`.domain`
bundle.
anchor:formtags-case-study-par-par[]
=== Constructing the PAR
Finally we need to construct the PAR itself.
The following are
the contents of the exploded PAR.
image:formtags-case-study-par-exploded.png[]
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
`/META-INF/MANIFEST.MF`.
[source,txt]
----
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
`/META-INF/MANIFEST.MF`
, please consult xref:developing-applications[].
You can now deploy the PAR on the {tomcat-product-name-short}, for
example by copying
`/dist/formtags-par*.par`
to the {tomcat-product-name-short}'s
`pickup`
directory.
You should then see console output similar to the
following:
[NOTE]
--
The console output has been reformatted to fit this document.
--
[source,txt]
----
[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.
[TIP]
--
Note that the web application's context path is explicitly
defined via the
`Web-ContextPath`
manifest header in
`/META-INF/MANIFEST.MF`
of the Web application bundle within the PAR.
--
anchor:formtags-case-study-summary[]
=== Summary of the Form Tags Migration
The {tomcat-product-name} provides out-of-the-box support for
deploying
standard Java EE WAR files. In addition support for
*Shared Libraries*
and
*Shared Services*
WAR formats provides a logical migration path away from standard,
monolithic WARs toward OSGi-enable Web applications. The PAR
packaging
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
and
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.
anchor:formtags-case-study-as-plan[]
=== 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:
[source,txt]
----
org.springframework.showcase.formtags.domain-2.0.0.RELEASE.jar
org.springframework.showcase.formtags.service-2.0.0.RELEASE.jar
org.springframework.showcase.formtags.web-2.0.0.RELEASE.war
----
which are just those files which were part of the PAR.
Here is the contents of a suitable plan file for the Form Tags
example:
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<plan name="formtags.plan" version="2.0.0" scoped="true" atomic="true"
xmlns="http://www.eclipse.org/virgo/schema/plan"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.eclipse.org/virgo/schema/plan
http://www.eclipse.org/virgo/schema/plan/eclipse-virgo-plan.xsd">
<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)"/>
</plan>
----
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
unit.