This document describes the steps to run JBoss Seam's booking
sample application on Apache Geronimo 2.1. You can read about JBoss Seam at its web site.
This document applied to JBoss Seam 2.0.0.GA. Download it from http://sourceforge.net/project/showfiles.php?group_id=22866&package_id=163777&release_id=551158.
This document applies to Geronimo 2.1 daily build (aka 2.1-SNAPSHOT). Until it's released you can download it from http://people.apache.org/~prasad/binaries/trunk/20071130/.
Hibernate Transaction Manager Lookup class for Geronimo
Hibernate doesn't support Geronimo by default as far as Geronimo transaction manager's concerned. Whenever Hibernate does transaction management it needs a JTA transaction manager which is a necessary component of every Java EE application server. Geronimo provides one, but Hibernate doesn't know how to look it up. We need to create a transaction manager lookup class for Hibernate to access Geronimo transaction manager. With the class - org.apache.geronimo.hibernate.transaction.GeronimoTransactionManagerLookup - it'll be able to do its duties.
You can read more about migrating JBoss/Hibernate applications to Geronimo at The documentation about JBoss to Geronimo - Hibernate Migration.
geronimo-hibernate-transaction-manager-lookup maven project
To simplify the step here's how the tx manager lookup class is developed using Apache Maven 2. Go to any directory you want where the maven project for Hibernate Transaction Manager Lookup class for Geronimo is to be created.
jlaskowski@dev /cygdrive/c
$ mvn archetype:create -DgroupId=org.apache.geronimo.hibernate -DartifactId=geronimo-hibernate-transaction-manager-lookup
...
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating Archetype: maven-archetype-quickstart:RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.apache.geronimo.hibernate
[INFO] Parameter: packageName, Value: org.apache.geronimo.hibernate
[INFO] Parameter: basedir, Value: c:\
[INFO] Parameter: package, Value: org.apache.geronimo.hibernate
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: artifactId, Value: geronimo-hibernate-transaction-manager-lookup
[INFO] ********************* End of debug info from resources from generated POM ***********************
[INFO] Archetype created in dir: c:\geronimo-hibernate-transaction-manager-lookup
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
Replace the content of pom.xml
which is the main configuration file of any maven project to the following:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.geronimo.hibernate.transaction</groupId> <artifactId>geronimo-hibernate-transaction-manager-lookup</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>geronimo-hibernate-transaction-manager-lookup</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jta_1.1_spec</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.4.sp1</version> <exclusions> <exclusion> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.geronimo.modules</groupId> <artifactId>geronimo-kernel</artifactId> <version>2.1-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> </build> </project> {code:XML} Change your working directory to the project's directory, e.g. {{c:/geronimo-hibernate-transaction-manager-lookup}} and do the following steps from within. Create the {{org.apache.geronimo.hibernate.transaction.GeronimoTransactionManagerLookup}} class in {{src/main/java/org/apache/geronimo/hibernate/transaction/}} directory. {code:JAVA|borderStyle=solid|title=org.apache.geronimo.hibernate.transaction.GeronimoTransactionManagerLookup} package org.apache.geronimo.hibernate.transaction; import java.util.Properties; import java.util.Set; import javax.management.ObjectName; import javax.transaction.TransactionManager; import org.hibernate.HibernateException; import org.hibernate.transaction.TransactionManagerLookup; import org.apache.geronimo.kernel.*; import org.apache.geronimo.gbean.*; public class GeronimoTransactionManagerLookup implements TransactionManagerLookup { public static final String UserTransactionName = "java:comp/UserTransaction"; public TransactionManager getTransactionManager(Properties props) throws HibernateException { try { Kernel kernel = KernelRegistry.getSingleKernel(); AbstractNameQuery query = new AbstractNameQuery(TransactionManager.class.getName ()); Set<AbstractName> names = kernel.listGBeans(query); if (names.size() != 1) { throw new IllegalStateException("Expected one transaction manager, not " + names.size()); } AbstractName name = names.iterator().next(); TransactionManager transMg = (TransactionManager) kernel.getGBean(name); return (TransactionManager)transMg; } catch (Exception e) { e.printStackTrace(); System.out.println(); throw new HibernateException("Geronimo Transaction Manager Lookup Failed", e); } } public String getUserTransactionName() { return UserTransactionName; } } {code:JAVA} Build it. {color:white}{noformat:borderStyle=solid|bgColor=#000000} $ mvn -Dmaven.test.skip=true install [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Building geronimo-hibernate-transaction-manager-lookup [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 2 source files to c:\geronimo-hibernate-transaction-manager-lookup\target\classes [INFO] [resources:testResources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:testCompile] [INFO] Not compiling test sources [INFO] [surefire:test] [INFO] Tests are skipped. [INFO] [jar:jar] [INFO] Building jar: c:\geronimo-hibernate-transaction-manager-lookup\target\geronimo-hibernate-transaction-manager-lookup-1.0-SNAPSHOT.jar [INFO] [install:install] [INFO] Installing c:\geronimo-hibernate-transaction-manager-lookup\target\geronimo-hibernate-transaction-manager-lookup-1.0-SNAPSHOT.jar to C:\.m2\org\apache\geronimo\hibernate\transaction\geronimo-hibernate-transaction-manager-lookup\1.0-SNAPSHOT\geronimo-hibernate-transaction-manager-lookup-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ {noformat}{color} Note that the file is installed into your maven local repository, e.g. {{C:\.m2\org\apache\geronimo\hibernate\transaction\geronimo-hibernate-transaction-manager-lookup\1.0-SNAPSHOT\geronimo-hibernate-transaction-manager-lookup-1.0-SNAPSHOT.jar}}. Install the file to Geronimo artifact repository, i.e. {{$\{GERONIMO_HOME\}/repository}}. With Geronimo stopped, create a directory and place the file in it. {color:white}{noformat:borderStyle=solid|bgColor=#000000} jlaskowski@dev /cygdrive/c/geronimo $ mkdir -p repository/org/apache/geronimo/hibernate/transaction/geronimo-hibernate-transaction-manager-lookup/1.0-SNAPSHOT jlaskowski@dev /cygdrive/c/geronimo $ cp c\:/.m2/org/apache/geronimo/hibernate/transaction/geronimo-hibernate-transaction-manager-lookup/1.0-SNAPSHOT/geronimo-hibernate-transaction-manager-lookup-1.0-SNAPSHOT.jar \ repository/org/apache/geronimo/hibernate/transaction/geronimo-hibernate-transaction-manager-lookup/1.0-SNAPSHOT/ {noformat}{color} h1. Hibernate JPA change If we attempted to deploy JBoss Seam's booking application with Hibernate JPA it would choke with NPE. {noformat:borderStyle=solid|title=java.lang.NullPointerException at Hibernate processing of PersistenceUnitInfo bookingDatabase} 12:10:24,359 INFO [Version] Hibernate Annotations 3.3.0.GA 12:10:24,437 INFO [Environment] Hibernate 3.2.4.sp1 12:10:24,734 INFO [Environment] hibernate.properties not found 12:10:24,734 INFO [Environment] Bytecode provider name : cglib 12:10:24,750 INFO [Environment] using JDK 1.4 java.sql.Timestamp handling 12:10:25,171 INFO [Version] Hibernate EntityManager 3.3.1.GA 12:10:25,328 INFO [Ejb3Configuration] Processing PersistenceUnitInfo [ name: bookingDatabase ...] 12:10:25,328 ERROR [GBeanInstanceState] Error while starting; GBean is now in the FAILED state: abstractName="org.jboss.seam.examples.jee5/jboss-seam-jee5/2.0.0.GA/ear?EJBModule=jboss-s eam-jee5.jar,J2EEApplication=org.jboss.seam.examples.jee5/jboss-seam-jee5/2.0.0.GA/ear,PersistenceUnitModule=jboss-seam-jee5.jar,j2eeType=PersistenceUnit,name=bookingDatabase" java.lang.NullPointerException at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:346) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:126) at org.apache.geronimo.persistence.PersistenceUnitGBean.<init>(PersistenceUnitGBean.java:117) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:494) at org.apache.geronimo.gbean.runtime.GBeanInstance.createInstance(GBeanInstance.java:946) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.attemptFullStart(GBeanInstanceState.java:268) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.start(GBeanInstanceState.java:102) at org.apache.geronimo.gbean.runtime.GBeanInstance.start(GBeanInstance.java:539) at org.apache.geronimo.gbean.runtime.GBeanDependency.attemptFullStart(GBeanDependency.java:111) at org.apache.geronimo.gbean.runtime.GBeanDependency.addTarget(GBeanDependency.java:146) at org.apache.geronimo.gbean.runtime.GBeanDependency$1.running(GBeanDependency.java:120) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor.fireRunningEvent(BasicLifecycleMonitor.java:176) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor.access$300(BasicLifecycleMonitor.java:44) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor$RawLifecycleBroadcaster.fireRunningEvent(BasicLifecycleMonitor.java:254) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.attemptFullStart(GBeanInstanceState.java:294) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.start(GBeanInstanceState.java:102) at org.apache.geronimo.gbean.runtime.GBeanInstance.start(GBeanInstance.java:539) at org.apache.geronimo.gbean.runtime.GBeanDependency.attemptFullStart(GBeanDependency.java:111) at org.apache.geronimo.gbean.runtime.GBeanDependency.addTarget(GBeanDependency.java:146) at org.apache.geronimo.gbean.runtime.GBeanDependency$1.running(GBeanDependency.java:120) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor.fireRunningEvent(BasicLifecycleMonitor.java:176) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor.access$300(BasicLifecycleMonitor.java:44) at org.apache.geronimo.kernel.basic.BasicLifecycleMonitor$RawLifecycleBroadcaster.fireRunningEvent(BasicLifecycleMonitor.java:254) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.attemptFullStart(GBeanInstanceState.java:294) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.start(GBeanInstanceState.java:102) at org.apache.geronimo.gbean.runtime.GBeanInstanceState.startRecursive(GBeanInstanceState.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.startRecursive(GBeanInstance.java:553) at org.apache.geronimo.kernel.basic.BasicKernel.startRecursiveGBean(BasicKernel.java:379) at org.apache.geronimo.kernel.config.ConfigurationUtil.startConfigurationGBeans(ConfigurationUtil.java:448) at org.apache.geronimo.kernel.config.KernelConfigurationManager.start(KernelConfigurationManager.java:187) at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:530) at org.apache.geronimo.kernel.config.SimpleConfigurationManager.startConfiguration(SimpleConfigurationManager.java:511) at org.apache.geronimo.kernel.config.SimpleConfigurationManager$$FastClassByCGLIB$$ce77a924.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:865) at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239) at org.apache.geronimo.kernel.KernelGBean.invoke(KernelGBean.java:342) at org.apache.geronimo.kernel.KernelGBean$$FastClassByCGLIB$$1cccefc9.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:865) at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239) at org.apache.geronimo.system.jmx.MBeanGBeanBridge.invoke(MBeanGBeanBridge.java:168) at com.sun.jmx.mbeanserver.DynamicMetaDataImpl.invoke(DynamicMetaDataImpl.java:213) at com.sun.jmx.mbeanserver.MetaDataImpl.invoke(MetaDataImpl.java:220) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:815) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:784) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1410) at javax.management.remote.rmi.RMIConnectionImpl.access$100(RMIConnectionImpl.java:81) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1247) at java.security.AccessController.doPrivileged(Native Method) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1350) at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:784) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport$1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707) at java.lang.Thread.run(Thread.java:595) {noformat} Without delving into much detail it boils down to patching {{org.hibernate.ejb.Ejb3Configuration}} to avoid NPE. Download the class from its source code repository at http://fisheye.jboss.com/browse/Hibernate/entitymanager/trunk/src/java/org/hibernate/ejb/Ejb3Configuration.java. h1. The plan{anchor:plan} The plan configures necessary Geronimo resources to deploy JBoss Seam's booking sample application. {code:xml| borderStyle=solid| title=jboss-seam-jee5-geronimo-plan.xml} <?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-2.0"> <environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> <moduleId> <groupId>org.jboss.seam.examples.jee5</groupId> <artifactId>jboss-seam-jee5</artifactId> <version>2.0.0.GA</version> <type>ear</type> </moduleId> <dependencies> <dependency> <groupId>org.apache.geronimo.hibernate.transaction</groupId> <artifactId>geronimo-hibernate-transaction-manager-lookup</artifactId> <type>jar</type> </dependency> </dependencies> </environment> <module> <web>jboss-seam-jee5.war</web> <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"> <environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> <moduleId> <groupId>org.jboss.seam.examples.jee5</groupId> <artifactId>jboss-seam-jee5</artifactId> <version>2.0.0.GA</version> <type>war</type> </moduleId> </environment> <context-root>/seam-jee5</context-root> </web-app> </module> <module> <ejb>jboss-seam-jee5.jar</ejb> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1"> <environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> <moduleId> <groupId>org.jboss.seam.examples.jee5</groupId> <artifactId>jboss-seam-jee5</artifactId> <version>2.0.0.GA</version> <type>jar</type> </moduleId> </environment> <!-- overrides what's in the module's persistence.xml --> <persistence xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="bookingDatabase"> <jta-data-source>jdbc/__default</jta-data-source> <class>org.jboss.seam.example.booking.Booking</class> <class>org.jboss.seam.example.booking.Hotel</class> <class>org.jboss.seam.example.booking.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.transaction.manager_lookup_class" value="org.apache.geronimo.hibernate.transaction.GeronimoTransactionManagerLookup" /> </properties> </persistence-unit> <!-- change the way the default PU works - make it an alias to bookingDatabase PU --> <persistence-unit name="cmp"> <class>org.jboss.seam.example.booking.Booking</class> <class>org.jboss.seam.example.booking.Hotel</class> <class>org.jboss.seam.example.booking.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> </persistence-unit> </persistence> </openejb-jar> </module> <ext-module> <connector>seam-jee5-dbpool</connector> <external-path xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:groupId>org.tranql</dep:groupId> <dep:artifactId>tranql-connector-derby-embed-xa</dep:artifactId> <dep:type>rar</dep:type> </external-path> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"> <environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> <moduleId> <groupId>org.jboss.seam.examples.jee5</groupId> <artifactId>booking-dbpool</artifactId> <version>2.0.0.GA</version> <type>rar</type> </moduleId> <dependencies> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>system-database</artifactId> <type>car</type> </dependency> </dependencies> </environment> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface> <connectiondefinition-instance> <name>jdbc/__default</name> <config-property-setting name="DatabaseName">SystemDatabase</config-property-setting> <connectionmanager> <local-transaction /> <single-pool> <max-size>100</max-size> <blocking-timeout-milliseconds>5000</blocking-timeout-milliseconds> <select-one-assume-match /> </single-pool> </connectionmanager> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector> </ext-module> </application>
Starting Geronimo
Type it in on the command line.
jlaskowski@dev /cygdrive/c/geronimo
$ ./bin/geronimo.sh run -vv
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: c:\geronimo\var\temp
Using JRE_HOME: c:\apps\java5\jre
...
Geronimo startup complete
Deploying jboss-seam-jee5.ear
Build the booking sample as follows:
jlaskowski@dev /cygdrive/c/apps/jboss-seam-2.0.0.GA/examples/jee5/booking
$ ant clean archive
Buildfile: build.xml
...
archive:
[jar] Building jar: c:\apps\jboss-seam-2.0.0.GA\examples\jee5\booking\dist\jboss-seam-jee5.jar
[jar] Building jar: c:\apps\jboss-seam-2.0.0.GA\examples\jee5\booking\dist\jboss-seam-jee5.war
[jar] Building jar: c:\apps\jboss-seam-2.0.0.GA\examples\jee5\booking\dist\jboss-seam-jee5.ear
BUILD SUCCESSFUL
Total time: 23 seconds
You can deploy jboss-seam-jee5.ear from the web console of Geronimo, but there's another way to do the same - executing deploy
command on the command line.
jlaskowski@dev /cygdrive/c/geronimo-jetty6-jee5-2.0.2
$ ./bin/deploy.sh -u system -p manager deploy hudson.war hudson-geronimo-plan.xml
Using GERONIMO_BASE: c:\geronimo-jetty6-jee5-2.0.2
Using GERONIMO_HOME: c:\geronimo-jetty6-jee5-2.0.2
Using GERONIMO_TMPDIR: c:\geronimo-jetty6-jee5-2.0.2\var\temp
Using JRE_HOME: c:\apps\java5\jre
Deployed hudson/hudson/1.153/war @ /hudson
The Geronimo console shows deployment progress as follows:
hudson home directory: C:\Documents and Settings\jlaskowski\.hudson 2007-11-08 08:53:12 hudson.TcpSlaveAgentListener <init> INFO: JNLP slave agent listener started on TCP port 3448 2007-11-08 08:53:12 hudson.model.Hudson load INFO: Took 31 ms to load
Running the webapp
Point the browser of your choice to http://localhost:8080/hudson. You should see hudson's welcome page.
Setting up a new Maven2 job in hudson works fine too.