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?
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”.
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
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
)
What about storing a persistence.xml in the META-INF folder of a classes
directory and then specifying that folder first in the classpath?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With