Start developing and deploying J2EE apps on Apache's open source J2EE server The ambitious Apache Geronimo project has been going full-steam for more than a year now and has recently made its third milestone release. If you haven’t checked it out yet, this article will help you get started. We’ll download and install Geronimo, review some of its architecture, and go through a couple of sample J2EE applications. Although no date has been set for the official release, its list of stated goals is indeed impressive:Pass Sun Microsystems’ J2EE 1.4 certificationReuse as much existing ASF (Apache Server Foundation) code as possibleIntegrate technology outside of ASF within Geronimo, most notably OpenEJB and ActiveMQ from codehaus.orgGeronimo is a J2EE server, which means it includes all the containers required by the J2EE 1.4 specification (but, thanks to smart thinking, is backwards compatible to earlier versions). Wherever possible, Geronimo uses existing open source products. Some of these are: Servlet container services: Jetty and TomcatEnterprise JavaBean container: OpenEJBJava Message Service (JMS) provider: ActiveMQDatabase connection pooling: TranQLTransaction support: HOWL (High-speed ObjectWeb Logger)Database: Axion, DerbyJava Management Extensions (JMX) support: MX4JEach service is implemented by a core object called a GBean. Much work went into the design of these GBeans so the core server could manage their entire lifecycles without manual intervention.Geronimo and JBoss Geronimo has also had to deal with some legal noise from JBoss, who alleges similarities between the Geronimo and JBoss codebases. It appears as if the ASF has successfully repudiated these allegations, but as yet, JBoss has not acquiesced. If nothing else, this situation means the project is being carefully watched by its competitors! Build and install GeronimoAlthough the Geronimo team makes milestone releases available (the current one is M3), I recommend using the latest source and building Geronimo yourself. While building from source can be time consuming, you will need the latest source to get the examples in this article to work. (I did my best to get them running on M3, but alas, they wouldn’t all work.) To build Geronimo, you need three things: the Subversion version control system client, Apache Maven, and the Geronimo source code. I assume you have downloaded and installed the first two per their instructions. Now, with both the Subversion client and the Maven executable in your PATH, you can build Geronimo.First, you need to download Geronimo. To do that, type this Subversion command: svn checkout http://svn.apache.org/repos/asf/geronimo/trunk geronimo This command creates a directory called geronimo, which contains the Geronimo source code, in the directory where you are currently located. Now, change into the geronimo directory and do the build: cd geronimo maven -Dmaven.test.skip=true -Dmaven.itest-skip=true m:rebuild-all The two system properties tell Maven to ignore all the tests and just do a straight build. While the Geronimo build instructions tell you to build without them, I couldn’t get Geronimo built without some tests failing. Thankfully, however, whatever failed did not affect this article’s examples.If this is your first time executing Maven, you may have to wait a bit. On one of my Windows XP machines with an ISDN connection, execution took an hour and a half! But chances are your time will be considerably less. Still, find a good movie to watch while you wait. Eventually, the build will complete—hopefully with success. If it showed a failure, you’ll have to wait until the next day and hope whatever was broken has been fixed. Or join one of the Geronimo lists and let the team know about your problems.In the source code tree, you will find the build files in the modules/assembly/target/geronimo-1.0-SNAPSHOT subdirectory. Rather than remembering all that, create a symbolic link somewhere convenient. In my case, I did: cd ~/build/ext ln -s geronimo/modules/assembly/target/geronimo-1.0-SNAPSHOT geronimo-latest >From now on, I’ll refer to this Geronimo installation directory as $GERONIMO_HOME. Create a sample Web applicationCurrently, Geronimo does not come with much in the way of demo or default applications. So let us start with the first of a series of sample applications we will build for this article. Find a development space somewhere (mine is in ~/devel/test), and create a directory called gtest. I’ll refer to this directory as $GERONIMO_DEVEL. Within this directory, create the following directories: etc src web Our first project is just a simple Web application. For this, we need three files. First, we need a simple JSP (JavaServer Pages) page, index.jsp, which we put in the web directory: <%@ page language="java" import="java.util.Date" %> <html> <head> <title>Geronimo Test Application</title> <style type="text/css"> <!-- a { text-decoration: none } body { font-family: verdana, helvetica, sans serif; font-size: 10pt; } td { font-family: verdana, helvetica, sans serif; font-size: 10pt; } p { font-family: verdana, helvetica, sans serif; font-size: 10pt; } ul { font-family: verdana, helvetica, sans serif; font-size: 10pt; } h3 { font-family: verdana, helvetica, sans serif; font-size: 12pt; font-weight: bold; color: #547180; } --> </style> </head> <body> <center><h3>Geronimo Test Application</h3> <table class="legacyTable" width="50%"><tr><td> Welcome to Geronimo. Today is <%=(new Date())%>. This is a J2EE application running inside of Geronimo. Here are some things you can try <ul> <li>Test a simple EJB</li> <li>Test a JDBC connection pool</li> </ul> </td></tr></table> </center> </body> </html> Second, we need a Web application descriptor, web.xml, which goes in the etc directory: <?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app id="GeronimoTestWebApp"> <display-name>GeronimoTestWebApp</display-name> </web-app> Note the id attribute in the <web-app> tag. This gives Geronimo a name for your application. (If you don’t supply the name, Geronimo will try to use the value of the <display-name> tag.) Without a name—technically a configuration id—Geronimo can’t deploy the application.DTDs and XML schemas I purposely use the Servlet 2.3 specification document type definition for my web.xml to keep things as simple as possible. Geronimo supports not only DTDs, but also the newer XML schemas as used in the J2EE 1.4 specification. As I imagine many of you have spent much of your time developing against the 1.3 specification, it is nice to know you don’t have to update all your descriptor files to run on Geronimo. Finally, we need an Ant build file. If you don’t have Ant installed, you can download it from Resources. Once you install it, make sure the bin directory in the Ant installation directory is in your PATH. This is the build file we’ll use. It is called build.xml and goes right in $GERONIMO_DEVEL: <project default="build" basedir="."> <property name="ghome" value="${user.home}/devel/build/ext/geronimo-latest"/> <path id="cp"> <pathelement path="${java.class.path}"/> <fileset dir="${ghome}/repository/geronimo-spec/jars"> <include name="*.jar"/> </fileset> </path> <target name="prepare"> <mkdir dir="dist"/> <mkdir dir="classes"/> <mkdir dir="build"/> <delete> <fileset dir="classes" includes="**/*.class"/> </delete> <mkdir dir="build/WEB-INF"/> <mkdir dir="build/WEB-INF/lib"/> <copy file="etc/web.xml" todir="build/WEB-INF"/> <copy file="etc/geronimo-jetty.xml" todir="build/WEB-INF" failonerror="false"/> <copy todir="build"> <fileset dir="web"/> </copy> </target> <target name="compile" depends="prepare"> <javac srcdir="src" destdir="classes" debug="on" optimize="off" deprecation="off"> <classpath refid="cp"/> </javac> </target> <target name="jar" depends="compile"> <jar jarfile="build/WEB-INF/lib/gtest-ejbs.jar"> <fileset dir="classes" includes="**/*.class"/> <metainf dir="etc" includes="ejb-jar.xml,openejb-jar.xml"/> </jar> </target> <target name="war" depends="jar"> <war destfile="dist/gtest.war" webxml="build/WEB-INF/web.xml"> <fileset dir="build"> <exclude name="WEB-INF/web.xml"/> </fileset> </war> </target> <target name="ear" depends="war"> <copy todir="dist" file="build/WEB-INF/lib/gtest-ejbs.jar"/> <ear destfile="dist/gtest.ear" appxml="etc/application.xml"> <fileset dir="dist" includes="*.war,*.jar"/> </ear> </target> </project> As you can see, this build file contains commands to build not just our Web application, but also our J2EE application. You will have to edit the one <property> tag at the top of the build file for your purposes. Make sure it points to the Geronimo binary installation directory. In my case, it points to the symbolic link I just created. For now, we want only a simple war file. So, type the following (make sure you are in $GERONIMO_DEVEL): ant war This command creates a file called gtest.war in the dist subdirectory. It should not produce an error, since no compilation is involved.Run the Web applicationFinally we can fire up Geronimo! We need two terminal or command windows to do this. In one, go to $GERONIMO_HOME and type: java -jar bin/server.jar You’ll see a bunch of messages spilling onto your screen eventually followed by the message Server startup completed. This tells you Geronimo is now running. If you want to stop the server, just hit Ctrl-C. (Yes, I too am hoping a more elegant stop mechanism is coming!) You might only encounter problems if you have a servlet container (like Tomcat) running on port 8080 or an RMI (remote method invocation) server running on port 1099. These are both ports that Geronimo uses, and it can’t start if they are in use.In the second terminal or command window, also go to $GERONIMO_HOME. We now install our Web application. This command is: java -jar bin/deployer.jar --user system --password manager deploy $GERONIMO_DEVEL/dist/gtest.war This command requires some explanation. First of all, we are using the Geronimo deployer, which has many deployment commands: deploy: Install and start a componentdistribute: Install a componentlist-modules: List installed modulesredeploy: Redeploy an already installed componentstart: Start a componentstop: Stop a componentundeploy: Stop and uninstall a componentThe deploy command we use is essentially the combination of the distribute and start commands.When you use the deployer, you must provide an administration login, which we do on the command line. If you don’t supply it there, the deployer will ask you for it. The login I use here comes with Geronimo by default. What is really cool about Geronimo is that you don’t have to specify the kind of component you are installing: the deployer figures it out. In our first use of this tool, we just give it our .war file and the deployer will deploy the file as a Web application.Once you run the deploy command, you should receive the response: Deployed GeronimoTestWebApp Go back to your first terminal window and check out the message that just popped up: 07:16:59,814 INFO [LocalConfigStore:config-store] Installed configuration GeronimoTestWebApp in location 26 07:16:59,929 INFO [ConfigurationManagerImpl] Loaded Configuration geronimo.config:name="GeronimoTestWebApp" 07:17:00,053 INFO [Configuration] Started configuration GeronimoTestWebApp 07:17:00,471 INFO [Container] Started org.mortbay.jetty.servlet.WebApplicationHandler@1cd022c 07:17:00,472 INFO [GeronimoTestWebApp] JSR154 unwrappedDispatchSupported=true 07:17:00,477 INFO [JettyWebAppContext] JettyWebAppContext started 07:17:00,478 INFO [Container] Started WebApplicationContext[/GeronimoTestWebApp,GeronimoTestWebApp] This message says that Geronimo has deployed the application, or configuration, called GeronimoTestWebApp. Geronimo has installed it in a numbered location—26 in this example, but yours will differ. It then tells us that the Web application has started in Jetty and is available under the URI-base of /GeronimoTestWebApp.After all this work, it is time to be rewarded with some output! Point your browser to http://[server]:8080/GeronimoTestWebApp where “[server]” refers to the machine on which you installed Geronimo. Figure 1 shows the output I received: Before we move on, let’s talk more about the config-store message. In $GERONIMO_HOME, you’ll see a config-store directory, which contains some numbered directories and a file called index.properties. Open that file. You’ll see a list of the configurations (or components, or applications) running in your Geronimo installation. Each configuration has a number. If this is a brand-new Geronimo installation, you should have about 13 system configurations and one for our test application, GeronimoTestWebApp. Find the number for the latter and then look at its directory: $GERONIMO_HOME/config-store/<number>. In my case, I’m looking at $GERONIMO_HOME/config-store/27. What you find inside are your deployment files: config-store/27/META-INF config-store/27/war config-store/27/war/index.jsp config-store/27/war/META-INF config-store/27/war/WEB-INF config-store/27/war/WEB-INF/web.xml config-store/27/war/WEB-INF/lib Again, make sure you replace 27 with your GeronimoTestWebApp’s configuration number.I’m explaining the config-store directory for only one reason: it tells you where to find your deployment files. It is not, I repeat NOT, a place to make any edits. Geronimo can and will overwrite things, so any changes you make will eventually get lost. You should treat the directories under $GERONIMO_HOME/config-store as read-only for humans. Geronimo directories For the record, I should at least mention the other Geronimo directories. Currently, under $GERONIMO_HOME, you’ll find the following:bin: The executable JARsconfig-store: The configuration repository, just mentionedlib: Contains the core Geronimo librariesrepository: Holds shared librariesschema: Contains J2EE descriptor schemasvar: Miscellaneous directory containing runtime-related stuff; includes subdirectories for logs, transaction logs, authentication files, etc. Adding database connectivityMany Web applications need some sort of database connectivity, and this section shows you how to get a connection pool running in Geronimo. Geronimo comes with connection pool manager TranQL. You only need to supply your database’s JDBC (Java Database Connectivity) JAR and a pool descriptor.In this example, I use MySQL and its JDBC JAR named mysql-connector-java-3.0.9-stable-bin.jar. Your JAR’s name will probably differ, so make sure to make a note of it. Our first task is to create a directory for the MySQL JAR in $GERONIMO_HOME. Geronimo keeps all shared JARs in the repository directory. So, we do the following: cd $GERONIMO_HOME mkdir -p repository/mysql/jars cp [path-to-jdbc-jar] repository/mysql/jars Now we need to tell Geronimo about the connection pool we want. One thing I haven’t covered yet is a deployment plan, an XML descriptor file that tells Geronimo information about the component. You don’t always have to use one—we didn’t before—but sometimes it is necessary. Adding a connection pool to Geronimo is one such time. And this is the deployment file we need: <?xml version="1.0"?> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector" version="1.5" configId="MySQLPool" parentId="org/apache/geronimo/Server"> <dependency> <uri>mysql/jars/mysql-connector-java-3.0.9-stable-bin.jar</uri> </dependency> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface> javax.sql.DataSource </connectionfactory-interface> <connectiondefinition-instance> <name>MysqlDataSource</name> <config-property-setting name="UserName"> root </config-property-setting> <config-property-setting name="Password"> [your-password] </config-property-setting> </config-property-setting> <config-property-setting name="Driver"> org.gjt.mm.mysql.Driver </config-property-setting> <config-property-setting name="ConnectionURL"> jdbc:mysql://localhost:3306/test?autoReconnect=true </config-property-setting> <connectionmanager> <single-pool> <max-size>10</max-size> <min-size>2</min-size> <match-one/> </single-pool> </connectionmanager> <global-jndi-name>MySQLPool</global-jndi-name> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector> You must modify this somewhat, of course, specifically the username, password, and URL. The most important setting here is the <name> tag in the <connectiondefinition-instance> block, which is required in our Web application configuration. Note too that we specify the JDBC jar file as a dependency for this pool—if the JAR is missing, Geronimo will complain.And finally, note the configId attribute in the <connector> tag. This serves as this connection pool’s name within Geronimo, not to be confused with its JNDI (Java Naming and Directory Interface) name.Save this file somewhere as mysql-plan.xml. To deploy the connection pool, we use the resource adapter provided by TranQL and included in Geronimo: java -jar bin/deployer.jar --user system --password manager deploy repository/tranql/rars/tranql-connector-1.0-SNAPSHOT.rar ~/devel/test/gtest1/etc/mysql-plan.xml As long as your syntax is correct, Geronimo will reply: Deployed MySQLPool Just to verify that the pool is active, you can type the following: java -jar bin/deployer.jar --user system --password manager list-modules A sample output is shown in Figure 2. Here you can see that the MySQLPool component is really there, along with our Web applications and a bunch of system components.To use our new pool, we must complete three tasks:Update our application’s web.xmlAdd a Geronimo-specific Web application descriptor, geronimo-jetty.xmlCreate a new JSP pageThe new web.xml is shown below. It differs from our previous file in that we use the XML Schema definition for the Java 2.4 Servlet Specification. We also define the javax.sql.DataSource reference that our code will use: <?xml version="1.0"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>GeronimoTestWebApp</display-name> <resource-ref> <res-ref-name>jdbc/DataSource</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> </web-app> The <resource-ref> block tells Geronimo that our application needs a JNDI resource called jdbc/DataSource. To map this resource to the connection pool we just created, we need a Geronimo-specific (actually, Jetty-specific) Web application descriptor file. We call this file geronimo-jetty.xml and put it in the $GERONIMO_DEVEL/etc directory: <?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="GeronimoTestWebApp" parentId="org/apache/geronimo/Server"> <context-root>/GeronimoTestWebApp</context-root> <context-priority-classloader>false</context-priority-classloader> <naming:resource-ref> <naming:ref-name>jdbc/DataSource</naming:ref-name> <naming:resource-link>MysqlDataSource</naming:resource-link> </naming:resource-ref> </web-app> Remember the <name> tag from our connection pool descriptor? This is where it comes into play, as we map the local JNDI resource name jdbc/DataSource to the connection pool named MysqlDataSource. Note too that this descriptor labels the Web application using the <web-app> tag’s configId attribute. In addition, a parentId attribute defines the component under which this application will be placed. The value I use here, org/apache/geronimo/Server, can be considered the server’s “root.”Lastly, we need a simple JSP page to test our connection. Save this as $GERONIMO_DEVEL/web/dbtest.jsp: <html> <head> <title>Geronimo Test Application</title> <style type="text/css"> <!-- a { text-decoration: none } body { font-family: verdana, helvetica, sans serif; font-size: 10pt; } td { font-family: verdana, helvetica, sans serif; font-size: 10pt; } p { font-family: verdana, helvetica, sans serif; font-size: 10pt; } ul { font-family: verdana, helvetica, sans serif; font-size: 10pt; } h3 { font-family: verdana, helvetica, sans serif; font-size: 12pt; font-weig ht: bold; color: #547180; } --> </style> </head> <body> <center><h3>Geronimo Test Application - database test</h3> <% Connection conn = null; Statement stmt = null; ResultSet rs = null; try { out.println("<table class="legacyTable" border="1">"); Context ctx = new InitialContext(); Context envCtx = (Context)ctx.lookup("java:comp/env"); DataSource ds = (DataSource)envCtx.lookup("jdbc/DataSource"); conn = ds.getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery("select * from Test"); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); for (int i = 1; i <= cols; i++) { out.println("<td align="center"><b>" + rsmd.getColumnName(i) + "</b></td>"); } while (rs.next()) { out.println("<tr>"); for (int i = 1; i <= cols; i++) { out.println("<td align="left">" + rs.getString(i) + "</td>"); } out.println("</tr>"); } out.println("</table>"); conn.close(); } catch (Exception e) { out.println("" + e.toString() + ""); } finally { if (rs != null) try { rs.close(); } catch (Exception e) { } if (stmt != null) try { stmt.close(); } catch (Exception e) { } if (conn != null) try { conn.close(); } catch (Exception e) { } } %> </center> </body> </html> You’ll need to substitute your own SQL statement for this test.Let’s build and deploy our new application: cd $GERONIMO_DEVEL ant war cd $GERONIMO_HOME java -jar bin/deployer.jar --user system --password manager undeploy GeronimoTestWebApp java -jar bin/deployer.jar --user system --password manager deploy $GERONIMO_DEVEL/dist/gtest.war Notice that to redeploy our application, we first undeploy it by name and then redeploy just as we did before. Now we can test by pointing our browser to http://[server]:8080/GeronimoTestWebApp/dbtest.jsp. Figure 3 shows my results.Test a simple EJBFor our final example, we create a full-blown J2EE Web application with a simple EJB component. Our work involves building on our existing application as follows:Create the EJB filesCreate an EJB descriptor file, ejb-jar.xmlCreate an OpenEJB-specific descriptor file, openejb-jar.xmlCreate an application descriptor, application.xmlCreate a test JSP pageEdit the Web application descriptor, web.xmlI know this looks like a bunch of work, but it really is pretty straightforward. Let’s start with our EJB components. We need three files for a simple entity bean example, and they all go in $GERONIMO_DEVEL‘s src directory. The first file, DateBean.java, is for the bean itself: package test.ejb; public class DateBean implements javax.ejb.SessionBean { public void ejbCreate() { } public void ejbRemove() { } public void ejbActivate() { } public void ejbPassivate() { } public void setSessionContext(javax.ejb.SessionContext ctx) { } public String getDate() { return new java.util.Date().toString(); } } The next file, DateHome, defines the bean’s home interface: package test.ejb; public interface DateHome extends javax.ejb.EJBHome { DateRemote create() throws java.rmi.RemoteException, javax.ejb.CreateException; } The last file, DateRemote, defines the bean’s remote interface: package test.ejb; public interface DateRemote extends javax.ejb.EJBObject { public String getDate() throws java.rmi.RemoteException; } Next, we create the EJB descriptor file: $GERONIMO_DEVEL/etc/ejb-jar.xml: <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2. 0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <description>Geronimo EJB Test</description> <enterprise-beans> <session id="GeronimoTestEJB"> <ejb-name>DateEJB</ejb-name> <home>test.ejb.DateHome</home> <remote>test.ejb.DateRemote</remote> <local-home>test.ejb.DateHome</local-home> <local>test.ejb.DateRemote</local> <ejb-class>test.ejb.DateBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar> Note the EJB name is DateEJB. In the next file, $GERONIMO_DEVEL/etc/openejb-jar.xml, we map this name to a JNDI name: <?xml version="1.0"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar" configId="GeronimoTestEJB" parentId="org/apache/geronimo/Server"> <enterprise-beans> <session> <ejb-name>DateEJB</ejb-name> <jndi-name>DateEJB</jndi-name> </session> </enterprise-beans> </openejb-jar> This is the OpenEJB-specific descriptor. If you’ve previously used older versions of OpenEJB, you are probably familiar with this file. Only the namespace declaration differs.Next up is the application descriptor, which we save as $GERONIMO_DEVEL/etc/application.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd"> <application id="GeronimoTestApp"> <display-name>GeronimoTestApp</display-name> <description>A test of a simple EJB</description> <module> <ejb>gtest-ejbs.jar</ejb> </module> <module> <web> <web-uri>gtest.war</web-uri> <context-root>GeronimoTestWebApp</context-root> </web> </module> </application> This is all standard J2EE application descriptor stuff. Note <application>‘s id attribute: it names our J2EE application in Geronimo.We are almost done! All we need is a JSP page to test our bean, which we call $GERONIMO_DEVEL/web/ejbtest.jsp: <%@ page language="java" import="javax.naming.*, javax.ejb.CreateException, javax.ejb.RemoveException, java.rmi.RemoteException, javax.naming.NamingException, test.ejb.* "%> <html> <head> <title>EJB Test</title> <style type="text/css"> <!-- a { text-decoration: none } body { font-family: verdana, helvetica, sans serif; font-size: 10pt; } td { font-family: verdana, helvetica, sans serif; font-size: 10pt; } p { font-family: verdana, helvetica, sans serif; font-size: 10pt; } h3 { font-family: verdana, helvetica, sans serif; font-size: 12pt; font-weig ht: bold; color: #547180; } --> </style> </head> <body> <center><h3>Geronimo Test Application - EJB test</h3> <% String output = ""; try { javax.naming.InitialContext ctx = new javax.naming.InitialContext(); Object obj = ctx.lookup("java:comp/env/DateEJB"); DateHome home = (DateHome)javax.rmi.PortableRemoteObject.narrow(obj, DateHome.class); DateRemote dr = home.create(); output = dr.getDate(); dr.remove(); } catch (NamingException e){ System.err.println("Naming exception occurred during initialization"+ e); e.printStackTrace(); } %> The EJB said: <%= output %> </body> </html> Like the EJB components, this is boiler-plate EJB test code. As you can see, we look up our EJB component by the JNDI name of DateEJB, which maps to the EJB itself via the openejb-jar.xml file.To build, type ant ear, which creates the file $GERONIMO_DEVEL/dist/gtest.ear. To deploy this file, we first must undeploy our Web application and then deploy the .ear file: java -jar bin/deployer.jar --user system --password manager undeploy GeronimoTestWebApp java -jar bin/deployer.jar --user system --password manager deploy $GERONIMO_DEVEL/dist/gtest.ear This deployment only differs from the earlier ones in that we reference the gtest.ear file. After we run this command, Geronimo replies with: Deployed GeronimoTestApp Again, the name used by Geronimo is the one we specified in the $GERONIMO_DEVEL/etc/application.xml descriptor.Let’s test by going to http://[server]:8080/GeronimoTestWebApp/ejbtest.jsp. Figure 4 shows my results.ConclusionIn all this work, did you notice the one task we never had to perform? Nowhere did we have to restart Geronimo! The entire time, with all our deployment, undeployment, and connection pool setup activities, we let the server run. If you’ve spent much time with other J2EE-related servers, like Apache Tomcat and older versions of OpenEJB, you know you must restart for just about any major configuration change. But Geronimo was designed from the ground up with a dynamic classloading mechanism so that it can operate as a true enterprise application that, once started, just keeps on running.This article’s examples just scratch the surface of Geronimo. I didn’t have time to get into things like JMS, Tomcat, security, or transactions. But I hope that I have provided the basics you need for getting started. With the other documentation resources listed at the end of this article and your own work, you’ll soon be building serious Web applications for Geronimo. (If you’d like a real challenge, try to get the Sun J2EE PetStore application running on Geronimo.) Just remember to update your source code frequently and keep an eye on the mailing lists. Development on the project is extremely volatile, and there is still room for major changes in architecture. Look forward to both stability and community applause when the official Geronimo release is made!Lajos Moczar is a J2EE and Web consultant based in Colorado Springs, Colo. He is the author of several books and articles on open source Web technologies, most recently Tomcat 5 Unleashed from SAMS. Through his company, Galatea IS, he provides consulting and training services to companies all over the world. Web DevelopmentJavaTechnology Industry