Entity enhancement on OpenJPA 2.x

3.1k Views Asked by At

I am working on project with Spring and OpenJPA. I have a use case where I need to create entities of same data source in different projects/maven modules.

Approach 1:

I have Maven project core-entities having two modules containing set of entities with specific functionality.

Module A - Enitity1, Enitity2, Enitity3 Module B – Enitity4, Enitity5, Enitity6

I have a created separate persistence units and persistence xml for each set of entities. It works fine when entities are enhanced in their respective maven modules.

Approach 2: In this approach I have separate modules for entities as above but the only difference is that I am using a single persistence unit for both set of entities. I have added the openjpa-maven-plugin for enhancing entities in both the modules. In this case when entities are enhanced using maven plugin it gives exception saying no metadata found for entities in Module A at runtime. Is it because when the entities are enhanced, somehow metadata of entities in Module A is lost at runtime.This problem does not come with entities of module B.

I have few questions around this issue:

1)Is it recommended to have multiple persistence units for same data source (as done in Approach 1)?

2)Is there any way by which I can enhance entities in single persistence unit and different maven modules?

3)Are the any alternate approaches of entities enhancement other than using eclipse and maven plugin?

Below is the plugin in pom.xml of each module:

<build>
        <plugins>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>openjpa-maven-plugin</artifactId>
                <version>1.1</version>
                <configuration>
                    <includes>**/entity/**/*.class</includes>
                    <addDefaultConstructor>true</addDefaultConstructor>
                    <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
                    <persistenceXmlFile>${basedir}/src/main/resources/META-INF/moduleApersistence.xml</persistenceXmlFile>
                </configuration>
                <executions>
                    <execution>
                        <id>enhancer</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.openjpa</groupId>
                        <artifactId>openjpa</artifactId>
                        <version>${openjpa.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings 
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.apache.openjpa
                                        </groupId>
                                        <artifactId>
                                            openjpa-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [2.2.0,)
                                        </versionRange>
                                        <goals>
                                            <goal>enhance</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.codehaus.mojo
                                        </groupId>
                                        <artifactId>
                                            cobertura-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [2.5.2,)
                                        </versionRange>
                                        <goals>
                                            <goal>instrument</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
1

There are 1 best solutions below

0
On

It's generally a good idea to group functional concepts into modules. Following that idea, it makes sense that the classes describing the functional concepts of ModuleA are contained within ModuleA, not spread according to their technical implementation.

  1. Single or multiple persistence units: It depends on your application and dependencies between your domain objects. Each persistence unit will have its own 1st level cache (read more here). Summarized in one line, this means that a row representing Entity4 will be mapped to different instances within the same transaction depending on which persistence unit was queried. For instance entityManager.find(Entity4.class, 3L) in ModuleB will return a different instance than the one you would get in a OneToMany in Entity3 in ModuleA since Entity3 and Entity4 are in different persistence units.

    In general, you keep entities that have nothing to do with each other in different persistence units, and entities that are correlated somehow in the same persistence unit. My advise is to keep to one persistence unit unless you're sure you'll benefit from several. Keep it simple, avoid complexity if you can.

  2. Yes. Place your persistence.xml in a separate module. Configure the openjpa-maven-plugin in the parent pom and then load it in the modules containing entities.

parent-pom.xml:

    <pluginManagement><plugins>
    ...
    <plugin>
        <groupId>org.apache.openjpa</groupId>
        <artifactId>openjpa-maven-plugin</artifactId>
        <version>${openjpa-maven-plugin.version}</version>
        <executions>
            <execution>
                <id>enhancer</id>
                <phase>process-classes</phase>
                <goals>
                    <goal>enhance</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <addDefaultConstructor>true</addDefaultConstructor>
            <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
            <persistenceXmlFile>${project.parent.basedir}/module-infra/src/main/resources/META-INF/persistence.xml</persistenceXmlFile>
        </configuration>
        <dependencies>
            <dependency>
                <groupId>org.apache.openjpa</groupId>
                <artifactId>openjpa</artifactId>
                <version>${openjpa.version}</version>
            </dependency>
        </dependencies>
    </plugin>

ModuleA and ModuleB pom.xml:

    <build><plugins>
    <plugin>
        <groupId>org.apache.openjpa</groupId>
        <artifactId>openjpa-maven-plugin</artifactId>
        <configuration>
            <includes>
                **/*SomeEntity.class
            </includes>
        </configuration>
    </plugin>

module-infra/../persistence.xml (configures a non-jta datasource in an osgi container)

    <?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="yourPersistenceUnit" transaction-type="RESOURCE_LOCAL">
            <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>

            <non-jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=somedb)</non-jta-data-source>

            <class>com.example.modulea.Entity1</class>
            <class>com.example.moduleb.Entity3</class>

            <exclude-unlisted-classes>true</exclude-unlisted-classes>

            <properties>
                <property name="openjpa.TransactionMode" value="local"/>
                <property name="openjpa.ConnectionFactoryMode" value="local"/>
                <property name="openjpa.Log" value="slf4j"/>
            </properties>
        </persistence-unit>
    </persistence>

  1. Not that I know of. The maven plugin should suffice though. I've never used the eclipse plugin.