TOMEE-2295 Improvements for JPA/CMP mapping
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/b82b8e87 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/b82b8e87 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/b82b8e87 Branch: refs/heads/tomee-7.1.x Commit: b82b8e87611743739a506fccc2e88cfcff75c0f1 Parents: bf6a58b Author: Jonathan Gallimore <[email protected]> Authored: Wed Nov 28 13:53:40 2018 +0000 Committer: Otavio Santana <[email protected]> Committed: Mon Dec 17 13:56:00 2018 -0200 ---------------------------------------------------------------------- .../apache/openejb/config/CmpJpaConversion.java | 110 +++++++++++++------ .../openejb/core/LegacyInterfaceTest.java | 40 ++----- 2 files changed, 84 insertions(+), 66 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/b82b8e87/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java b/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java index 7f0e3f1..194bbd9 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java @@ -20,20 +20,7 @@ package org.apache.openejb.config; import org.apache.openejb.OpenEJBException; import org.apache.openejb.core.cmp.CmpUtil; import org.apache.openejb.core.cmp.jpa.JpaCmpEngine; -import org.apache.openejb.jee.CmpField; -import org.apache.openejb.jee.CmpVersion; -import org.apache.openejb.jee.EjbJar; -import org.apache.openejb.jee.EjbRelation; -import org.apache.openejb.jee.EjbRelationshipRole; -import org.apache.openejb.jee.EnterpriseBean; -import org.apache.openejb.jee.EntityBean; -import org.apache.openejb.jee.Multiplicity; -import org.apache.openejb.jee.PersistenceContextRef; -import org.apache.openejb.jee.PersistenceType; -import org.apache.openejb.jee.Query; -import org.apache.openejb.jee.QueryMethod; -import org.apache.openejb.jee.RelationshipRoleSource; -import org.apache.openejb.jee.Relationships; +import org.apache.openejb.jee.*; import org.apache.openejb.jee.jpa.AttributeOverride; import org.apache.openejb.jee.jpa.Attributes; import org.apache.openejb.jee.jpa.Basic; @@ -58,6 +45,7 @@ import org.apache.openejb.jee.jpa.unit.PersistenceUnit; import org.apache.openejb.jee.jpa.unit.TransactionType; import org.apache.openejb.jee.oejb3.EjbDeployment; import org.apache.openejb.jee.oejb3.OpenejbJar; +import org.apache.openejb.loader.IO; import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; @@ -67,6 +55,7 @@ import javax.ejb.EJBLocalObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -99,15 +88,38 @@ public class CmpJpaConversion implements DynamicDeployer { "serialVersionUID" ))); + public static EntityMappings readEntityMappings(final String location) { + + // first try the classpath + EntityMappings entitymappings = null; + + try { + final URL cpUrl = Thread.currentThread().getContextClassLoader().getResource(location); + entitymappings = (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(cpUrl)); + } catch (Exception e) { + // ignore + } + + if (entitymappings == null) { + // then try reading as a URL + try { + final URL url = new URL(location); + entitymappings = (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(url)); + } catch (Exception e) { + logger.error("Unable to read entity mappings from " + location, e); + } + } + + return entitymappings; + } + public AppModule deploy(final AppModule appModule) throws OpenEJBException { if (!hasCmpEntities(appModule)) { return appModule; } - // todo scan existing persistence module for all entity mappings and don't generate mappings for them - - // create mappings if no mappings currently exist + // create mappings if no mappings currently exist EntityMappings cmpMappings = appModule.getCmpMappings(); if (cmpMappings == null) { cmpMappings = new EntityMappings(); @@ -115,6 +127,23 @@ public class CmpJpaConversion implements DynamicDeployer { appModule.setCmpMappings(cmpMappings); } + // todo scan existing persistence module for all entity mappings and don't generate mappings for them + + final Set<String> definedMappedClasses = new HashSet<>(); + + // check for an existing "cmp" persistence unit, and look at existing mappings + final PersistenceUnit cmpPersistenceUnit = findCmpPersistenceUnit(appModule); + if (cmpPersistenceUnit != null) { + if (cmpPersistenceUnit.getMappingFile() != null || cmpPersistenceUnit.getMappingFile().size() > 0) { + for (final String mappingFile : cmpPersistenceUnit.getMappingFile()) { + final EntityMappings entityMappings = readEntityMappings(mappingFile); + if (entityMappings != null) { + definedMappedClasses.addAll(entityMappings.getEntityMap().keySet()); + } + } + } + } + // we process this one jar-file at a time...each contributing to the // app mapping data for (final EjbModule ejbModule : appModule.getEjbModules()) { @@ -123,7 +152,7 @@ public class CmpJpaConversion implements DynamicDeployer { // scan for CMP entity beans and merge the data into the collective set for (final EnterpriseBean enterpriseBean : ejbJar.getEnterpriseBeans()) { if (isCmpEntity(enterpriseBean)) { - processEntityBean(ejbModule, cmpMappings, (EntityBean) enterpriseBean); + processEntityBean(ejbModule, definedMappedClasses, cmpMappings, (EntityBean) enterpriseBean); } } @@ -152,7 +181,6 @@ public class CmpJpaConversion implements DynamicDeployer { for (final MappedSuperclass mapping : userMappings.getMappedSuperclass()) { logger.warning("openejb-cmp-orm.xml mapping ignored: module=" + ejbModule.getModuleId() + ": <mapped-superclass class=\"" + mapping.getClazz() + "\">"); } - } if (!cmpMappings.getEntity().isEmpty()) { @@ -160,7 +188,9 @@ public class CmpJpaConversion implements DynamicDeployer { persistenceUnit.getMappingFile().add("META-INF/openejb-cmp-generated-orm.xml"); for (final Entity entity : cmpMappings.getEntity()) { - persistenceUnit.getClazz().add(entity.getClazz()); + if (! persistenceUnit.getClazz().contains(entity.getClazz())) { + persistenceUnit.getClazz().add(entity.getClazz()); + } } } @@ -176,17 +206,7 @@ public class CmpJpaConversion implements DynamicDeployer { private PersistenceUnit getCmpPersistenceUnit(final AppModule appModule) { // search for the cmp persistence unit - PersistenceUnit persistenceUnit = null; - for (final PersistenceModule persistenceModule : appModule.getPersistenceModules()) { - final Persistence persistence = persistenceModule.getPersistence(); - for (final PersistenceUnit unit : persistence.getPersistenceUnit()) { - if (CMP_PERSISTENCE_UNIT_NAME.equals(unit.getName())) { - persistenceUnit = unit; - break; - } - - } - } + PersistenceUnit persistenceUnit = findCmpPersistenceUnit(appModule); // if not found create one if (persistenceUnit == null) { persistenceUnit = new PersistenceUnit(); @@ -215,6 +235,21 @@ public class CmpJpaConversion implements DynamicDeployer { return persistenceUnit; } + private PersistenceUnit findCmpPersistenceUnit(final AppModule appModule) { + PersistenceUnit persistenceUnit = null; + for (final PersistenceModule persistenceModule : appModule.getPersistenceModules()) { + final Persistence persistence = persistenceModule.getPersistence(); + for (final PersistenceUnit unit : persistence.getPersistenceUnit()) { + if (CMP_PERSISTENCE_UNIT_NAME.equals(unit.getName())) { + persistenceUnit = unit; + break; + } + + } + } + return persistenceUnit; + } + private String getPersistenceModuleId(final AppModule appModule) { if (appModule.getModuleId() != null) { return appModule.getModuleId(); @@ -437,12 +472,14 @@ public class CmpJpaConversion implements DynamicDeployer { /** * Generate the CMP mapping data for an individual * EntityBean. - * - * @param ejbModule The module containing the bean. + * @param ejbModule The module containing the bean. + * @param ignoreClasses * @param entityMappings The accumulated set of entity mappings. * @param bean The been we're generating the mapping for. */ - private void processEntityBean(final EjbModule ejbModule, final EntityMappings entityMappings, final EntityBean bean) { + private void processEntityBean(final EjbModule ejbModule, final Collection<String> ignoreClasses, + final EntityMappings entityMappings, final EntityBean bean) { + // try to add a new persistence-context-ref for cmp if (!addPersistenceContextRef(bean)) { // Bean already has a persistence-context-ref for cmp @@ -478,6 +515,11 @@ public class CmpJpaConversion implements DynamicDeployer { } } + // Check that this mapping hasn't already been defined in another mapping file on the persistence unit + if (ignoreClasses.contains(jpaEntityClassName)) { + return; + } + // Look for an existing mapping using the openejb generated subclass name Entity entity = removeEntity(userMappings, jpaEntityClassName); http://git-wip-us.apache.org/repos/asf/tomee/blob/b82b8e87/container/openejb-core/src/test/java/org/apache/openejb/core/LegacyInterfaceTest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/core/LegacyInterfaceTest.java b/container/openejb-core/src/test/java/org/apache/openejb/core/LegacyInterfaceTest.java index 0b4b73f..0e1f2d7 100644 --- a/container/openejb-core/src/test/java/org/apache/openejb/core/LegacyInterfaceTest.java +++ b/container/openejb-core/src/test/java/org/apache/openejb/core/LegacyInterfaceTest.java @@ -253,43 +253,16 @@ public class LegacyInterfaceTest extends TestCase { throw new Exception("Failed to create test directory: " + f); } - final EntityMappings entityMappings = new EntityMappings(); - - final Entity entity = new Entity(); - entity.setClazz("openejb.org.apache.openejb.core.MyCmpBean"); - entity.setName("MyCmpBean"); - entity.setDescription("MyCmpBean"); - entity.setAttributes(new Attributes()); - - final NamedQuery namedQuery = new NamedQuery(); - namedQuery.setQuery("SELECT OBJECT(DL) FROM License DL"); - entity.getNamedQuery().add(namedQuery); - - final Id id = new Id(); - id.setName("id"); - entity.getAttributes().getId().add(id); - - final Basic basic = new Basic(); - basic.setName("name"); - final Column column = new Column(); - column.setName("wNAME"); - column.setLength(300); - basic.setColumn(column); - entity.getAttributes().getBasic().add(basic); - - entityMappings.getEntity().add(entity); - final AppModule module = new AppModule(this.getClass().getClassLoader(), f.getAbsolutePath()); final EjbModule ejbModule = new EjbModule(ejbJar); - Persistence persistence = new Persistence(); PersistenceUnit pu = persistence.addPersistenceUnit("cmp"); pu.setTransactionType(TransactionType.JTA); pu.setJtaDataSource("fake"); pu.setNonJtaDataSource("fake"); pu.getMappingFile().add("test-orm.xml"); - pu.addClass("openejb.org.apache.openejb.core.MyCmpBean"); + pu.getClazz().add("openejb.org.apache.openejb.core.MyCmpBean"); module.addPersistenceModule(new PersistenceModule("pu", persistence)); module.getEjbModules().add(ejbModule); @@ -297,12 +270,15 @@ public class LegacyInterfaceTest extends TestCase { assertNull(module.getCmpMappings()); assembler.createApplication(config.configureApplication(module)); assertNotNull(module.getCmpMappings()); + + // no mapping should be automatically generated + assertTrue(module.getCmpMappings().getEntityMap().isEmpty()); + + // pu should not be modified, no duplicate classes assertEquals(1, pu.getClazz().size()); assertEquals("openejb.org.apache.openejb.core.MyCmpBean", pu.getClazz().get(0)); - final List<Basic> basicList = module.getCmpMappings().getEntityMap().get("openejb.org.apache.openejb.core.MyCmpBean").getAttributes().getBasic(); - assertEquals(1, basicList.size()); - assertEquals(300, basicList.get(0).getColumn().getLength().intValue()); - assertEquals("wNAME", basicList.get(0).getColumn().getName()); + assertEquals(1, pu.getMappingFile().size()); + assertEquals("test-orm.xml", pu.getMappingFile().get(0)); } @LocalHome(MyLocalHome.class)
