A new Roo app deploys to Jetty without any changes, but JBoss 6 is a different story, mainly because it provides:
- its own versions of some libraries normally bundled with Roo (e.g. the Hibernate JPA provider and Validator).
- the full stack of JEE APIs, unlike Jetty which being a mere servlet container does not.
- its own TransactionManager, which you can look up via JNDI
- an injected EntityManagerFactory for each JPA persistence unit that you deploy to it, which again is exposed via JNDI
So the changes you need to make are as follows:
===========================================
Edit src/main/resources/META-INF/spring/applicationContext.xml:
- remove the BasicDataSource bean (the DataSource is now specified in persistence.xml)
- remove the JpaTransactionManager bean
- add <tx:jta-transaction-manager /> to look up JBoss' JtaTransactionManager from JNDI instead
- remove the LocalContainerEntityManagerFactoryBean
- add this bean:
Code:
<jee:jndi-lookup id="entityManagerFactory"
jndi-name="foo/bar/MyEntityManagerFactory"
expected-type="javax.persistence.EntityManagerFactory" />
(the "expected-type" attribute is optional but provides faster feedback in case of problems)
===========================================
Edit src/main/resources/META-INF/persistence.xml:
- change the persistence-unit's "transaction-type" attribute from RESOURCE_LOCAL to JTA
- add a child element to "persistence-unit" as follows:
Code:
<jta-data-source>java:/MyDSName</jta-data-source>
- add this property to the persistence-unit's "properties" element (triggers JBoss to create an EntityManagerFactory and expose it via the given JNDI name):
Code:
<property name="jboss.entity.manager.factory.jndi.name"
value="foo/bar/MyEntityManagerFactory"/>
===========================================
Create src/main/webapp/WEB-INF/jboss-classloading.xml:
- create this file as follows:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!-- See http://phytodata.wordpress.com/2010/10/21/demystifying-the-jboss5-jboss-classloading-xml-file -->
<classloading xmlns="urn:jboss:classloading:1.0"
domain="my_app.war"
import-all="true">
</classloading>
This causes the JAR files in your WAR file's WEB-INF/lib folder to be loaded in preference to those located in JBoss' own lib and common/lib folders. This is more flexible than simply marking all overlapping dependencies as "provided" in your POM (as I've seen suggested elsewhere), because it means you can use whatever version of Hibernate you like, not just the one shipped with JBoss 6.
===========================================
Edit pom.xml:
- replace these obsolete dependencies:
- org.hibernate:com.springsource.org.hibernate.annot ations:jar:3.3.1.ga
- org.hibernate:com.springsource.org.hibernate.ejb:j ar:3.3.2.GA
- org.hibernate:com.springsource.org.hibernate.valid ator:jar:4.0.0.GA
- javax.persistence:com.springsource.javax.persisten ce:jar:1.0.0
- with these (which happen to coincide with those in JBoss 6, but need not):
- org.hibernate:hibernate-entitymanager:jar:3.6.0.Final
- org.hibernate:hibernate-validator:jar:4.1.0.Final
- org.hibernate.javax.persistencehibernate-jpa-2.0-api:jar:1.0.0.Final: provided
- mark this dependency as provided (because with a full JEE app server, it is):
- javax.transaction:com.springsource.javax.transacti on:jar:1.1.0
===========================================
Your Roo app should now deploy and run happily in JBoss 6 (at least 6.0.0.Final, which I used). I can't speak for JBoss 5, as I haven't tested it, but a lot of the principles described above still hold and the same techniques therefore probably still apply.
Hope this helps someone!