2

In the midst of learning Maven created a simple JPA project (Java Persistence 1.0.2 with EclipseLink implementation 2.0.2). This is an Application Managed environment. So I manually control EntityManager's life cycle.

The persistence.xml file used by the main source code is different from the one that unit test code uses (also suggested here). Main code uses an Oracle DB and the test code uses an in-memory Derby. Running unit tests was updating the Oracle DB (!) and I eventually managed to fix that by using two different persistence-units in the XML files.

However, I don't understand why that fixed the problem. I manually create and shut down the entity managers and they are not running concurrently. I'm pretty sure Maven (or the way I set it up) doesn't mess up the resources (XML files). In fact by looking at Maven's debug output I can see it's using the right XML file for unit tests. In fact I don't see why that should be a problem to begin with.

Could someone enlighten me, please?

-- Updated

Here is the src/main/resources/META-INF/Persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence     http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="MainPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>org.domain.Book</class>
        <class>org.domain.Tag</class>
        <properties>
            <property name="eclipselink.target-database" value="Oracle" />
            <property name="eclipselink.logging.level" value="INFO" />
            <property name="javax.persistence.jdbc.driver"     value="oracle.jdbc.OracleDriver" />
        <property name="javax.persistence.jdbc.url"     value="jdbc:oracle:thin:@xxx:1526:XE" />
            <property name="javax.persistence.jdbc.user" value="usr" />
            <property name="javax.persistence.jdbc.password" value="pass" />
        </properties>
    </persistence-unit>
</persistence>

and here is src/test/resources/META-INF/Persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence     http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">
    <persistence-unit name="TestPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>org.domain.Book</class>
        <class>org.domain.Tag</class>
        <properties>
            <property name="eclipselink.target-database" value="DERBY" />
            <property name="eclipselink.ddl-generation" value="drop-and-create-    tables" />
            <property name="eclipselink.logging.level" value="FINE" />
            <property name="javax.persistence.jdbc.driver"     value="org.apache.derby.jdbc.EmbeddedDriver" />
            <property name="javax.persistence.jdbc.url"     value="jdbc:derby:memory:testDB;create=true" />
            <property name="javax.persistence.jdbc.user" value="usr" />
            <property name="javax.persistence.jdbc.password" value="pass" />
        </properties>
    </persistence-unit>
</persistence>

The Main source code:

....
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MainPU");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();

tx.begin();
Iterator<Book> booksItr = books.iterator();
while (booksItr.hasNext())
    em.persist(booksItr.next());
tx.commit();

em.close();
emf.close();
...

and unit test source code is almost the same except that it uses "TestPU" to create EntityManagerFactory.

Community
  • 1
  • 1
Amir Keibi
  • 1,991
  • 28
  • 45
  • Could you post relevant snippet of your unit test. Most likely the persistence file of the main source is getting used in the test. – Raghuram Apr 02 '12 at 06:58
  • updated the main post. That works perfectly unless in the unit test source code I use "MainPU" instead of "TestPU" as mentioned above. What I don't understand is that why with two different resource files (one used for unit test and one for main code) when both test and source use the same Persistence Unit, unit test updates the Oracle DB. – Amir Keibi Apr 02 '12 at 08:33
  • Solved. Because both were in runtime's Class-Path. – Amir Keibi Apr 30 '12 at 18:56
  • How did you set the classpath? It seems i have the same problem. – JHollanti Jan 23 '14 at 05:53
  • If your main and test code are within the same project, then both Persistence Units will fall in the same CLASSPATH. – Amir Keibi Jan 24 '14 at 06:55
  • I just realized that I never updated my question properly after I fixed my problem. These were Integration Tests which I was temporarily writing them as Unit Tests for a showcase. Obviously Unit Tests should mock external dependencies. I eventually moved them out to a separate project and persistence units weren't interfering with each other. – Amir Keibi Jan 24 '14 at 07:01

1 Answers1

-1

When you have 2 different databases therefore you need 2 different persistence.xml files. In your test persistence.xml file when you have one test class then you need only one persistence unit. When you would write a second test class which tests business rules that accesses your in-memory Derby database, you need a further persistence-unit in your test persistence.xml. I think the reason why your testing code access the Oracle DB is that you have the persistence unit of the Oracle DB defined in you test/persistence.xml file. You should remove it and you should only have that persistence unit for the derby in-memory DB.

ugurkocak1980
  • 143
  • 1
  • 13
  • This is basically repeating the question and doesn't address the problem. The solution was already found (see comments). – Amir Keibi Feb 19 '18 at 21:07
  • Let's see. You're suggesting that 2 different PUs should be used, one for source and another for tests. Right? If so, that's already in the question. You're not providing anything new. If that's not what you're suggesting, then please clarify. – Amir Keibi Feb 21 '18 at 23:59
  • Thank you Amir. I think I didn't get the question in right way. I hope that my edited answer makes you confident ;-) Any question welcome – ugurkocak1980 Mar 02 '18 at 23:32