Repository: ambari Updated Branches: refs/heads/trunk ac508b8df -> 1cdf8864c
AMBARI-11957 - Views : DataStore persistence error (tbeerbower) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1cdf8864 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1cdf8864 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1cdf8864 Branch: refs/heads/trunk Commit: 1cdf8864c1d52d44a910b836e31acf6f6ded161d Parents: ac508b8 Author: tbeerbower <tbeerbo...@hortonworks.com> Authored: Tue Jun 16 17:36:51 2015 -0400 Committer: tbeerbower <tbeerbo...@hortonworks.com> Committed: Tue Jun 16 17:36:59 2015 -0400 ---------------------------------------------------------------------- .../server/view/persistence/DataStoreImpl.java | 30 +++-- .../view/persistence/DataStoreImplTest.java | 121 +++++++++++++++++++ 2 files changed, 144 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/1cdf8864/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java index 8353d63..69328e7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/persistence/DataStoreImpl.java @@ -25,14 +25,17 @@ import org.apache.ambari.view.PersistenceException; import org.eclipse.persistence.dynamic.DynamicClassLoader; import org.eclipse.persistence.dynamic.DynamicEntity; import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.helper.DatabaseField; import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper; import org.eclipse.persistence.jpa.dynamic.JPADynamicTypeBuilder; +import org.eclipse.persistence.mappings.DirectToFieldMapping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; import javax.persistence.Query; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -41,6 +44,8 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; +import java.sql.Clob; +import java.sql.Types; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -131,9 +136,7 @@ public class DataStoreImpl implements DataStore { persistEntity(entity, em, new HashSet<DynamicEntity>()); em.getTransaction().commit(); } catch (Exception e) { - if (em.getTransaction()!= null) { - em.getTransaction().rollback(); - } + rollbackTransaction(em.getTransaction()); throwPersistenceException("Caught exception trying to store view entity " + entity, e); } } finally { @@ -162,9 +165,7 @@ public class DataStoreImpl implements DataStore { em.remove(dynamicEntity); em.getTransaction().commit(); } catch (Exception e) { - if (em.getTransaction()!= null) { - em.getTransaction().rollback(); - } + rollbackTransaction(em.getTransaction()); throwPersistenceException("Caught exception trying to remove view entity " + entity, e); } } @@ -297,7 +298,15 @@ public class DataStoreImpl implements DataStore { Class<?> propertyType = descriptor.getPropertyType(); if (isDirectMappingType(propertyType)) { - typeBuilder.addDirectMapping(attributeName, propertyType, attributeName); + DirectToFieldMapping mapping = typeBuilder.addDirectMapping(attributeName, propertyType, attributeName); + + // explicitly set the type of string fields + if (String.class.isAssignableFrom(propertyType)) { + DatabaseField field = mapping.getField(); + + field.setSqlType(Types.CLOB); + field.setType(Clob.class); + } } } } @@ -593,6 +602,13 @@ public class DataStoreImpl implements DataStore { return (Class<?>) parameterizedType.getActualTypeArguments()[0]; } + // rollback the given transaction if it is active + private static void rollbackTransaction(EntityTransaction transaction) { + if (transaction != null && transaction.isActive()) { + transaction.rollback(); + } + } + // throw a new persistence exception and log the error private static void throwPersistenceException(String msg, Exception e) throws PersistenceException { LOG.error(msg, e); http://git-wip-us.apache.org/repos/asf/ambari/blob/1cdf8864/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java index 2b19b0a..d623a26 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/persistence/DataStoreImplTest.java @@ -139,6 +139,67 @@ public class DataStoreImplTest { } @Test + public void testStore_create_longStringValue() throws Exception { + DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader()); + + // create mocks + EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class); + EntityManager entityManager = createMock(EntityManager.class); + JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class); + SchemaManager schemaManager = createNiceMock(SchemaManager.class); + EntityTransaction transaction = createMock(EntityTransaction.class); + + // set expectations + Capture<DynamicType> typeCapture = new Capture<DynamicType>(); + Capture<DynamicType> typeCapture2 = new Capture<DynamicType>(); + jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture), capture(typeCapture2)); + + expect(entityManagerFactory.createEntityManager()).andReturn(entityManager); + expect(entityManager.getTransaction()).andReturn(transaction).anyTimes(); + + Capture<Class> entityClassCapture = new Capture<Class>(); + expect(entityManager.find(capture(entityClassCapture), eq("bar"))).andReturn(null); + + Capture<Class> entityClassCapture2 = new Capture<Class>(); + expect(entityManager.find(capture(entityClassCapture2), eq(99))).andReturn(null); + + Capture<DynamicEntity> entityCapture = new Capture<DynamicEntity>(); + entityManager.persist(capture(entityCapture)); + + Capture<DynamicEntity> entityCapture2 = new Capture<DynamicEntity>(); + entityManager.persist(capture(entityCapture2)); + + entityManager.close(); + + transaction.begin(); + transaction.commit(); + + // replay mocks + replay(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager); + + DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager); + + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < 5000; ++i) { + sb.append("A"); + } + String longString = sb.toString(); + + dataStore.store(new TestEntity(99, longString, new TestSubEntity("bar"))); + + Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass()); + Assert.assertEquals(entityClassCapture2.getValue(), typeCapture2.getValue().getJavaClass()); + + Assert.assertEquals("bar", entityCapture.getValue().get("DS_name")); + + Assert.assertEquals(99, entityCapture2.getValue().get("DS_id")); + Assert.assertEquals(longString, entityCapture2.getValue().get("DS_name")); + + // verify mocks + verify(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager); + } + + @Test public void testStore_update() throws Exception { DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader()); @@ -193,6 +254,66 @@ public class DataStoreImplTest { } @Test + public void testStore_update_longStringValue() throws Exception { + DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader()); + + // create mocks + EntityManagerFactory entityManagerFactory = createMock(EntityManagerFactory.class); + EntityManager entityManager = createMock(EntityManager.class); + JPADynamicHelper jpaDynamicHelper = createNiceMock(JPADynamicHelper.class); + SchemaManager schemaManager = createNiceMock(SchemaManager.class); + EntityTransaction transaction = createMock(EntityTransaction.class); + DynamicEntity dynamicEntity = createMock(DynamicEntity.class); + + // set expectations + Capture<DynamicType> typeCapture = new Capture<DynamicType>(); + Capture<DynamicType> typeCapture2 = new Capture<DynamicType>(); + jpaDynamicHelper.addTypes(eq(true), eq(true), capture(typeCapture), capture(typeCapture2)); + + expect(entityManagerFactory.createEntityManager()).andReturn(entityManager); + expect(entityManager.getTransaction()).andReturn(transaction).anyTimes(); + + Capture<Class> entityClassCapture = new Capture<Class>(); + expect(entityManager.find(capture(entityClassCapture), eq("bar"))).andReturn(null); + + Capture<Class> entityClassCapture2 = new Capture<Class>(); + expect(entityManager.find(capture(entityClassCapture2), eq(99))).andReturn(dynamicEntity); + + Capture<DynamicEntity> entityCapture = new Capture<DynamicEntity>(); + entityManager.persist(capture(entityCapture)); + + entityManager.close(); + + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < 5000; ++i) { + sb.append("A"); + } + String longString = sb.toString(); + + expect(dynamicEntity.set("DS_id", 99)).andReturn(dynamicEntity); + expect(dynamicEntity.set("DS_name", longString)).andReturn(dynamicEntity); + + Capture<DynamicEntity> subEntityCapture = new Capture<DynamicEntity>(); + expect(dynamicEntity.set(eq("DS_subEntity"), capture(subEntityCapture))).andReturn(dynamicEntity); + + transaction.begin(); + transaction.commit(); + + // replay mocks + replay(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity); + + DataStoreImpl dataStore = getDataStore(entityManagerFactory, jpaDynamicHelper, classLoader, schemaManager); + + dataStore.store(new TestEntity(99, longString, new TestSubEntity("bar"))); + + Assert.assertEquals(entityClassCapture.getValue(), typeCapture.getValue().getJavaClass()); + Assert.assertEquals(entityClassCapture2.getValue(), typeCapture2.getValue().getJavaClass()); + + // verify mocks + verify(entityManagerFactory, entityManager, jpaDynamicHelper, transaction, schemaManager, dynamicEntity); + } + + @Test public void testRemove() throws Exception { DynamicClassLoader classLoader = new DynamicClassLoader(DataStoreImplTest.class.getClassLoader());