5
votes

I have a Java web application leveraging JPA. The database instance is specified in the persistence.xml file using the jta-data-source tag.

I would like to deploy a second copy of the web application on the same (glassfish) server, but pointed at a different database instance.

What is the best way to achieve this? I think ideally, I'd like to place a persistence.xml override file outside of the war (somewhere on the classpath?). I'm not exactly sure where to put it or how to define it in a way that it wouldn't confilt with my other instance. I can see us hosting a handful of instances in this manner (SaaS) and I'd like the configuration to be outside the deployed war so that it wouldn't become a maintenance issue. Sharing a database instance between clients is not an option for security reasons.

I'm sure this isn't a unique problem to our group. What are the best practices or solutions others are using to solve this problem?

6
If you have multiple unique instances of the app running, why not just change the persistence.xml for the 2nd instance?kgrad
It seems like a maintenance problem to have to do this manually for each instance on every build, I'd like an automated solution.Vinnie

6 Answers

2
votes

update:

http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html

not sure if this can be set up in an appserver but i'll give it a go. only thing that worries me is management of the scope. the container manages the scope along transaction boundaries

//inject entity manager
@Inject("mySpecialEntityManager")
EntityManager em;

//then mark the actual factory method in the factory bean with    
@Produces("mySpecialEntityManager")

but then how to manage scope is the problem


2.2.2. Bootstrapping

The JPA specification defines a bootstrap procedure to access the EntityManagerFactory and the EntityManager. The bootstrap class is javax.persistence.Persistence, e.g.

Map configOverrides = new HashMap();

configOverrides.put("hibernate.hbm2ddl.auto", "create-drop");

EntityManagerFactory programmaticEmf =

Persistence.createEntityManagerFactory("manager1", configOverrides);

The first version is equivalent to the second with an empty map. The map version is a set of overrides that will take precedence over any properties defined in your persistence.xml files. All the properties defined in Section 2.2.1, “Packaging” can be passed to the createEntityManagerFactory method and there are a few additional ones:

*

  javax.persistence.provider to define the provider class used
*

  javax.persistence.transactionType to define the transaction type used (either JTA or RESOURCE_LOCAL)
*

  javax.persistence.jtaDataSource to define the JTA datasource name in JNDI
*

  javax.persistence.nonJtaDataSource to define the non JTA datasource name in JNDI
*

  javax.persistence.lock.timeout pessimistic lock timeout in milliseconds (Integer or String)
*

  javax.persistence.query.timeout query timeout in milliseconds (Integer or String)
*

  javax.persistence.sharedCache.mode corresponds to the share-cache-mode element defined in Section 2.2.1, “Packaging”.
1
votes

i guess you are already altering the copy in other things too ? (e.g. name of ear file)

If you use a build software like ant or maven you could use a placeholder inside the persistence.xml and create a different "copy" by just using different build parameters.

e.g. with maven

mvn clean install -DmyDatabaseName=db/somedb

1
votes

I would package two versions of the webapp and declare a specific datasource in the jta-data-source element of their respective persistence.xml (I don't think you can externalize this file, it is expected to be in WEB-INF/classes/META-INF/persistence.xml)

1
votes

What about storing a persistence.xml in the META-INF folder of a classes directory and then specifying that folder first in the classpath?

0
votes

Via spring you can override persistance.xml settings on application startup, and load those settings from an externalized properties file.

http://www.summa-tech.com/blog/2009/04/20/6-tips-for-managing-property-files-with-spring/

Take a look at @darren's answer at: Spring + Hibernate + JPA

0
votes

Here is what I was able to do in a Java SE environment:

Create a .jar file without the persistence.xml file. I created a manifest.mf file manually and in the Class-Path: I put "." in addition to the other entries I needed.

In the directory where you install the software, create a META-INF directory and put persistence.xml in there. It should get picked up automatically.

e.g.

  /my/install/dir/
                 META-INF/persistence.xml
                 foo.jar