Configuring a Spring web app using JPA2 to use a JBoss datasource on OpenShift

By default, when creating a web app with Spring Roo, your JPA configuration is set up to use a Commons DBCP BasicDataSource. This works great for testing locally on Tomcat, but doesn’t work when deployed to the OpenShift environment, you’ll get errors like this as Hibernate tries to get connections and set up your schema based on your Entity mappings :

2012/03/08 18:17:03,423 ERROR [org.hibernate.tool.hbm2ddl.SchemaExport]
(MSC service thread 1-3) HHH000231: Schema export unsuccessful:
java.lang.UnsupportedOperationException: The application must supply JDBC connections

At the current time there isn’t a great deal of documentation on the Open Shift site that explains how to config your app to use a datasource, but this post on the community forum has some good clues (this one is Flex specific, but it mentions the standalone.xml JBoss config file).

When you add a database cartridge to your app in OpenShift, your JBoss in your environment is also configured with a DataSource using connection properties set up to access your MySQL (or other) db, and it’s ready to go.

To get your Spring Roo app configured to use the datasource requires a bit more effort. There’s various posts online about how to configure JPA2 to use a DataSource provided by a container, but getting all the right parts changed or removed in your existing config is a bit tricky. This post here lists all the steps needed, and most of the text below is taken from this post (thanks to the poster of this entry on the Spring forum as before I got to this stage I had already spent a few hours trying to piece this together) – here we go:

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. The default name of the bean using this tag is ‘transactionManager’
  • If you had previously used the <tx:annotation-driven> tag, make sure it’s transaction-manger attribute now uses ‘transactionManager’ (from the previous step):
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

 

  • remove the LocalContainerEntityManagerFactoryBean
  • add this bean:
<jee:jndi-lookup id="entityManagerFactory"
        jndi-name="your/app/MyEntityManagerFactory"
        expected-type="javax.persistence.EntityManagerFactory" />

Your EntityManagerFactory gets exposed by JBoss from the following changes to your persistence.xml files:

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:
<jta-data-source>java:/MyDSName</jta-data-source>

Add the following property to expose your EntityManagerFactory:

<property name="jboss.entity.manager.factory.jndi.name"
        value="your/app/MyEntityManagerFactory"/>

Adding additional Maven repositories to your pom.xml

Not all jars can be located in the default maven repo. org.jboss jars for example can be picked up from JBoss’ own repo.

To add an additional repo to your pom.xml, add a section like this:

	<repositories>
		<repository>
			<id>JBoss Repo</id>
			<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
			<name>JBoss Repo</name>
		</repository>
	</repositories>

Changing the default page in a Spring Roo app

To map a default Spring MVC view to a URL, for example to map the default URL, /, add this to your webmvc-config.xml file to define a static view, i.e. a view not using an explicit Controller:

<mvc:view-controller path="/" view-name="index"/>

You can change the view-name attribute to point to any other view if you need to have a default other than /views/index.jspx .

Note that using the web.xml welcome file only works for a real file, and doesn’t work to map to a Spring MVC view URL:

<welcome-file-list><welcome-file>/index</welcome-file></welcome-file-list>