You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/05/06 01:28:27 UTC

svn commit: r941541 - in /openjpa/trunk/openjpa-slice/src/test: java/org/apache/openjpa/slice/TestTransaction.java resources/META-INF/persistence.xml

Author: ppoddar
Date: Wed May  5 23:28:26 2010
New Revision: 941541

URL: http://svn.apache.org/viewvc?rev=941541&view=rev
Log:
OPENJPA-1649: Add a test to verify transaction atomicity across slices.

Added:
    openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java   (with props)
Modified:
    openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml

Added: openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java?rev=941541&view=auto
==============================================================================
--- openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java (added)
+++ openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java Wed May  5 23:28:26 2010
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.slice;
+
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.RollbackException;
+
+/**
+ * Tests that if any of the slices fail then none of the slices are committed.
+ * 
+ * The test setup assumes that configuration is created for each slice to store
+ * cars from a particular Manufacturer. 
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class TestTransaction extends SliceTestCase {
+    private static final Random rng = new Random(System.currentTimeMillis());
+    Manufacturer[] manufacturers;
+    
+    protected String getPersistenceUnitName() {
+        return System.getProperty("unit","car");
+    }
+
+
+    public void setUp() throws Exception {
+        super.setUp(CLEAR_TABLES, 
+                Car.class, Manufacturer.class, 
+                "openjpa.slice.DistributionPolicy", CarDistributorPolicy.class.getName());
+        DistributedConfiguration conf = (DistributedConfiguration)emf.getConfiguration();
+        List<Slice> slices = conf.getSlices((Slice.Status[])null);
+        assertFalse(slices.isEmpty());
+        manufacturers = persistManufacturers(slices);
+    }
+    
+    public void testCommitsAreAtomic() {
+        int nCarStart = count(Car.class);
+        persistCars(false);
+        int nCarStage1 = count(Car.class);
+        assertEquals(nCarStart+manufacturers.length, nCarStage1);
+        
+        for (int i = 0; i < 10; i++) {
+            persistCars(true);
+            int nCarStage2 = count(Car.class);
+            assertEquals(nCarStage1, nCarStage2);
+        }
+    }
+    
+    Manufacturer getManufacturer(EntityManager em, Slice slice) {
+        Manufacturer m = em.find(Manufacturer.class, slice.getName());
+        if (m == null) {
+            m = new Manufacturer();
+            m.setName(slice.getName());
+            em.persist(m);
+        }
+        return m;
+    }
+    
+    /**
+     * Creates the manufacturers each per given slice. 
+     */
+    Manufacturer[] persistManufacturers(List<Slice> slices) {
+        Manufacturer[] manufacturers = new Manufacturer[slices.size()];
+        int i = 0;
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        for (Slice slice : slices) {
+            manufacturers[i++] = getManufacturer(em, slice);
+        }
+        em.getTransaction().commit();
+        return manufacturers;
+    }
+    
+    /**
+     * Create new car for each manufacture. 
+     * @param introduceError if true then one of the car will carry null VIN.
+     */
+    void persistCars(boolean introduceError) {
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        int i = introduceError ? rng.nextInt(manufacturers.length) : -1;
+        for (int j = 0; j < manufacturers.length; j++) {
+            Manufacturer maker = em.find(Manufacturer.class, manufacturers[j].getName());
+            Car car = newCar(maker);
+            em.persist(car);
+            if (i == j)
+                car.setVin(null); // this will make the commit fail
+        }
+        try {
+            em.getTransaction().commit();
+            if (introduceError) {
+                fail("Expected " + RollbackException.class.getName());
+            }
+        } catch (RollbackException e) {
+            if (!introduceError) {
+                fail("Expected " + RollbackException.class.getName());
+            } else {
+                // this is expected
+            }
+        }
+    }
+    
+    Car newCar(Manufacturer maker) {
+        Car car = new Car();
+        car.setVin(maker.getName().charAt(0) + randomString(6));
+        car.setMaker(maker);
+        return car;
+    }
+    
+    String randomString(int n) {
+        StringBuilder s = new StringBuilder();
+        for (int i = 0; i < n; i++) {
+            s.append(rng.nextInt(10));
+        }
+        return s.toString();
+    }
+    
+    /**
+     * A distribution policy that selects the slice based on Manufacturer.
+     * @author Pinaki Poddar
+     *
+     */
+    public static class CarDistributorPolicy implements DistributionPolicy {
+        @Override
+        public String distribute(Object pc, List<String> slices, Object context) {
+            if (pc instanceof Manufacturer) {
+                return ((Manufacturer)pc).getName();
+            } else if (pc instanceof Car) {
+                if (((Car) pc).getMaker() == null) {
+                    throw new RuntimeException("New " + pc + " must have a non-null Manufacturer");
+                }
+                return distribute(((Car)pc).getMaker(), slices, context);
+            }
+            throw new RuntimeException("No policy for " + pc.getClass().getName());
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestTransaction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml?rev=941541&r1=941540&r2=941541&view=diff
==============================================================================
--- openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml (original)
+++ openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml Wed May  5 23:28:26 2010
@@ -180,4 +180,53 @@
       </properties>
    </persistence-unit>
    
+   <persistence-unit name="car">
+   	  <class>org.apache.openjpa.slice.Car</class>
+   	  <class>org.apache.openjpa.slice.Manufacturer</class>
+   	  
+      <properties>
+         <property name="openjpa.BrokerFactory" value="slice"/>
+         <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver"/>
+
+         <property name="openjpa.slice.Names" value="BMW,Honda,Ford"/>
+         
+         <property name="openjpa.ConnectionUserName" value=""/>
+         <property name="openjpa.ConnectionPassword" value=""/>
+         
+         <property name="openjpa.slice.BMW.ConnectionURL" value="jdbc:derby:target/database/bmw;create=true"/>
+         <property name="openjpa.slice.Honda.ConnectionURL" value="jdbc:derby:target/database/honda;create=true"/>
+         <property name="openjpa.slice.Ford.ConnectionURL" value="jdbc:derby:target/database/ford;create=true"/>
+         
+         <property name="openjpa.Multithreaded" value="false"/>
+         <property name="openjpa.Log" value="DefaultLevel=INFO, Enhance=TRACE, SQL=TRACE"/>
+         <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=native"/>
+         <property name="openjpa.jdbc.MappingDefaults" value="DefaultMissingInfo=true"/>
+            <property name="openjpa.RuntimeUnenhancedClasses" value="unsupported"/>
+            <property name="openjpa.DynamicEnhancementAgent"   value="false"/>
+      </properties>
+   </persistence-unit>
+   
+   
+   <persistence-unit name="car.mysql">
+      <properties>
+         <property name="openjpa.BrokerFactory" value="slice"/>
+         <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
+
+         <property name="openjpa.slice.Names" value="BMW,Honda,Ford"/>
+         
+         <property name="openjpa.ConnectionUserName"        value="root"/>
+         <property name="openjpa.ConnectionPassword"        value=""/>
+         <property name="openjpa.slice.BMW.ConnectionURL" value="jdbc:mysql://localhost/bmw"/>
+         <property name="openjpa.slice.Honda.ConnectionURL" value="jdbc:mysql://localhost/ford"/>
+         <property name="openjpa.slice.Ford.ConnectionURL" value="jdbc:mysql://localhost/honda"/>
+         
+         <property name="openjpa.Multithreaded" value="false"/>
+         <property name="openjpa.jdbc.SynchronizeMappings" value="refresh"/>
+         <property name="openjpa.jdbc.MappingDefaults" value="DefaultMissingInfo=true"/>
+            <property name="openjpa.RuntimeUnenhancedClasses" value="unsupported"/>
+            <property name="openjpa.DynamicEnhancementAgent"   value="false"/>
+      </properties>
+   </persistence-unit>
+   
+   
 </persistence>