Before jumping into the example application, you might want to get your feet wet first by taking a closer look at the three technologies that will be used to create and deploy the application. (To read more about each of these technologies, see Resources for links.
Maven is an application for building Java applications, from source code to packaging to Web sites. The Geronimo application server was built using the Maven application's build system. At its core, Maven's extensible framework allows the creation of modules that perform several actions involved in building software components. Related to Apache Ant -- the Java build tool -- Maven's actions have been compared to the results generated by using the UNIX command make. Maven scripting also lets you automatically deploy your application into a running Geronimo server. This article shows how you can use Maven to package your source code into a full Java 2 Platform, Enterprise Edition (J2EE) enterprise application.
Struts is a Web application framework based on the Model 2 architecture (see Resources for a link to a good description of the JSP Model 2 architecture). This hybrid architecture separates business logic and display logic as much as possible. Struts accomplishes this by separating business logic into pure Java classes that do the work of manipulating your data, as well as providing a rich tag library that can be used to display the data when it's time to write JavaServer Pages (JSPs). (Of the myriad Web development frameworks available -- many with high acclaim, such as Tapestry and JavaServer Faces -- Struts continues to be one of my favorites.)
XDoclet has its roots in the long-time Java documentation tool, Javadoc. The developers of XDoclet originally used Javadoc in a novel way, using specialized comments to generate a model that can then be compiled into source code.They moved away from the actual use of Javadoc, producing their own variant called Xjavadoc. However, the use of tags in the Javadoc comments of your source code to produce automatically generated code still remains unchanged from the early days of XDoclet. Writing the source code and deployment descriptor files in a J2EE application can be tedious. For every one hundred or so lines of Java code, you can expect to generate at least three times as much supporting J2EE descriptor code to get the job done. To reduce much of the pain of developing a multitiered enterprise application, XDoclet comes to the rescue, providing code tagging and code generation so that the deployment descriptors are mostly generated automatically. This hides a lot of the complexity of J2EE, but be aware of what the code generator is building, because you'll have to read through it if things don't go as you expect.
As mentioned in the introduction, the Geronimo team uses Maven to build the entire application server. You can harness the power of the Maven build tool to compile your application source code, perform code generation (with the help of XDoclet), bundle your enterprise application modules, and finally deploy them to your running Geronimo server.
The process starts with three files. The first, project.xml, defines what is commonly referred to as the Project Object Model (POM). It lists the pertinent information about your application -- including the application name -- who's involved with writing it, its version number, the dependencies that are important to build the application, and a general statement of how to build the application. For the purposes of this article, you're mainly concerned with the dependencies section of the POM. (See Resources for a link to the entire POM file.)
Maven uses the dependencies section of project.xml to download the artifacts it needs to build an application from designated repositories on the Internet. One such repository, iBiblio (see Resources for a link), contains hundreds of open source Java libraries and supporting files, as well as POM information for those libraries. It has a wealth of information collected for the sole purpose of simplifying the Java developer's life during the application build process. The dependency section of the project.xml file for the phonebook application consists of 23 dependencies, half of these being .jar files needed to support Struts and the DisplayTag tag library. The rest of the dependencies are mainly XDoclet requirements. Without Maven, each of these dependencies would need to be bundled with the sample application.
Maven simply downloads all the dependent artifacts the first time the application is compiled. Subsequent compilation runs draw on Maven's local repository (a local cache of the downloaded artifacts usually found in a .maven directory of your $HOME directory) for the artifacts there.
Our example application requires some initial setup of Maven for everything to work correctly. First you need to install Maven 1.0.2 (see Resources for a link to the Maven Web site). After installation is complete, type maven at your command line. You'll see information similar to the following displayed:
E:\Documents and Settings\Neal\My Documents\eclipse\workspace\Phonebook> maven __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0.2 |
Next, compile Geronimo from source code following the instructions found on the Wiki (see Resources for a link). After a successful build, the Geronimo artifacts are in your local repository. They are required for building the sample application. After Geronimo is compiled, find and install the geronimo-deployment-plugin-1.0-SNAPSHOT.jar file into your $MAVEN_HOME/plugins directory; otherwise you may see a message like the following:
Tag library requested that is not present: 'geronimo:deploy' in plugin: 'null' |
Finally, install XDoclet 1.2.3 into your Maven repository. If, when trying to build the sample application, a Maven message appears stating that it can't find some of the other XDoclet 1.2.3 artifacts, you might need to download the XDoclet 1.2.3 (lib bundle) and extract the .jar files in your local Maven repository under .maven/repository/xdoclet/jars (see Resources for a link to the XDoclet Web site). If you're a Windows user, you should find this Maven directory under your C:\Documents and Settings\username directory. If you're a UNIX user, you should find this directory under your home directory. You should also install the XDoclet Maven plug-in by adding the maven-xdoclet-plugin-1.2.3.jar into your $MAVEN_HOME/plugins directory.
After you have these prerequisites in place, the build process should go smoothly. Of course, you can attempt the build before doing the above work and see which files Maven cannot find, and then install only those files. You can try running Maven inside the sample application's top directory. At first, many artifacts will be downloaded, and at the end, you'll see the BUILD SUCCESSFUL message.
To understand a little more about what Maven is doing, take a look at the maven.xml and project.properties files. Maven is goal oriented. It reads through maven.xml and attempts to satisfy all the goals specified in the default attribute of the top-level project element. In this case, it tries to satisfy everything that the deploy goal states as its prerequisites; namely, it will try to build the .ear file, then it tries to stop and start the application. The deployment of the application is performed by the Geronimo Deployment Maven plug-in mentioned earlier. Of course, your Geronimo server should be running -- otherwise your build will fail with a message similar to this:
Failed to retrieve RMIServer stub: javax.naming.ServiceUnavailableException
[Root exception is java.rmi.ConnectException: Connection refused to
host: 10.0.0.7; nested exception is:
java.net.ConnectException: Connection refused: connect]
|
If you receive this message, start your Geronimo server using a command like the following:
E:\geronimo-snapshot>java -jar bin\server.jar org/apache/geronimo/ DebugConsole org/apache/geronimo/RuntimeDeployer |
This command tells Geronimo to start its server, the DebugConsole application configuration, and the RuntimeDeployer configuration.
The DebugConsole (shown in Figure 1) is an optional component that lets you view what's running inside a Geronimo server through a small Web application (see http://localhost:8080/debug-tool).
Figure 1. The Geronimo DebugConsole

After you've built the example application, you can visit its top-level page where you'll see something much like Figure 2.
Figure 2. The Geronimo Phonebook example application built with Struts 1.2.7

Post application build: A look under the hood
Now that you've successfully built the application and have seen the power and simplicity of using Maven, it's time to take a look at the file layout and some of the code necessary to make it all happen. The Web application layer will be explained first, followed by the EJB layer. Finally you'll see the connective tissue -- the deployment plans and configuration files that tie everything together and make it all work. Refer to the file directory tree shown in Figure 3 as a reference to where you can find the files.
Figure 3. Directory layout of the sample application files

The Web application is written using JSPs and the Struts 1.2.7 framework. In the src/webapp directory you'll find the files that comprise the sample application's Web interface.
This application consists of two main views: the phone number list and the phone number edit screen. All the required features for editing simple records from a database (add, delete, edit, update, and list) are present. The src/java/org/acme/phonebook/struts directory contains a number of Struts actions that perform these required functions, such as creation of new entries, deletion of entries, listing all the entries, and editing existing entries.
The Struts Tiles template system was used to ensure that minimal effort was spent making the Web application look the way it does. The site-template.jsp file in the webapp/pages directory defines the look for the application.
The two main JSPs that will be explained are the EditPhoneNumberPage.jsp and the ListPhoneNumbersPage.jsp. Each of these pages and its function in the application is described in Listing 1.
Listing 1. EditPhoneNumberPage.jsp
<%@ page language="java"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles"%>
<tiles:insert page="/pages/site-template.jsp" flush="true">
<tiles:put name="content" type="string">
<hr>
<h1><bean:message key="h1.EditPhoneNumberPage" /></h1>
<hr>
<h2><bean:write name="phoneBookEntryForm" property="action"/>
</h2>
<html:form action="/pages/SaveEntry.do">
<table>
<tr>
<td>
<bean:message key="prompt.EditPhoneNumberPage.name" />
</td>
<td>
<html:text property="name" size="40" />
</td>
</tr>
<tr>
<td>
<bean:message key="prompt.EditPhoneNumberPage.phoneNumber" />
</td>
<td>
<html:text property="phoneNumber" size="40" /></td>
</tr>
<html:hidden property="action" />
<html:hidden property="pk" />
<tr>
<td></td>
<td>
<html:submit>
<bean:message key="button.submit" />
</html:submit> <html:reset>
<bean:message key="button.reset" />
</html:reset>
</td>
</tr>
</table>
</html:form>
</tiles:put>
</tiles:insert>
|
In Listing 1, the first few lines set up the tag libraries that will be active within the page. They also set up the content area of the site template as the location where the content will be displayed. This example shows a simple Struts-based entry form with some <bean:message> tags to show strings from a resource file (located in webapp/WEB-INF/classes/resources/application.properties). The form submits a name and a phone number to a Struts action called SaveEntry.do.
If you look at the class Javadoc tag in the SaveEntry.java source file in Listing 2, you'll see the first example of XDoclet tags in this application. These tags define all of the properties necessary to generate the Struts deployment descriptor, which is called struts-config.xml.
Listing 2.
SaveEntry.java JavaDoc class tag./** * Save an Entry * * @struts.action * name = "phoneBookEntryForm" * path = "/pages/SaveEntry" * scope = "request" * input = "/pages/EditPhoneNumberPage.jsp" * unknown = "false" * validate = "false" * @struts.action-forward * name = "success" * path = "/pages/ListNumbers.do" * redirect = "true" */ |
This code sample, in a nutshell, demonstrates that this action, called /pages/SaveEntry, takes its input from the EditPhoneNumberPage.jsp and uses a phoneBookEntryForm to marshal the user's input from the page to the Java code. After the action is complete, it redirects to the /pages/ListNumbers action to display the number list.
The ListNumbers action, which you can find in the ListNumbers.java file, makes a call to the Session EJB, called PhoneBookSession, using the code in Listing 3.
Listing 3. Excerpt of the
execute() method of the ListNumbers action.
PhoneBookSessionLocal session =
PhoneBookSessionUtil.getLocalHome().create();
// Call the method
Collection c = session.listEntries();
// Put the retrieved information into the request attributes
// so the page can render them.
request.setAttribute("numbers", c);
|
As shown in Listing 3, you can see the use of a PhoneBookSessionUtil class. This is an XDoclet-generated class that helps with getting the home interfaces of the PhoneBookSession object. A session is created and its listEntries() method is called, which returns a collection of all the phone book entries. Then the numbers attribute in the request object is set to that collection. This has the effect of putting the phone numbers into a named location that the JSP page that is used to display the entries can retrieve and use to write out the list, as shown in Listing 4.
Listing 4. Display Tag in
ListPhoneNumbersPage.jsp
<display:table name="numbers" requestURI="ListNumbers.do"
scope="request" pagesize="5" id="row_obj">
<display:column property="name" title="Name"/>
<display:column property="phoneNumber" title="Phone"/>
<display:column title="Actions">
<logic:present name="row_obj">
<html:link action="/pages/EditEntry"
paramId="id" paramName="row_obj"
paramProperty="name">Edit</html:link>
<html:link action="/pages/DeleteEntry"
paramId="id" paramName="row_obj"
paramProperty="name"
onclick="return confirmDelete('Number')">
Delete
</html:link>
</logic:present>
</display:column>
...
</display:table>
|
There are two EJB classes in this application. The first one, which uses Container-Managed Persistence (CMP) to provide object-based access to a simple database table, is called PhoneBookEntryBean. The second class is a stateless session bean, which provides the business logic. Often it's desirable to manipulate CMP beans through a stateless session bean, because session beans can be set up to provide transactions on the database so that updates can be rolled back in the event of an error. Also, performing all CMP operations in a session bean shields the Web application from having to know any of the implementation details of the database access layer. So if replacement of that layer with another technology occurs (such as using a Hibernate persistence layer), the code in the Web application won't need to be changed.
XDoclet is used heavily in the EJB layer to provide the deployment descriptor generation. This is important to reduce the maintenance effort required to build this type of application. Download the source code and look at the class Javadoc comments for both PhoneBookEntryBean.java and PhoneBookSessionBean.java to see many of the XDoclet tags used to define EJB classes.
To generate a method on the stateless session bean, it's sufficient to add an XDoclet tag, called @ejb.interface-method, with a view-type property of local, remote, or both. This tells XDoclet to generate the appropriate methods in the local interface, remote interface, or both interfaces for the session bean. You can also control the transaction type. See Listing 5 for an example of one of the interface methods for listing phonebook entries and returning their value object representations.
Listing 5.
listEntries() method of the PhoneBookSessionBean.java class
/**
* List all of the phone book entries.
* @return a collection of PhoneBookEntryValue objects.
*
* @ejb.interface-method view-type="both"
* @ejb.transaction type="Required"
*/
public java.util.Collection listEntries() {
ArrayList values = new ArrayList();
try {
Collection entries = PhoneBookEntryUtil.getLocalHome().findAll();
Iterator i = entries.iterator();
while(i.hasNext()) {
PhoneBookEntryLocal entry = (PhoneBookEntryLocal)i.next();
values.add(entry.getPhoneBookEntryValue());
}
} catch (Throwable ex) {
ex.printStackTrace();
}
return values;
}
|
In my previous article, "Three ways to connect a database to a Geronimo application server" (developerWorks, June 2005), the importance of Geronimo's various deployment plans was explained in detail. Getting this small application to a functional state was very challenging and required many small options to be present within the deployment plans, as well as interactions between XDoclet tags, the code the tags generate, and the deployment plans. Going through the details, however, is beyond the scope of this article. The example program has many configuration files and deployment plans, nearly all of which are found in the src/resources subtree of the project. The following paragraphs briefly describe the pertinent details of these files to show where you'd need to make modifications to get future applications working.
The ear subdirectory contains the enterprise application deployment descriptors, the application.xml file, and the geronimo-application.xml file. In this application, these files are configured to provide an application-scoped Java Database Connectivity (JDBC) connector. Read "Three ways to connect a database to a Geronimo application server" (developerWorks, June 2005) for details on doing that. The mysql-plan.xml and tranql-connector-1.0-SNAPSHOT.rar files are part of this configuration, as well as module definitions in both the application.xml and geronimo-application.xml files, to cause the runtime deployer to set up the JDBC connector properly.
The geronimo-application.xml file contains an <application> element that has an attribute called configId. This element is essential to the correct operation of the automatic deployment feature of the Maven build script. The value this is set to can be used in the id attribute of any <deploy:*> tags in the maven.xml file, as shown in Listing 6.
Listing 6.
maven.xml start goal.
<goal name="start">
<deploy:distribute
uri="deployer:geronimo:jmx:rmi://localhost/jndi/rmi:/JMXConnector"
username="system"
password="manager"
home="${basedir}"
module="target/${pom.artifactId}.ear"
/>
<deploy:start
uri="deployer:geronimo:jmx:rmi://localhost/jndi/rmi:/JMXConnector"
username="system"
password="manager"
id="org/acme/PhoneBook"/>
</goal>
|
In Listing 6, because the configId attribute in the geronimo-application.xml file is set to org/acme/PhoneBook, it must also be the value of the id attributes in the automatic deployment statements. The Geronimo team has designed a nice, automated deployment facility here. However, if you often deploy automatically, make sure to check your temp directories, because they could be filling up with old deployment files.
Next in our list of subdirectories, in the resources directory, is the ejb directory. Inside the META-INF subdirectory is the openejb-jar.xml deployment descriptor. This file is essential for making all the linkages between your database and your entity (CMP) beans. It's also necessary to make small modifications to this file to ensure appropriate Java Naming and Directory Interface (JNDI) names are present for your enterprise beans. This file is shown in Listing 7.
Listing 7. openejb-jar.xml
<?xml version="1.0"?>
<openejb-jar
xmlns="http://www.openejb.org/xml/ns/openejb-jar"
configId="org/acme/PhonebookEJB"
parentId="MysqlDatabase">
<cmp-connection-factory>
<resource-link>MysqlDataSource</resource-link>
</cmp-connection-factory>
<enterprise-beans>
<entity>
<ejb-name>PhoneBookEntry</ejb-name>
<local-jndi-name>
java:comp/env/ejb/PhoneBookEntryLocal
</local-jndi-name>
<table-name>phone</table-name>
<cmp-field-mapping>
<cmp-field-name>name</cmp-field-name>
<table-column>name</table-column>
</cmp-field-mapping>
<cmp-field-mapping>
<cmp-field-name>phoneNumber</cmp-field-name>
<table-column>phone</table-column>
</cmp-field-mapping>
</entity>
<session>
<ejb-name>PhoneBookSession</ejb-name>
<local-jndi-name>
java:comp/env/ejb/PhoneBookSessionLocal
</local-jndi-name>
</session>
</enterprise-beans>
</openejb-jar>
|
The most important element of Listing 7 is <cmp-connection-factory> and its <resource-link> subelement. The name inside the <resource-link> element must match the name of the JDBC connector configuration, as shown in the following excerpt:
...
<connectiondefinition-instance>
<name>MysqlDataSource</name>
...
|
The <local-jndi-name> elements in the openejb-jar.xml elements are also essential to get things to work. If you receive errors about JNDI names not being found, you've probably set one of these elements incorrectly.
Also of note in Listing 7 are the <table-name> and <table-column> elements for your entity beans, where you must configure which database tables and columns map to the entity bean fields. See the <cmp-field-mapping> elements in Listing 7 for two examples of doing this.
The last directory is the src/resources directory named merge. The contents of this directory relate directly to the way XDoclet code generation is performed. XDoclet takes information from Javadoc tags, but it also merges information in specially named files inside a merge directory. These merge files contain some of the configuration information for the Web application layer. In the src/resources/merge directory of the project, the taglibs.xml file allows all the tag libraries in the application to be defined. There are also many of the files that are merged into web.xml and struts-config.xml when XDoclet generates them.
Another deployment plan exists in the src/webapp/WEB-INF/geronimo-jetty.xml file shown in Listing 8.
Listing 8. geronimo-jetty.xml
<?xml version="1.0"?>
<web-app
xmlns="http://geronimo.apache.org/xml/ns/web/jetty"
xmlns:naming="http://geronimo.apache.org/xml/ns/naming"
configId="org/acme/PhoneBookWeb"
>
<context-priority-classloader>true</context-priority-classloader>
</web-app>
|
This deployment plan, shown in Listing 8, has one important line in it. Without the <context-priority-classloader> element set to true, the Struts application is unable to run because of conflicts in the classes available in the Geronimo library. Setting this value to true tells Geronimo to use standard Web application scoping when looking up classes. This means that the application is insulated from any other applications running in the server. But it also means that any classes the application needs must be bundled with the application.
All of the bundling of .jar components that the application depends on are specified in the project.xml dependencies section and are handled automatically by Maven.
The final configuration file, named project.properties, drives much of the build process and is located in the root directory of the project. This file is a storehouse of XDoclet-related information and information about what to include inside .war files, and even properties that control the Java compiler output formats.
Putting all of these elements together takes a lot of time, but hopefully you'll be able to use this example application as a stepping stone along your way.
This article provides a very basic starting template for a much larger application. In adding more CMP beans and session beans for business logic, you can create a more interesting Web application. I've demonstrated the definite benefits of the Maven build system for reducing the complexity of compiling and producing the nested file structure of the final .ear file. The XDoclet code-generation system was also used to simplify the process of generating the EJB artifacts, the Struts artifacts, and the Web application artifacts necessary for compiling the final phonebook application. Using this sample application, you should now be able to take advantage of Maven and XDoclet to simplify your enterprise application development process.
Geronimo developers have carefully crafted the server itself, following the Sun J2EE specifications, and have produced a product that clearly separates deployment and configuration issues from the details necessary for the container to host the application.
| Description | Name | Size | Download method |
|---|---|---|---|
| Source code for the example phonebook application | GeronimoPhonebook2.zip | 128 KB | HTTP |
Information about download methods
Learn
- Neal's developerWorks article, "Three ways to connect a database to a Geronimo application server (developerWorks, June 2005).
- Learn more about JSP Model 2 architecture.
- See Apache's Web site for information, documentation, and downloads for Maven and the Struts framework.
- Take a look at the Maven Repository Search.
- See the official XDoclet Web site.
- Visit the SourceForge site for access to the XDoclet EJB tag documentation.
- Access the Apache site for links to the entire POM file.
- The Geronimo Wiki gives you information for compiling Geronimo from source code.
- Visit the iBiblio repository.
- Get information on the DisplayTag JSP tag library.
- Visit the official Apache Geronimo Web page for documentation, news, and download information.
- Read the two-part series on Geronimo: Part 1, "The J2EE 1.4 engine that could," is an introduction and conceptual overview to Geronimo. Part 2, "Tame this J2EE 1.4 bronco," covers Geronimo configuration, deployment, management, and provides hands-on examples of deploying Web applications and EJBs (developerWorks, May 2005).
- Visit the official Geronimo project site to access the latest source code, binaries, and an active community on the mailing lists and wiki.
- See the Apache Geronimo project area for a complete listing of free open source resources from developerWorks.
- Browse all the Apache articles and free Apache tutorials available in the developerWorks Open source area.
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
Get products and technologies
- Geronimo uses Apache Maven to manage project builds. Version control for most projects is managed using Subversion.
- Visit The DisplayTag JSP Tag Web page for documentation and download information about the display tag library.
- Download Gluecode Standard Edition, an open source application server based on Apache Geronimo.
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
Discuss
- Participate in the discussion forum.
- Get involved in the developerWorks community by participating in developerWorks blogs.
Neal Sanche is a Java developer recently beached in the Microsoft® .NET world and fighting for any ties back to his old, comfortable roots. His experience includes development of several commercial J2EE applications, as well as several stand-alone Java applications. In his spare time, he writes music, takes photographs, and writes technical articles. See several examples at his Web site. Contact Neal at neal@nsdev.org.




