16

I have two persistence.xml files, for the sake of testing:

  • src/main/resources/META-INF/persistence.xml
  • src/test/resources/META-INF/persistence.xml

How to instruct Maven to ignore the first file during testing? Now it is not ignored since OpenEJB says:

ERROR - FAIL ... Finder: @PersistenceContext unitName has multiple matches: 
unitName "abc" has 2 possible matches.
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
yegor256
  • 102,010
  • 123
  • 446
  • 597
  • possible duplicate of [How to configure JPA for testing in Maven](http://stackoverflow.com/questions/385532/how-to-configure-jpa-for-testing-in-maven) – Colin Hebert Oct 05 '10 at 10:41
  • Hmm, could you add more details about the OpenEJB part (maybe a link?). Because this works with "basic" JUnit tests. – Pascal Thivent Oct 05 '10 at 22:37
  • Are you using [Application discovery via the classpath ](http://openejb.apache.org/3.0/application-discovery-via-the-classpath.html)? – Pascal Thivent Oct 06 '10 at 08:33
  • if you have any more details, I can try and give a better answer. Have you tried the altDD approach? – David Blevins Oct 26 '10 at 23:08
  • @Pascal Yes, I'm using "application discovery via the classpath", and I see this error message all the time. I actually can understand what's going on, there are two `persistence.xml` in the classpath, and OpenEJB gets confused.. – yegor256 Oct 28 '10 at 10:21

4 Answers4

11

Check out the alternate descriptors functionality which is aimed at what you're trying to do.

Try this setup:

  • src/main/resources/META-INF/persistence.xml
  • src/main/resources/META-INF/test.persistence.xml

Then you can construct OpenEJB to prefer the test.persistence.xml file by setting the openejb.altdd.prefix System or InitialContext property to test

A different possible solution could be to override the persistence unit properties in the test. With that approach you could avoid the need for a second persistence.xml which can be nice as maintaining two can be a pain.

You can use the Maven approach, but be aware that per spec the persistence provider will only look (aka scan) for @Entity beans in the exact jar or directory where the persistence.xml is found. So be keenly aware that in Maven these are two different locations:

  • target/classes
  • target/test-classes

EDIT More details on the overriding capabilities

You can override any property in your test setup via either system properties or the initial context properties (this includes jndi.properties files). The format is:

<unit-name>.<property>=<value>

So for example with the following persistence.xml:

<persistence>
  <persistence-unit name="movie-unit">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>movieDatabase</jta-data-source>
    <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.max_fetch_depth" value="3"/>
    </properties>
  </persistence-unit>
</persistence>

You can override and add persistence unit properties in your test case. There are currently no facilities for removing them (if you have a need for that let us know – it hasn't really come up so far).

Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.openejb.client.LocalInitialContextFactory");

p.put("movie-unit.hibernate.hbm2ddl.auto", "update");
p.put("movie-unit.hibernate.dialect", "org.hibernate.dialect.HSQLDialect");

context = new InitialContext(p);

Or alternatively via a jndi.properties file

java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory
movie-unit.hibernate.hbm2ddl.auto = update
movie-unit.hibernate.dialect = org.hibernate.dialect.HSQLDialect
David Blevins
  • 19,178
  • 3
  • 53
  • 68
  • 4
    Yes, I'm using Maven, and it's important to strictly separate production `persistence.xml` and testing `persistence.xml`. That's why I strongly disagree with the idea of placing `test.persistence.xml` into `src/main/resources`. – yegor256 Oct 28 '10 at 10:24
  • From the look of your other posts, it looks like you could easily get away with just the override option linked above. That's the more ideal option as maintaining two persistence.xml files is a pain. – David Blevins Oct 29 '10 at 20:26
  • Does the alternate descrption solution really working for the persistence.xml file? It doesn't look so according to the documentation. Also, I tried a quick test of this myself, without success. – Magnilex Sep 01 '14 at 10:19
1

I think you can create two profiles in your pom.xml:

<properties>
  <environment>dev</environment>
</properties>
<profiles>
  <profile>
    <id>prod</id>
    <properties>
      <environment>test</environment>
    </properties>
  </profile>
</profiles>

After that, in your src folder, create two folders named dev/resoruces and test/resources and copy your different resources there. After that, add something like this:

<resources>
  <resource>
    <directory>${basedir}/src/main/resources</directory>
    <filtering>false</filtering>
  </resource>
  <resource>
    <directory>${basedir}/src/main/${environment}/resources</directory>
    <filtering>true</filtering>
  </resource>
</resources>

The ${basedir} depends on the command line parameter, it can be test or dev. You run the maven command like this: mvn clean package -P test.

virgium03
  • 627
  • 1
  • 5
  • 14
  • 2
    Looks like a very "dirty" solution, since I always have to remember that tests are to be run with `mvn test -P test`, not as usual `mvn test`... – yegor256 Oct 28 '10 at 09:36
0

I have been testing these and other similar solutions without involving the pom.xml... In my opinion, the best way to solve this issue is to have two application-context.xml (one only to be used in test classes) and to add a custom persistence unit manager bean in the test's application-context.xml. Like this example:

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
  <property name="persistenceXmlLocation">
     <value>classpath*:META-INF/test.persistence.xml</value>
  </property>
  <property name="defaultDataSource" ref="dataSource"/>
</bean>

This solution runs. :)

ᄂ ᄀ
  • 5,669
  • 6
  • 43
  • 57
-2

Better add both files - in general, making test/production or debug/profile/production distinction in build makes only trouble. Better try to use different perasistence unit name for production (say abc-production) and for tests (abc-tests).

iirekm
  • 8,890
  • 5
  • 36
  • 46
  • @iiekm If there are two different unit names - how can I run my unit tests with automated injection of `EntityManager` by `unitName`? – yegor256 Oct 28 '10 at 09:34
  • I have never used @PersistenceContext so I won't tell you with it in Spring - just create two Spring XML files; let one be used for regular application (you usually choose it in web.xml), another for test (you choose it inside test code); let the one for production create an EntityManager with persistence context abc-production, the other with abc-tests – iirekm Oct 28 '10 at 20:03