blob: 4c913a5afa1885ce54e032bd65651558f02661ca [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>A Guide to the GreenPages Sample</title><link rel="stylesheet" href="css/stylesheet.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"><meta name="description" content="Spring application programmers are introduced to Virgo by installing the Virgo Tomcat Server and building and running a small application called GreenPages. Despite its simplicity, GreenPages is designed to demonstrate many different Virgo features and to act as a template from which other modular applications can be built. This guide highlights areas of interest in the sample code. This version of the guide is based on the following software versions: GreenPages Sample2.5.0.RELEASEVirgo Tomcat Server3.0.2.RELEASEApache Maven2.2.0"><!--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="book" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="d0e1"></a>A Guide to the GreenPages Sample</h1></div><div><div class="mediaobject" align="right"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0"><tr><td align="right" valign="bottom"><img src="images/virgo-logo-large.png" align="right"></td></tr></table></div></div><div><div class="abstract"><p class="title"><b>Abstract</b></p><p>
Spring application programmers are introduced to Virgo
by installing the Virgo Tomcat Server and building and running a small application called GreenPages.
</p><p>
Despite its simplicity, GreenPages is designed to demonstrate many different Virgo features and to
act as a template from which other modular applications can be built.
This guide highlights areas of interest in the sample code.
</p><p>
This version of the guide is based on the following software versions:
</p><table class="simplelist" border="0" summary="Simple list"><tr><td></td><td><span class="emphasis"><em>GreenPages Sample</em></span></td><td>2.5.0.RELEASE</td></tr><tr><td></td><td><span class="emphasis"><em>Virgo Tomcat Server</em></span></td><td>3.0.2.RELEASE</td></tr><tr><td></td><td><span class="emphasis"><em>Apache Maven</em></span></td><td>2.2.0</td></tr></table><p>
</p></div></div></div><div><div><div class="legalnotice"><a name="d0e40"></a><p>
Copyright &copy; 2011 VMware Inc.
</p><div class="mediaobject"><img src="images/virgo-logo-small.png"></div><p>
</p><p>
All rights reserved. This document is made available under the terms of the Eclipse Public License v1.0
which is available at
<a class="ulink" href="http://www.eclipse.org/legal/epl-v10.html" target="_top">http://www.eclipse.org/legal/epl-v10.html</a>.
</p><p>Java, Sun, and Sun Microsystems
are trademarks or registered
trademarks of Sun Microsystems, Inc. in the United
States and other countries.
</p><p>OSGi is a trademark or a registered trademark of the OSGi Alliance in
the United States, other countries, or both.
</p><p>Eclipse is a trademark of Eclipse Foundation, Inc.</p><p>UNIX is a registered trademark of The Open Group.</p><p>Windows is a registered trademark of Microsoft Corporation in the
United States and other countries.</p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#installation">1. Installing Pre-requisites</a></span></dt><dd><dl><dt><span class="section"><a href="#installation.prereqs">1.1. Installing a JDK</a></span></dt><dt><span class="section"><a href="#installation.dmserver">1.2. Installing Virgo Tomcat Server</a></span></dt><dt><span class="section"><a href="#installation.virgotooling">1.3. Installing the Eclipse Tooling</a></span></dt><dt><span class="section"><a href="#installation.maven">1.4. Installing Apache Maven</a></span></dt></dl></dd><dt><span class="chapter"><a href="#installing.greenpages">2. Installing and Running GreenPages</a></span></dt><dd><dl><dt><span class="section"><a href="#installing.greenpages.introduction">2.1. Introduction</a></span></dt><dt><span class="section"><a href="#installing.greenpages.obtaining">2.2. Obtaining GreenPages</a></span></dt><dt><span class="section"><a href="#installing.greenpages.building">2.3. Building and Installing GreenPages</a></span></dt><dt><span class="section"><a href="#installing.greenpages.browsing">2.4. Browsing the GreenPages Application</a></span></dt><dt><span class="section"><a href="#installing.greenpages.tools">2.5. Running GreenPages from Eclipse</a></span></dt></dl></dd><dt><span class="chapter"><a href="#highlights">3. GreenPages Highlights</a></span></dt><dd><dl><dt><span class="section"><a href="#highlights.wab">3.1. Web Application Bundle Highlights</a></span></dt><dt><span class="section"><a href="#highlights.middletier">3.2. Middle Tier Highlights</a></span></dt><dt><span class="section"><a href="#highlights.testing">3.3. Testing Highlights</a></span></dt><dt><span class="section"><a href="#highlights.automated.build">3.4. Automated Build Highlights</a></span></dt></dl></dd><dt><span class="appendix"><a href="#further.resources">A. Further Resources</a></span></dt><dd><dl><dt><span class="section"><a href="#further.resources.projects">A.1. Projects</a></span></dt><dt><span class="section"><a href="#further.resources.documentation">A.2. Documentation</a></span></dt></dl></dd></dl></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="installation"></a>1.&nbsp;Installing Pre-requisites</h2></div></div></div><p>
Before building and running the GreenPages sample, it is essential to install a <span class="emphasis"><em>JDK</em></span>,
<span class="emphasis"><em>Virgo Tomcat Server</em></span> and <span class="emphasis"><em>Apache Maven</em></span>.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installation.prereqs"></a>1.1&nbsp;Installing a JDK</h2></div></div></div><p>
Before proceeding, ensure that a Java<span class="trademark"></span>&#8482; Standard Edition Development Kit (JDK)
for Java 6 or later is installed and that the <code class="literal">JAVA_HOME</code> environment variable
is set to the root directory of the JDK.
(<span class="emphasis"><em>A Java Runtime Environment (JRE) alone is not sufficient for building the sample.</em></span>)
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installation.dmserver"></a>1.2&nbsp;Installing Virgo Tomcat Server</h2></div></div></div><p>
Unzip the Virgo Tomcat Server Zip file.
Ensure the destination path does not contain spaces.
On Windows<span class="trademark"></span>&#8482; operating systems, ensure you unzip this near the root of a drive to avoid issues with long path names.
</p><p>
Please refer to the Virgo User Guide for full installation instructions.
See <a class="link" href="#further.resources.documentation" title="A.2&nbsp;Documentation">Documentation</a>.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installation.virgotooling"></a>1.3&nbsp;Installing the Eclipse Tooling</h2></div></div></div><p>
This is necessary only if you would like to run the sample under Eclipse.
</p><p>
Please refer to the Virgo Programmer Guide for installation instructions of the Virgo tooling.
See <a class="link" href="#further.resources.documentation" title="A.2&nbsp;Documentation">Documentation</a>.
</p><p>
This sample also uses Maven and to support the build in Eclipse you need to install the m2e plugin.
This is simple to do from the 'Help' -&gt; 'Install New Software..' menu item. Add a new update site of
<code class="literal">http://download.eclipse.org/technology/m2e/releases/</code> and then use it to install the plugin.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installation.maven"></a>1.4&nbsp;Installing Apache Maven</h2></div></div></div><p>
<span class="emphasis"><em>Apache Maven</em></span>, or Maven for short, is a software project management and comprehension tool
which uses a central <span class="emphasis"><em>Project Object Model</em></span> (POM) to manage a project&#8217;s build, reporting
and documentation generation. POM files (<code class="literal">pom.xml</code>) are included in the projects for
GreenPages.
</p><p>
To install Maven, visit the Maven website (<a class="ulink" href="http://maven.apache.org" target="_top">http://maven.apache.org</a>)
and follow the download instructions from there.
This document has been written and tested with Maven version 2.2.0. The rest of the document
assumes that Maven
commands (<code class="literal">mvn &#8230;</code>) are available from the command line.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="installing.greenpages"></a>2.&nbsp;Installing and Running GreenPages</h2></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installing.greenpages.introduction"></a>2.1&nbsp;Introduction</h2></div></div></div><p>GreenPages is a simple application that allows users to search an online email address directory. Each listing
in the directory details the relevant email addresses and the name of the owner. GreenPages has only three screens:
the search screen, the results screen and the listing detail screen.</p><p>In the search screen, users can enter search criteria to be matched against the listings in the directory.
The result screen displays any listings that match the criteria entered by the user. The listing detail screen
shows all the data known about a given listing.</p><p>Despite its simplicity, GreenPages is designed to demonstrate many different Virgo Tomcat Server features and to
act as a template from which other modular applications can be built. In particular, GreenPages demonstrates:
</p><div class="itemizedlist"><ul type="bullet"><li style="list-style-type: disc"><p>bundle dependencies with <code class="literal">Import-Package</code>,</p></li><li style="list-style-type: disc"><p>load-time weaving with JPA and AspectJ,</p></li><li style="list-style-type: disc"><p>bundle classpath scanning, and</p></li><li style="list-style-type: disc"><p>service export, lookup and injection.</p></li></ul></div><p>In addition to demonstrating common Virgo Tomcat Server features, GreenPages demonstrates integration with:
</p><div class="itemizedlist"><ul type="bullet"><li style="list-style-type: disc"><p>Spring Framework 3.0;</p></li><li style="list-style-type: disc"><p>FreeMarker 2.3;</p></li><li style="list-style-type: disc"><p>EclipseLink 1.0.0;</p></li><li style="list-style-type: disc"><p>H2 1.0.71; and</p></li><li style="list-style-type: disc"><p>Commons DBCP 1.2.2.</p></li></ul></div><p>
</p><p>The GreenPages application is packaged as a PAR file containing four bundles.
</p><div class="mediaobject" align="center"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="461"><tr><td align="center"><img src="images/installing-greenpages/greenpages.png" align="middle" width="461"></td></tr></table></div><p>
</p><p>
The <code class="literal">greenpages.db</code> bundle provides access to an external database and publishes a
<code class="literal">javax.sql.DataSource</code> service.
</p><p>
The <code class="literal">greenpages.app</code> bundle exports a <code class="literal">greenpages</code> package containing
<code class="literal">Directory</code> and <code class="literal">Listing</code> interfaces.
</p><p>
The <code class="literal">greenpages.jpa</code> bundle imports the <code class="literal">greenpages</code> package and
uses the <code class="literal">javax.sql.DataSource</code> service to
access the external database and publishes its contents as a <code class="literal">greenpages.Directory</code> service.
</p><p>
The <code class="literal">greenpages.web</code> web application bundle imports the <code class="literal">greenpages</code> package and uses the
<code class="literal">greenpages.Directory</code> service to respond to web requests.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installing.greenpages.obtaining"></a>2.2&nbsp;Obtaining GreenPages</h2></div></div></div><p>This document provides instructions for building the complete GreenPages application and running it in Virgo Tomcat Server.
</p><p>To get the completed GreenPages application, including tests and explanatory skeleton parts:
</p><div class="orderedlist"><ol type="1"><li><p>download the latest Zip file from </p><pre class="programlisting">http://eclipse.org/virgo/download/</pre></li><li><p>extract all the files from the Zip file to a convenient directory (preserving the directory structure).</p></li></ol></div><p>
</p><p>To extract the files on Windows:
</p><pre class="programlisting">prompt&gt; mkdir c:\springsource\samples
prompt&gt; cd c:\springsource\samples
prompt&gt; jar xf c:\path\to\greenpages-2.5.0.RELEASE.zip
prompt&gt; set GREENPAGES_HOME=c:\springsource\samples\greenpages-2.5.0.RELEASE</pre><p>
</p><p>To extract the files on Unix systems:
</p><pre class="programlisting">prompt$ mkdir -p /opt/springsource/samples
prompt$ cd /opt/springsource/samples
prompt$ unzip /path/to/greenpages-2.5.0.RELEASE.zip
prompt$ export GREENPAGES_HOME=/opt/springsource/samples/greenpages-2.5.0.RELEASE
</pre><p>
</p><p>The environment variable <code class="literal">GREENPAGES_HOME</code> set here is not used by the projects, but is used as a shorthand
in the instructions that follow.
</p><p>The GreenPages Zip file contains several directories with names that start <code class="literal">greenpages</code>.
They contain the completed application which can be built and tested (as described in the next section).
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installing.greenpages.building"></a>2.3&nbsp;Building and Installing GreenPages</h2></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.building.mvn"></a>Building with Apache Maven</h3></div></div></div><p>GreenPages uses Apache Maven as its primary build system. Each bundle of the application can be built
separately and the entire application can built and assembled into a PAR file from a single location.
To build the application and assemble it into a PAR
file:
</p><div class="orderedlist"><ol type="1"><li><p>Make <code class="code">$GREENPAGES_HOME/</code> the current directory.</p></li><li><p>Run the command
<code class="code">mvn package</code>. The first time this is run several files will be downloaded
from Maven repositories. Subsequent runs will not need to do this.
</p></li><li><p>Verify that the
<code class="code">greenpages-2.5.0.RELEASE.par</code> file exists in
<code class="code">$GREENPAGES_HOME/greenpages/target</code>.
</p></li></ol></div><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.building.par.provided"></a>Installing Dependencies into Virgo Tomcat Server</h3></div></div></div><p>
Unlike traditional Java EE applications, GreenPages does not package all of its dependencies inside its
deployment unit. Instead, it relies on the mechanisms of OSGi to locate its dependencies at runtime.
When running an OSGi application on Virgo Tomcat Server, these dependencies can be loaded into memory as needed, but first they
must be made available to Virgo Tomcat Server.
</p><p>The Maven build included with GreenPages uses the <code class="code">dependency:copy-dependencies</code> plugin to gather
all the artifacts that GreenPages depends on that are not supplied by the Virgo Tomcat Server runtime. These dependencies
can then be installed into the Virgo Tomcat Server repository. Dependencies are gathered automatically during the
<code class="code">package</code> phase. These dependencies can be found in
<code class="literal">$GREENPAGES_HOME/greenpages/target/par-provided</code>. To install dependencies
simply copy all the <code class="code">*.jar</code> files from this directory into <code class="literal">$SERVER_HOME/repository/usr</code>
(where <code class="literal">$SERVER_HOME</code> is the Virgo Tomcat Server installation directory).
</p><p>Installing dependencies on Windows:
</p><pre class="programlisting">prompt&gt; cd %GREENPAGES_HOME%\greenpages
prompt&gt; copy target\par-provided\* %SERVER_HOME%\repoorg.apache.commons.fileuploadsitory\usr
</pre><p>
</p><p>Installing dependencies on UNIX:
</p><pre class="programlisting">prompt$ cd $GREENPAGES_HOME/org.apache.commons.fileuploadgreenpages
prompt$ cp target/par-provided/* $SERVER_HOME/repository/usr
</pre><p>
</p><p>
Notice that Virgo Tomcat Server will not necessarily see these dependencies unless its repository indexes are rebuilt.
Different repositories behave differently in this respect; some are passive (their indexes are built only once upon startup)
and some are active (they can detect new files or files being removed dynamically).
The <code class="literal">usr</code> repository is active so there is no
need to restart Virgo Tomcat Server when copying these files.
The next time Virgo Tomcat Server is started the <code class="literal">-clean</code> option will cause Virgo Tomcat Server to re-scan the repository directories in any case.
It is always safe to start Virgo Tomcat Server with the <code class="literal">-clean</code> option.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.building.db"></a>Starting and Configuring the Database</h3></div></div></div><p>GreenPages uses the H2 database to store all its data. Before starting the application, start the database server and populate the database with data.</p><div class="orderedlist"><ol type="1"><li><p>Change to the <code class="code">$GREENPAGES_HOME/db</code> current directory. On Unix:</p><pre class="programlisting">prompt$ cd $GREENPAGES_HOME/db</pre><p>On Windows:</p><pre class="programlisting">prompt&gt; cd %GREENPAGES_HOME%\db</pre></li><li><p>Run the database startup script appropriate to the operating system. For Unix, this is <code class="literal">run.sh</code>, run in the background:</p><pre class="programlisting">prompt$ sh run.sh &amp;</pre><p>Press Return to continue.</p><p>On Windows, run the <code class="literal">run.bat</code> command:</p><pre class="programlisting">prompt&gt; run</pre><p>For both platforms, the command might invoke a browser window offering a connection to the database; close this window.</p></li><li><p>Run the data population script appropriate to the operating system. For Unix, this is <code class="literal">data.sh</code>:</p><pre class="programlisting">prompt$ sh data.sh</pre><p>On Windows, run the <code class="literal">data.bat</code> command:</p><pre class="programlisting">prompt&gt; data</pre></li></ol></div><p>
Run these commands once to start a database server for H2; the server will continue to run in the background.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.building.par"></a>Installing and Starting GreenPages PAR</h3></div></div></div><p>To install the GreenPages PAR into Virgo Tomcat Server and start it:
</p><div class="orderedlist"><ol type="1"><li><p>Copy the GreenPages PAR to the <code class="code">$SERVER_HOME/pickup</code> directory. On Unix:</p><pre class="programlisting">prompt$ cd $SERVER_HOME
prompt$ cp $GREENPAGES_HOME/greenpages/target/greenpages-2.5.0.RELEASE.par pickup/</pre><p>On Windows:</p><pre class="programlisting">prompt&gt; cd %SERVER_HOME%
prompt&gt; copy %GREENPAGES_HOME%\greenpages\target\greenpages-2.5.0.RELEASE.par pickup\</pre></li><li><p>Start Virgo Tomcat Server with the <code class="literal">-clean</code> option. On Unix:</p><pre class="programlisting">prompt$ $SERVER_HOME/bin/startup.sh -clean</pre><p>On Windows:</p><pre class="programlisting">prompt&gt; "%SERVER_HOME%"\bin\startup.bat -clean</pre></li><li><p>Verify that GreenPages starts correctly by checking in the Virgo Tomcat Server output for the log message:
</p><pre class="programlisting">&lt;DE0005I&gt; Started par 'greenpages' version '2.5.0.RELEASE'. </pre><p>
</p></li></ol></div><p>
</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installing.greenpages.browsing"></a>2.4&nbsp;Browsing the GreenPages Application</h2></div></div></div><p>
Once installed and started, the GreenPages
application can be accessed with a web browser using the address
<a class="ulink" href="http://localhost:8080/greenpages" target="_top">http://localhost:8080/greenpages</a>.
</p><p>
From the home page, a search query can be entered into the search box:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/browse-1.png" align="middle"></div><p>
</p><p>
After entering a query into the search box, the results page shows all the matches from the
directory:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/browse-2.png" align="middle"></div><p>
</p><p>
Clicking on <span class="emphasis"><em>view</em></span>, next to an entry in the search listing, displays the full details for that
listing entry:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/browse-3.png" align="middle"></div><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="installing.greenpages.tools"></a>2.5&nbsp;Running GreenPages from Eclipse</h2></div></div></div><p>Using Eclipse and the Virgo Tomcat Server tools, it is possible to run applications directly from the IDE.
As changes are made to the application in the IDE,
they can be automatically applied to the running application allowing for rapid feedback of changes in function.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.tools.importing"></a>Importing the GreenPages Projects into Eclipse</h3></div></div></div><p>
Before starting the GreenPages application from Eclipse, import the projects:
</p><div class="orderedlist"><ol type="1"><li><p>Open the Import Wizard using
<span class="guimenu">File</span> &#8594; <span class="guimenuitem">Import</span>.
</p></li><li><p>From the Import Wizard select
<span class="guimenu">General</span> &#8594; <span class="guimenuitem">Existing Projects into Workspace</span>
and click <span class="emphasis"><em>Next</em></span>:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/import-projects2.png" align="middle"></div><p>
</p></li><li><p>Click <span class="guibutton">Browse&#8230;</span> and select <code class="code">$GREENPAGES_HOME/</code> as the root directory.</p></li><li><p>In the <span class="emphasis"><em>Import Projects</em></span> window, select all the projects which include <code class="literal">greenpages</code> in their name and click <span class="emphasis"><em>Finish</em></span>:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/import-projects3.png" align="middle"></div><p>
</p></li><li><p>Validate that the imported projects appear in Package Explorer:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/import-projects4.png" align="middle"></div><p>
There may be compilation errors at this stage.
</p></li></ol></div><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.tools.configuring"></a>Configuring Virgo Tomcat Server Target Runtime</h3></div></div></div><p>
Projects for Virgo Tomcat Server are associated with a Virgo Virgo Tomcat Server runtime environment in Eclipse. This is to allow
launching and testing from within Eclipse, and also to allow classpath construction in Eclipse to
mirror the dynamic classpath in the Virgo Tomcat Server runtime.
</p><p>
Compilation errors in the previous step will be resolved here.
</p><p>
To configure a Virgo Tomcat Server runtime environment:
</p><div class="orderedlist"><ol type="1"><li><p>Open <span class="guimenu">Window</span> &#8594; <span class="guisubmenu">Show View</span> &#8594; <span class="guimenuitem">Other&#8230;</span>.</p></li><li><p>In the <span class="emphasis"><em>Show View</em></span> dialog choose
<span class="guimenu">Server</span> &#8594; <span class="guimenuitem">Servers</span> to make the servers view visible:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/servers.png" align="middle"></div><p>
</p></li><li><p>Right-click in the <span class="emphasis"><em>Servers</em></span> (which may not be empty) view and select
<span class="guimenu">New</span> &#8594; <span class="guimenuitem">Server</span>.
</p></li><li><p>In the <span class="emphasis"><em>New Server</em></span> dialog, choose
<span class="guimenu">EclipseRT</span> &#8594; <span class="guimenuitem">Virgo Web Server</span>
and click <span class="emphasis"><em>Next</em></span>.
</p></li><li><p>Click <span class="guibutton">Browse</span> and select the <code class="code">$SERVER_HOME</code> directory. Ensure that a JRE is selected
supporting Java 1.6 or above.
Click <span class="guibutton">Finish</span> to complete creation of the server:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/new-server.png" align="middle"></div><p>
</p></li><li><p>Select all projects (except <span class="emphasis"><em>Servers</em></span>) in <span class="emphasis"><em>Package Explorer</em></span>.
Right-click on the projects and choose <span class="guimenuitem">Close Project</span>
and then <span class="guimenuitem">Open Project</span>.
</p></li></ol></div><p>
It is possible that there remain spurious build errors from Eclipse (see the <span class="emphasis"><em>Problems</em></span> view), in which case
a project clean build may clear the problems. Select <span class="guimenu">Project</span> &#8594; <span class="guimenuitem">Clean&#8230;</span>
from the main menu, and choose to <span class="emphasis"><em>Clean all projects</em></span>.
It may be necessary to repeat this on a few projects.
(This process is sometimes known as the &#8220;<span class="quote">Eclipse dance</span>&#8221;.)
</p><p>
Despite the dance steps outlined, there will remain some <span class="emphasis"><em>Warnings/Errors</em></span> like this:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/problem-warning.png" align="middle"></div><p>
It is safe to ignore these.
</p><p>
When the Virgo Tooling starts the Virgo Tomcat Server it uses a &#8216;warm start&#8217; by default.
It is useful to set the <code class="literal">-clean</code> option so that every server start is a clean one.
This is done by an option on the Virgo Tomcat Server Overview window, which is obtained by opening the Virgo Tomcat Server entry in the Servers window.
(Double-click, or right-click and choose Open.)
The check box is labelled &#8216;Start server with -clean option&#8217;.
Close the window before proceeding.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="installing.greenpages.tools.run"></a>Running GreenPages from Within Eclipse</h3></div></div></div><p>
Now that GreenPages is successfully imported into Eclipse, run the project directly from within the IDE.</p><p>If the GreenPages PAR file was previously copied to the <code class="literal">pickup</code> directory, be sure it is now removed so that
it does not conflict with the deployment of the Eclipse project. On Unix:</p><pre class="programlisting">prompt$ cd $SERVER_HOME/pickup
prompt$ rm greenpages-2.5.0.RELEASE.par</pre><p>On Windows:</p><pre class="programlisting">prompt&gt; cd %SERVER_HOME%\pickup
prompt&gt; del greenpages-2.5.0.RELEASE.par</pre><p>Also, to prevent conflicts with the server configured in Eclipse, stop a currently-running Virgo Tomcat Server by typing <code class="literal">Control-C</code> in the console window.</p><p>
To run GreenPages from within Eclipse:
</p><div class="orderedlist"><ol type="1"><li><p>
Right click on the Virgo Tomcat Server instance in the <span class="emphasis"><em>Servers</em></span> view and select the <span class="guimenu">Add and Remove&#8230;</span>
menu item.
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/addedtoserver.png" align="middle"></div><p>
</p></li><li><p>
Add <span class="emphasis"><em>greenpages</em></span> (which is the containing project or PAR) to the server and finish.
</p></li><li><p>To start Virgo Tomcat Server from within Eclipse right-click on the Virgo Tomcat Server node in the Servers window and choose <span class="guimenuitem">Start</span>.
The <span class="emphasis"><em>Servers</em></span> view should now show the server and the added project:
</p><div class="mediaobject" align="center"><img src="images/installing-greenpages/installed.png" align="middle"></div><p>
</p></li><li><p>
Verify that GreenPages is started correctly by checking for:
</p><pre class="programlisting">&lt;DE0005I&gt; Started par 'greenpages' version '2.5.0.RELEASE'.
</pre><p>
in the Console window.
</p></li></ol></div><p>
</p><p>
(<span class="emphasis"><em>If errors are shown implying that GreenPages failed to be installed, this may be because some dependencies were not
copied to Virgo Tomcat Server, as described in <a class="xref" href="#installing.greenpages.building.par.provided" title="Installing Dependencies into Virgo Tomcat Server">the section called &#8220;Installing Dependencies into Virgo Tomcat Server&#8221;</a>. Check this.</em></span>)
</p><p>Once installed and started GreenPages is again available from a web browser at the address
<a class="ulink" href="http://localhost:8080/greenpages" target="_top">http://localhost:8080/greenpages</a>.
</p></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="highlights"></a>3.&nbsp;GreenPages Highlights</h2></div></div></div><p>
This chapter picks out some notable features of the GreenPages sample code from the <code class="literal">greenpages.*</code> folders.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="highlights.wab"></a>3.1&nbsp;Web Application Bundle Highlights</h2></div></div></div><p>
The GreenPages Web Application Bundle (WAB) is built using Spring MVC configured with Spring annotations and component
scanning. The Bundlor tool is used to generate the bundle manifest of the WAB and a service is injected into the code
using Spring DM in combination with Spring autowiring.
</p><p>
For more information on Spring, Spring MVC, Bundlor and Spring DM, please see <a class="link" href="#further.resources.projects" title="A.1&nbsp;Projects">Projects</a>..
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e791"></a>web.xml</h3></div></div></div><p>
The web deployment descriptor file <code class="literal">web.xml</code> is in the <code class="literal">src/main/webapp/WEB_INF</code> folder of the
<code class="literal">greenpages.web</code> project.
It defines a servlet, a servlet context parameter, and a servlet context listener.
</p><p>
Spring's dispatcher servlet is used to dispatch web requests to handlers.
</p><pre class="programlisting"> &lt;servlet&gt;
&lt;servlet-name&gt;greenpages&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
&lt;/servlet&gt;
</pre><p>
</p><p>
The <code class="literal">contextClass</code> servlet parameter declares the implementation of <code class="interfacename">WebApplicationContext</code>
that Spring instantiates.
The application context acts as a root application context and each servlet in the web application, which in the case of GreenPages is
just the dispatcher servlet, has its own application context which is a child of the root application context.
<code class="classname">ServerOsgiBundleXmlWebApplicationContext</code> is provided by Virgo and will hold beans created by Spring DM, which
are then available in child application contexts.
</p><pre class="programlisting"> &lt;context-param&gt;
&lt;param-name&gt;contextClass&lt;/param-name&gt;
&lt;param-value&gt;org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext&lt;/param-value&gt;
&lt;/context-param&gt;
</pre><p>
</p><p>
A servlet context listener is defined which will start up the root application context for the web application when the servlet context
is initialised.
</p><pre class="programlisting"> &lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e829"></a>Controller Class</h3></div></div></div><p>
In the <code class="literal">src/main/java</code> source folder of the <code class="literal">greenpages.web</code> project
the package <code class="classname">greenpages.web</code>
contains the controller class <code class="classname">GreenPagesController</code>.
</p><p>
Spring annotations are used to add web behaviour to the class.
The <code class="classname">@Controller</code> annotation tells Spring that the class serves the role of a controller and that the
class should be scanned for <span class="emphasis"><em>request mappings</em></span>.
Request mappings are defined using the <code class="classname">@RequestMapping</code> annotation.
For instance, the URL <code class="literal">/home.htm</code> is mapped to the handler method <code class="literal">home</code>.
</p><pre class="programlisting">@Controller
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> GreenPagesController {
&#8230;
@RequestMapping(<span class="hl-string">"/home.htm"</span>)
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> home() {
}
&#8230;
</pre><p>
Note that request mappings can also be specified at the class level.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e866"></a>Component Scanning</h3></div></div></div><p>
Spring will detect the <code class="classname">@Controller</code> annotation and create a bean of type controller,
<span class="emphasis"><em>provided that</em></span> it scans the classpath for these.
Spring&#8217;s component scanning is enabled by the presence of a <code class="literal">context</code> tag
in one of the Spring bean definition files.
</p><p>
The <code class="filename">WEB-INF/greenpages-servlet.xml</code> file in the
<code class="literal">src/main/webapp</code> folder contains the following lines:
</p><pre class="programlisting">&lt;<span class="hl-comment">!-- enable classpath scanning --</span>&gt;
&lt;<span class="hl-tag">context:component-scan</span> <span class="hl-attribute">base-package</span>=<span class="hl-value">"greenpages.web"</span> /&gt;
</pre><p>
Notice the convention embodied in the filename <code class="filename">WEB-INF/greenpages-servlet.xml</code>.
During dispatcher servlet initialisation, Spring looks for a file named <code class="literal">[servlet-name]-servlet.xml</code>
in the <code class="literal">WEB-INF</code> directory of the web application and creates the beans defined there.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e900"></a>Bundle Manifest</h3></div></div></div><p>
The Virgo Tomcat Server has special support for WABs.
To take advantage of this support, the <code class="literal">greenpages.web</code> bundle must be declared to be a WAB and a
context path must be defined.
</p><p>
The Bundlor template (the file <code class="filename">template.mf</code> at the top level under the <code class="literal">greenpages.web</code> project)
is input to the Bundlor tool which generates the manifest of the bundle.
</p><p>
The Bundlor template defines the context path as follows (and this is what declares the bundle to be a WAB):
</p><pre class="programlisting">Web-ContextPath: greenpages
</pre><p>
</p><p>
The Bundlor template also ensures Spring packages and greenpages packages from other bundles are imported with suitable version ranges:
</p><pre class="programlisting">Import-Template:
org.springframework.*;version="[3.0, 3.1)",
greenpages.*;version="[2.3, 2.4)"
</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e926"></a>Service Injection</h3></div></div></div><p>
The file <code class="filename">webapp/WEB-INF/applicationContext.xml</code> declares a reference to a
<code class="interfacename">greenpages.Directory</code> service in the service registry using Spring DM as follows:
</p><pre class="programlisting">&lt;<span class="hl-tag">osgi:reference</span> <span class="hl-attribute">id</span>=<span class="hl-value">"directory"</span> <span class="hl-attribute">interface</span>=<span class="hl-value">"greenpages.Directory"</span>/&gt;
</pre><p>
The resultant bean resides in the root web application context.
</p><p>
The <code class="classname">GreenPagesController</code> class uses Spring autowiring to inject the service:
</p><pre class="programlisting">@Autowired
<span class="hl-keyword">private</span> Directory directory;
</pre><p>
The controller's bean resides in the web application context associated with the Spring dispatcher servlet and so has
access to the directory service bean in the root web application context.
</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="highlights.middletier"></a>3.2&nbsp;Middle Tier Highlights</h2></div></div></div><p>
In the middle tier of GreenPages, the DataSource bundle <code class="literal">greenpages.db</code> constructs a DataSource and
publishes it in the service registry and the JPA bundle <code class="literal">greenpages.jpa</code> uses the datasource to define a JPA entity manager
which provides an object-relational mapping between directory listings and the database.
The JPA bundle also uses declarative transaction management to ensure its persistence operations are performed inside transactions.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e959"></a>DataSource</h3></div></div></div><p>
The file <code class="filename">src/main/resources/META-INF/spring/module-context.xml</code> in the <code class="literal">greenpages.db</code> project
declares the Spring <span class="emphasis"><em>p-namespace</em></span>:
</p><pre class="programlisting">&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.xsd"</span>
<span class="hl-attribute">xmlns:p</span>=<span class="hl-value">"http://www.springframework.org/schema/p"</span>&gt;
</pre><p>
which is then used to define properties of a datasource bean:
</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.apache.commons.dbcp.BasicDataSource"</span>
<span class="hl-attribute">p:driverClassName</span>=<span class="hl-value">"org.h2.Driver"</span> <span class="hl-attribute">p:url</span>=<span class="hl-value">"jdbc:h2:~/greenpages-db/greenpages"</span>
<span class="hl-attribute">p:username</span>=<span class="hl-value">"greenpages"</span> <span class="hl-attribute">p:password</span>=<span class="hl-value">"pass"</span>
<span class="hl-attribute">init-method</span>=<span class="hl-value">"createDataSource"</span> <span class="hl-attribute">destroy-method</span>=<span class="hl-value">"close"</span>/&gt;
</pre><p>
</p><p>
The file <code class="filename">src/main/resources/META-INF/spring/osgi-context.xml</code> publishes the datasource bean as a service in the
service registry using Spring DM:
</p><pre class="programlisting">&lt;<span class="hl-tag">osgi:service</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">interface</span>=<span class="hl-value">"javax.sql.DataSource"</span>/&gt;
</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e987"></a>EntityManager</h3></div></div></div><p>
The <code class="classname">greenpages.jpa.JpaDirectory</code> class in the folder <code class="filename">src/main/java</code> of the
<code class="literal">greenpages.jpa</code> project uses the <code class="literal">@Repository</code> annotation to make it eligible for Spring DataAccessException translation
(which abstracts implementation-specific persistence exceptions to protect the application from details of the persistence implementation):
</p><pre class="programlisting">@Repository
<span class="hl-keyword">final</span> <span class="hl-keyword">class</span> JpaDirectory <span class="hl-keyword">implements</span> Directory {
</pre><p>
and also declares an entity manager which will be injected by Spring:
</p><pre class="programlisting">@PersistenceContext
<span class="hl-keyword">private</span> EntityManager em;
</pre><p>
</p><p>
The file <code class="filename">src/main/resources/META-INF/spring/module-context.xml</code> in the <code class="literal">greenpages.jpa</code> project
declares an entity manager factory based on EclipseLink JPA:
</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"entityManagerFactory"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"</span>
<span class="hl-attribute">p:dataSource-ref</span>=<span class="hl-value">"dataSource"</span>&gt;
&lt;<span class="hl-tag">property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"jpaVendorAdapter"</span>&gt;
&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jpaVendorAdapter"</span>
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"</span>
<span class="hl-attribute">p:databasePlatform</span>=<span class="hl-value">"org.eclipse.persistence.platform.database.HSQLPlatform"</span>
<span class="hl-attribute">p:showSql</span>=<span class="hl-value">"true"</span>/&gt;
&lt;<span class="hl-tag">/property</span>&gt;
&lt;<span class="hl-tag">/bean</span>&gt;
</pre><p>
</p><p>
The same file enables scanning for annotations, including <code class="literal">@PersistenceContext</code>:
</p><pre class="programlisting">&lt;<span class="hl-tag">context:annotation-config</span>/&gt;
</pre><p>
enables load-time weaving, which is needed by the entity manager factory:
</p><pre class="programlisting">&lt;<span class="hl-tag">context:load-time-weaver</span> <span class="hl-attribute">aspectj-weaving</span>=<span class="hl-value">"on"</span>/&gt;
</pre><p>
and specifies a bean post processor to perform exception translation for <code class="literal">@Repository</code> classes:
</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"</span>/&gt;
</pre><p>
</p><p>
The file <code class="filename">src/main/resources/META-INF/persistence.xml</code> defines a persistence unit for a <code class="classname">JpaListing</code>
directory listing class.
</p><pre class="programlisting">&lt;<span class="hl-tag">persistence</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://java.sun.com/xml/ns/persistence"</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://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"</span>
<span class="hl-attribute">version</span>=<span class="hl-value">"1.0"</span>&gt;
&lt;<span class="hl-tag">persistence-unit</span> <span class="hl-attribute">name</span>=<span class="hl-value">"GreenPages"</span> <span class="hl-attribute">transaction-type</span>=<span class="hl-value">"RESOURCE_LOCAL"</span>&gt;
&lt;<span class="hl-tag">class</span>&gt;greenpages.jpa.JpaListing&lt;<span class="hl-tag">/class</span>&gt;
&lt;<span class="hl-tag">/persistence-unit</span>&gt;
&lt;<span class="hl-tag">/persistence</span>&gt;
</pre><p>
</p><p>
The file <code class="filename">src/main/resources/META-INF/orm.xml</code> defines an entity mapping for the <code class="classname">JpaListing</code> class.
</p><pre class="programlisting">&lt;<span class="hl-tag">entity-mappings</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://java.sun.com/xml/ns/persistence/orm"</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://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"</span>
<span class="hl-attribute">version</span>=<span class="hl-value">"1.0"</span>&gt;
&lt;<span class="hl-tag">package</span>&gt;greenpages.jpa&lt;<span class="hl-tag">/package</span>&gt;
&lt;<span class="hl-tag">entity</span> <span class="hl-attribute">class</span>=<span class="hl-value">"greenpages.jpa.JpaListing"</span> <span class="hl-attribute">name</span>=<span class="hl-value">"Listing"</span>&gt;
&lt;<span class="hl-tag">table</span> <span class="hl-attribute">name</span>=<span class="hl-value">"LISTING"</span>/&gt;
&lt;<span class="hl-tag">attributes</span>&gt;
&lt;<span class="hl-tag">id</span> <span class="hl-attribute">name</span>=<span class="hl-value">"listingNumber"</span>&gt;
&lt;<span class="hl-tag">column</span> <span class="hl-attribute">name</span>=<span class="hl-value">"LISTING_NUMBER"</span>/&gt;
&lt;<span class="hl-tag">generated-value</span> <span class="hl-attribute">strategy</span>=<span class="hl-value">"TABLE"</span>/&gt;
&lt;<span class="hl-tag">/id</span>&gt;
&lt;<span class="hl-tag">basic</span> <span class="hl-attribute">name</span>=<span class="hl-value">"firstName"</span>&gt;
&lt;<span class="hl-tag">column</span> <span class="hl-attribute">name</span>=<span class="hl-value">"FIRST_NAME"</span>/&gt;
&lt;<span class="hl-tag">/basic</span>&gt;
&#8230;
&lt;<span class="hl-tag">/attributes</span>&gt;
&lt;<span class="hl-tag">/entity</span>&gt;
&lt;<span class="hl-tag">/entity-mappings</span>&gt;
</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1060"></a>Transaction Management</h3></div></div></div><p>
The <code class="classname">greenpages.jpa.JpaDirectory</code> class in the folder <code class="filename">src/main/java</code> of the
<code class="literal">greenpages.jpa</code> project uses the <code class="literal">@Transactional</code> annotation to provide transaction demarcation
(beginning and committing a transaction around each method in this case):
</p><pre class="programlisting">@Transactional
&#8230;
<span class="hl-keyword">final</span> <span class="hl-keyword">class</span> JpaDirectory <span class="hl-keyword">implements</span> Directory {
</pre><p>
</p><p>
The file <code class="filename">src/main/resources/META-INF/spring/module-context.xml</code> enables AspectJ weaving for transaction demarcation:
</p><pre class="programlisting">&lt;<span class="hl-tag">tx:annotation-driven</span> <span class="hl-attribute">mode</span>=<span class="hl-value">"aspectj"</span>/&gt;
</pre><p>
and specifies that the Spring <code class="classname">JpaTransactionManager</code> should be used and associated with the entity manager factory:
</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"transactionManager"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.orm.jpa.JpaTransactionManager"</span>
<span class="hl-attribute">p:entityManagerFactory-ref</span>=<span class="hl-value">"entityManagerFactory"</span>/&gt;
</pre><p>
</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="highlights.testing"></a>3.3&nbsp;Testing Highlights</h2></div></div></div><p>
Testing is one of the most important aspects of software development. Without testing it would be difficult
to determine if a piece of code worked properly, changes would have undetected consequences, and the quality
of the code would generally be lower.
</p><p>
There are two major categories of testing generally recognised today: unit testing
and integration testing. In the context of the
GreenPages application, <span class="emphasis"><em>unit testing</em></span> means testing a single class in isolation from other application code.
This type of testing does not change at all when developing for Virgo and so the GreenPages sample does not include any unit tests.
</p><p>
In our application <span class="emphasis"><em>integration testing</em></span> means testing an application or
portion of an application with other code. This kind of testing does look a bit different when developing
for Virgo. In most cases Virgo applications are made up of small bundles that consume services through the
OSGi registry. The following highlights show how a single bundle and the entire GreenPages
application can be integration tested outside the OSGi container.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1109"></a>Single Bundle Integration Test</h3></div></div></div><p>
One of the most common forms of integration testing is ensuring that the object relational mapping in an
application is working properly. This kind of testing typically uses a data access object to retrieve data
from a live database.
</p><p>
The <code class="classname">greenpages.jpa.JpaDirectorySpringContextTests</code> class in the
<code class="filename">src/test/java</code> source folder of the <code class="literal">greenpages.jpa</code> project
is such a test case for the <code class="classname">JpaDirectory</code> class.
The class uses JUnit to run the test and tests that a directory search completes
correctly. Rather than instantiate
this class directly in the test, the Spring Test Framework is used to instantiate and inject a
<code class="classname">JpaDirectory</code> bean defined in the <code class="literal">META-INF/spring/module-context.xml</code> file.
Spring Test Framework declarations are used to run the test with the
<code class="classname">SpringJunit4ClassRunner</code> and configure the test with the files
<code class="literal">classpath:/META-INF/spring/module-context.xml</code> and
<code class="literal">classpath:/META-INF/spring/test-context.xml</code>:
</p><pre class="programlisting">@RunWith(SpringJUnit4ClassRunner.<span class="hl-keyword">class</span>)
@ContextConfiguration(locations = { <span class="hl-string">"classpath:/META-INF/spring/module-context.xml"</span>,
<span class="hl-string">"classpath:/META-INF/spring/test-context.xml"</span> })
@TestExecutionListeners(value = DependencyInjectionTestExecutionListener.<span class="hl-keyword">class</span>)
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> JpaDirectorySpringContextTests {
@Autowired
<span class="hl-keyword">private</span> Directory directory;
@Test
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> search() {
</pre><p>
</p><p>
The <code class="filename">test-context.xml</code> file in the
<code class="literal">src/test/resources/META-INF/spring</code> folder defines two beans: a
<code class="interfacename">DataSource</code> and a <code class="classname">TestDataPopulator</code>:
</p><pre class="programlisting">&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"dataSource"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.apache.commons.dbcp.BasicDataSource"</span>
<span class="hl-attribute">p:driverClassName</span>=<span class="hl-value">"org.h2.Driver"</span> <span class="hl-attribute">p:url</span>=<span class="hl-value">"jdbc:h2:.~/greenpages-db/greenpages"</span>
<span class="hl-attribute">p:username</span>=<span class="hl-value">"greenpages"</span> <span class="hl-attribute">p:password</span>=<span class="hl-value">"pass"</span> <span class="hl-attribute">init-method</span>=<span class="hl-value">"createDataSource"</span>
<span class="hl-attribute">destroy-method</span>=<span class="hl-value">"close"</span> /&gt;
&lt;<span class="hl-tag">bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"greenpages.jpa.TestDataPopulator"</span> <span class="hl-attribute">init-method</span>=<span class="hl-value">"populate"</span>&gt;
&lt;<span class="hl-tag">constructor-arg</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"dataSource"</span> /&gt;
&lt;<span class="hl-tag">constructor-arg</span> <span class="hl-attribute">value</span>=<span class="hl-value">"file:../../db/db.sql"</span> /&gt;
&lt;<span class="hl-tag">/bean</span>&gt;
</pre><p>
These two beans provide a test <code class="interfacename">DataSource</code> complete with test data.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1166"></a>Multi Bundle Integration Test</h3></div></div></div><p>
The single bundle integration test provides a test implementation of its <code class="interfacename">DataSource</code> dependency.
When integration testing, it is often a good idea to test the entire application outside of the container.
GreenPages includes such a test case for the
entire application, starting with the <code class="classname">GreenPagesController</code> class
and descending all the way to a database.
Although it would be sensible for this test case to reside in a separate test bundle,
one of the bundles involved is a web bundle and so it is more convenient to locate the test case in the <code class="literal">greenpages.web</code> project.
</p><p>
Since this test case will be testing the GreenPages application as a whole, it needs to depend on the bundles
that make up the application.
The <code class="filename">pom.xml</code> file for the <code class="literal">greenpages.web</code>
project contains a dependency declaration for the <code class="literal">greenpages.jpa</code> bundle:
</p><pre class="programlisting">&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;com.springsource.dmserver&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.jpa&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;${project.version}&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">scope</span>&gt;test&lt;<span class="hl-tag">/scope</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
</pre><p>
Note that the scope of the dependency is <code class="literal">test</code>.
</p><p>
The <code class="classname">GreenPagesSpringContextTests</code> class in the
<code class="literal">src/test/java/greenpages/web</code> folder
contains Spring Test Framework declarations to run the test with the
<code class="classname">SpringJunit4ClassRunner</code> and configure the test with the files
<code class="literal">classpath*:/META-INF/spring/module-context.xml</code>,
<code class="literal">file:src/main/webapp/WEB-INF/greenpages-servlet.xml</code>, and
<code class="literal">classpath:/META-INF/spring/test-context.xml</code>. Note the use of
<code class="literal">classpath*:</code> which causes Spring to look for files that match the specified path in all of the bundles on the classpath.
</p><pre class="programlisting">@RunWith(SpringJUnit4ClassRunner.<span class="hl-keyword">class</span>)
@ContextConfiguration(locations = {
<span class="hl-string">"classpath*:/META-INF/spring/module-context.xml"</span>,
<span class="hl-string">"file:src/main/webapp/WEB-INF/greenpages-servlet.xml"</span>,
<span class="hl-string">"classpath:/META-INF/spring/test-context.xml"</span> })
@TestExecutionListeners(value = DependencyInjectionTestExecutionListener.<span class="hl-keyword">class</span>)
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> GreenPagesSpringContextTests {
</pre><p>
</p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="highlights.automated.build"></a>3.4&nbsp;Automated Build Highlights</h2></div></div></div><p>
Another important aspect of application development is automated build. This permits
application artifacts to be created outside of the developer&#8217;s IDE. The application can then be
created and tested in a variety of environments, including continuous integration servers.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1228"></a>Building the PAR</h3></div></div></div><p>
All of the GreenPages projects have Maven POM files for building.
The PAR is built using the file <code class="filename">pom.xml</code> in the <code class="literal">greenpages</code> folder.
This file defines a parent POM and a packaging type of <code class="literal">par</code>:
</p><pre class="programlisting">&lt;<span class="hl-tag">parent</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.parent&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;2.4.0.RELEASE&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">relativePath</span>&gt;../greenpages.parent&lt;<span class="hl-tag">/relativePath</span>&gt;
&lt;<span class="hl-tag">/parent</span>&gt;
&lt;<span class="hl-tag">modelVersion</span>&gt;4.0.0&lt;<span class="hl-tag">/modelVersion</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">name</span>&gt;GreenPages PAR&lt;<span class="hl-tag">/name</span>&gt;
&lt;<span class="hl-tag">description</span>&gt;GreenPages PAR&lt;<span class="hl-tag">/description</span>&gt;
&lt;<span class="hl-tag">packaging</span>&gt;par&lt;<span class="hl-tag">/packaging</span>&gt;
</pre><p>
</p><p>
Thorsten Maus created a Maven plugin (see <a class="xref" href="#further.resources.documentation" title="A.2&nbsp;Documentation">Section&nbsp;A.2, &#8220;Documentation&#8221;</a>)
that builds a PAR file from a list of dependencies.
The file <code class="filename">pom.xml</code> lists those dependencies:
</p><pre class="programlisting">&lt;<span class="hl-tag">dependencies</span>&gt;
&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.app&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;${project.version}&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.jpa&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;${project.version}&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.db&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;${project.version}&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.eclipse.virgo&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;greenpages.web&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;${project.version}&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">type</span>&gt;war&lt;<span class="hl-tag">/type</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
&lt;<span class="hl-tag">dependency</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.freemarker&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;com.springsource.freemarker&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">scope</span>&gt;provided&lt;<span class="hl-tag">/scope</span>&gt;
&lt;<span class="hl-tag">/dependency</span>&gt;
&lt;<span class="hl-tag">/dependencies</span>&gt;
</pre><p>
The freemarker dependency is required to ensure the Web Application Bundle has the correct set of dependencies.
Most dependencies are resolved
transitively from the bundle projects, but the &#8216;war&#8217; project does not pass on its dependencies;
it expects
them to be contained in its <code class="literal">lib</code> directory.
</p><p>
The <code class="literal">&lt;build&gt;&lt;plugins&gt;&#8230;</code> section contains a declaration for the
<code class="literal">par</code> plugin and configuration of the application symbolic name of the PAR:
</p><pre class="programlisting">&lt;<span class="hl-tag">plugin</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.apache.maven.plugins&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;maven-par-plugin&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;1.0.0.RELEASE&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">configuration</span>&gt;
&lt;<span class="hl-tag">applicationSymbolicName</span>&gt;greenpages&lt;<span class="hl-tag">/applicationSymbolicName</span>&gt;
&lt;<span class="hl-tag">/configuration</span>&gt;
&lt;<span class="hl-tag">/plugin</span>&gt;
</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1269"></a>Obtaining Dependencies</h3></div></div></div><p>
The Maven <code class="literal">dependency</code> plugin is used to collect the transitive dependency graph for the PAR.
</p><p>
The <code class="literal">&lt;build&gt;&lt;plugins&gt;&#8230;</code> section
has a declaration for the <code class="literal">dependency</code> plugin:
</p><pre class="programlisting">&lt;<span class="hl-tag">plugin</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.apache.maven.plugins&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;maven-dependency-plugin&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">executions</span>&gt;
&lt;<span class="hl-tag">execution</span>&gt;
&lt;<span class="hl-tag">id</span>&gt;copy-dependencies&lt;<span class="hl-tag">/id</span>&gt;
&lt;<span class="hl-tag">phase</span>&gt;package&lt;<span class="hl-tag">/phase</span>&gt;
&lt;<span class="hl-tag">goals</span>&gt;
&lt;<span class="hl-tag">goal</span>&gt;copy-dependencies&lt;<span class="hl-tag">/goal</span>&gt;
&lt;<span class="hl-tag">/goals</span>&gt;
&lt;<span class="hl-tag">configuration</span>&gt;
&lt;<span class="hl-tag">outputDirectory</span>&gt;${project.build.directory}/par-provided&lt;<span class="hl-tag">/outputDirectory</span>&gt;
&lt;<span class="hl-tag">overWriteIfNewer</span>&gt;true&lt;<span class="hl-tag">/overWriteIfNewer</span>&gt;
&lt;<span class="hl-tag">excludeGroupIds</span>&gt;org.eclipse.virgo,org.apache.log4j&lt;<span class="hl-tag">/excludeGroupIds</span>&gt;
&lt;<span class="hl-tag">/configuration</span>&gt;
&lt;<span class="hl-tag">/execution</span>&gt;
&lt;<span class="hl-tag">/executions</span>&gt;
&lt;<span class="hl-tag">/plugin</span>&gt;
</pre><p>
</p><p>
The WAB must be prevented from having its dependencies included in a <code class="literal">lib</code> directory as they should be provided
by the runtime enviroment. The <code class="literal">greenpages.web</code> POM file contains the following:
</p><pre class="programlisting">&lt;<span class="hl-tag">build</span>&gt;
&lt;<span class="hl-tag">plugins</span>&gt;
&lt;<span class="hl-tag">plugin</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;maven-war-plugin&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">version</span>&gt;2.1-beta-1&lt;<span class="hl-tag">/version</span>&gt;
&lt;<span class="hl-tag">configuration</span>&gt;
&lt;<span class="hl-tag">packagingExcludes</span>&gt;WEB-INF/lib/**&lt;<span class="hl-tag">/packagingExcludes</span>&gt;
&lt;<span class="hl-tag">/configuration</span>&gt;
&lt;<span class="hl-tag">/plugin</span>&gt;
&lt;<span class="hl-tag">/plugins</span>&gt;
&lt;<span class="hl-tag">/build</span>&gt;</pre><p>
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1299"></a>Automatically Running the Tests</h3></div></div></div><p>
The following plug-in entry in the <code class="literal">pom.xml</code> file in the <code class="literal">parent</code>
directory ensure that the concrete test classes are run as part of the build:
</p><pre class="programlisting">&lt;<span class="hl-tag">plugin</span>&gt;
&lt;<span class="hl-tag">groupId</span>&gt;org.apache.maven.plugins&lt;<span class="hl-tag">/groupId</span>&gt;
&lt;<span class="hl-tag">artifactId</span>&gt;maven-surefire-plugin&lt;<span class="hl-tag">/artifactId</span>&gt;
&lt;<span class="hl-tag">configuration</span>&gt;
&lt;<span class="hl-tag">includes</span>&gt;
&lt;<span class="hl-tag">include</span>&gt;**/*Tests.java&lt;<span class="hl-tag">/include</span>&gt;
&lt;<span class="hl-tag">/includes</span>&gt;
&lt;<span class="hl-tag">excludes</span>&gt;
&lt;<span class="hl-tag">exclude</span>&gt;**/Abstract*.java&lt;<span class="hl-tag">/exclude</span>&gt;
&lt;<span class="hl-tag">/excludes</span>&gt;
&lt;<span class="hl-tag">junitArtifactName</span>&gt;org.junit:com.springsource.org.junit&lt;<span class="hl-tag">/junitArtifactName</span>&gt;
&lt;<span class="hl-tag">argLine</span>&gt;-javaagent:${user.home}/.m2/repository/&#8230;&lt;<span class="hl-tag">/argLine</span>&gt;
&lt;<span class="hl-tag">/configuration</span>&gt;
&lt;<span class="hl-tag">/plugin</span>&gt;
</pre><p>
The location of the user's Maven repository is hard-coded.
</p></div></div></div><div class="appendix" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="further.resources"></a>Appendix&nbsp;A.&nbsp;Further Resources</h2></div></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further.resources.projects"></a>A.1&nbsp;Projects</h2></div></div></div><div class="orderedlist"><ol type="a"><li><p>Virgo
(<a class="ulink" href="http://www.eclipse.org/virgo" target="_top">http://www.eclipse.org/virgo</a>) &#8212; homepage for Virgo.</p></li><li><p>Bundlor
(<a class="ulink" href="http://www.springsource.org/bundlor" target="_top">http://www.springsource.org/bundlor</a>) &#8212; homepage for Bundlor manifest generation tool.
Note that Bundlor has been donated to Eclipse and may a development milestone be downloaded from
<a class="ulink" href="http://www.eclipse.org/virgo/download" target="_top">http://www.eclipse.org/virgo/download</a>.
</p></li><li><p>SpringSource.org
(<a class="ulink" href="http://www.springsource.org" target="_top">http://www.springsource.org</a>) &#8212; homepage for Spring Framework.</p></li><li><p>OSGi
(<a class="ulink" href="http://www.osgi.org" target="_top">http://www.osgi.org</a>) &#8212; homepage for OSGi.</p></li><li><p>H2 Database
(<a class="ulink" href="http://www.h2database.com" target="_top">http://www.h2database.com</a> &#8212; homepage for the H2 database.</p></li><li><p>FreeMarker
(<a class="ulink" href="http://freemarker.sourceforge.net" target="_top">http://freemarker.sourceforge.net</a>) &#8212; homepage for FreeMarker templating
engine.</p></li><li><p>Commons DBCP
(<a class="ulink" href="http://commons.apache.org/dbcp" target="_top">http://commons.apache.org/dbcp</a>) &#8212; homepage for Commons DBCP.</p></li><li><p>Eclipse IDE
(<a class="ulink" href="http://www.eclipse.org/eclipse" target="_top">http://www.eclipse.org/eclipse</a>) &#8212; homepage for Eclipse IDE.</p></li><li><p>EclipseLink
(<a class="ulink" href="http://www.eclipse.org/eclipselink" target="_top">http://www.eclipse.org/eclipselink</a>) &#8212; homepage for EclipseLink JPA.</p></li></ol></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="further.resources.documentation"></a>A.2&nbsp;Documentation</h2></div></div></div><div class="orderedlist"><ol type="a"><li><p>Virgo Virgo Tomcat Server Documentation
(<a class="ulink" href="http://www.eclipse.org/virgo/documentation" target="_top">http://www.eclipse.org/virgo/documentation</a>) &#8211; cover page for all Virgo documentation.
</p></li><li><p>Spring DM Reference Guide
(<a class="ulink" href="http://static.springsource.org/osgi/docs/1.2.0/reference/html/" target="_top">http://static.springsource.org/osgi/docs/1.2.0/reference/html/</a>).
</p></li><li><p>Spring Framework 3.0 documentation
(<a class="ulink" href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/" target="_top">http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/</a>).
</p></li><li><p>FreeMarker documentation
(<a class="ulink" href="http://freemarker.sourceforge.net/docs" target="_top">http://freemarker.sourceforge.net/docs</a>).</p></li><li><p>Eclipse IDE documentation
(<a class="ulink" href="http://www.eclipse.org/documentation" target="_top">http://www.eclipse.org/documentation</a>).</p></li><li><p>EclipseLink documentation wiki
(<a class="ulink" href="http://wiki.eclipse.org/EclipseLink/UserManual" target="_top">http://wiki.eclipse.org/EclipseLink/UserManual</a>).</p></li><li><p>Maven PAR plugin
(<a class="ulink" href="http://blog.springsource.com/2009/06/24/maven-par-plugin-100m1/" target="_top">http://blog.springsource.com/2009/06/24/maven-par-plugin-100m1/</a>).</p></li></ol></div></div></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--></body></html>