7

I've been trying to refactor a java project, moving submodules into separate projects deployed to our internal maven repository (archiva).

The classes from the submodules are the following:

org.example.srv.DomainUser
org.example.srv.DomainUserBean //entity manager
org.example.srv.UserGroup
org.example.srv.UserGroupBean //entity manager

It works fine when the source files are copied into the appropriate package folder inside of the main backend server project, but when we remove the source files from the backend server project and pull the same code in as a maven dependency, I get the following error upon attempting to access the database:

org.hibernate.UnknownEntityTypeException: Unable to locate persister: org.example.srv.DomainUser

Persistence XML for backend server project:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="loginserver">
    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
    </properties>
</persistence-unit>
</persistence>

I can only imagine that it is something to do with the bean discovery when the projects are separate, but I'm really perplexed and it would be great to separate these projects with minimal configuration overhead.

Main server project pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example.srv</groupId>
    <artifactId>loginserver</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.unboundid</groupId>
            <artifactId>unboundid-ldapsdk</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>authobjects</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>loginserver</finalName>
    </build>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
</project>

Auth Objects pom.xml (this project also contains ORM code for the classes, including JPQL statement builders, etc.):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <properties>
        <pj.gid>org.example</pj.gid>
        <pj.aid>authobjects</pj.aid>
        <pj.ver>1.0.2-SNAPSHOT</pj.ver>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <groupId>${pj.gid}</groupId>
    <artifactId>${pj.aid}</artifactId>
    <version>${pj.ver}</version>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>ent.tnp.utils</groupId>
            <artifactId>genericentityejb</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <extension>
                <groupId>org.apache.maven.wagon</groupId>
                <artifactId>wagon-webdav</artifactId>
                <version>1.0-beta-2</version>
            </extension>
        </extensions>
    </build>

    <distributionManagement>
        <repository>
            <id>internal</id>
            <url>http://archiva.tnp.in/repository/internal/</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <url>http://archiva.tnp.in/repository/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <repositories>
        <repository>
            <id>internal</id>
            <name>Archiva Managed Internal Repository</name>
            <url>http://archiva.tnp.in/repository/internal/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>snapshots</id>
            <name>Archiva Managed Snapshot Repository</name>
            <url>http://archiva.tnp.in/repository/snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>internal</id>
            <name>Archiva Managed Internal Repository</name>
            <url>http://archiva.tnp.in/repository/internal/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>snapshots</id>
            <name>Archiva Managed Snapshot Repository</name>
            <url>http://archiva.tnp.in/repository/snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

Clarification: genericentityejb is an abstract class designed to compose JPQL queries and manage database queries for a JPA entity. The authobjects project extends it once for each of the entities it contains in order to provide persistence for each of those entities.

KG6ZVP
  • 3,610
  • 4
  • 26
  • 45
  • How do you add persistent classes to the Hibernate configuration? – v.ladynev Mar 05 '17 at 19:30
  • I configured them to auto-discover through the JPA settings window in JBoss Developer Studio (eclipse-based). I'm still new to JPA/Hibernte. Adding 'false' to the persistence.xml of the project with the JPA stuff doesn't seem to help, either. – KG6ZVP Mar 05 '17 at 22:44
  • This seems more a maven/archiva problem. Is your dependency `SNAPSHOT`? Is the **latest** build deployed correctly to archiva? There are any MD5 warn? Did you check that's correctly downloaded and packaged? Is the main module a WAR/EAR? Showing both POMs should help. – Michele Mariotti Mar 07 '17 at 09:32
  • The main module is a war deployed to Wildfly 10. Question edited to show both POMs – KG6ZVP Mar 07 '17 at 22:35

2 Answers2

3

From what I see there are at least 4 modules involved:

  • org.example.srv:loginserver:0.0.2-SNAPSHOT

    • org.example:authobjects:1.0.0
  • org.example:authobjects:1.0.2-SNAPSHOT

    • ent.tnp.utils:genericentityejb:1.0.0

and I note some possible criticality:

  1. loginserver is not depending on authobjects, but on genericentityejb (are they two unrelated example projects?).
  2. loginserver is not depending on authobjects:1.0.2-SNAPSHOT, but on authobjects:1.0.0
  3. loginserver is not declaring any repository (neither a parent POM), so genericentityejb is always resolved from your local machine repository, unless you declared repositories in global settings.xml (that's OK).
  4. I'm not sure it's a good idea to use properties for the authobjects project groupId, artifactId and version. Maybe it's not related, but I'd avoid such declaration.

That being said, I'm using a similar structure for my projects, deploying to Wildfly 10.1, and Hibernate correctly discovers all entities in all dependencies.

So I'd try a clean round. I'll ignore authobjects since it's not referenced and I suppose required entity classes are in genericentityejb:

  1. modify genericentityejb POM version to 1.0.1-SNAPSHOT
  2. from genericentityejb folder: mvn clean install
  3. modify authobjects POM version to 1.0.3-SNAPSHOT and dependency genericentityejb to 1.0.1-SNAPSHOT
  4. from authobjects folder: mvn clean install
  5. modify loginserver dependency authobjects to 0.0.3-SNAPSHOT and dependency authobjects to 1.0.3-SNAPSHOT
  6. from loginserver folder: mvn dependency:analyze to check for used undeclared deps (maybe genericentityejb?)
  7. from loginserver folder: mvn clean package
  8. check if loginserver/target/loginserver-0.0.3-SNAPSHOT.war!/WEB-INF/lib/genericentityejb-1.0.3-SNAPSHOT.jar and loginserver/target/loginserver-0.0.3-SNAPSHOT.war!/WEB-INF/lib/authobjects-0.0.3-SNAPSHOT.jar are present and contain all the entity classes.

Also it could be useful to look at the loginserver effective POM


declaring repositories in pom.xml or settings.xml is a personal choice. Both approaches have pros and cons:

  • copy'n'paste repositories

    • pom: for each new project
    • settings: for each new machine (developer, CI env, ...)
  • edit a repo URL

    • pom: for each project
    • settings: for each machine
  • when you release an artifact:

    • pom: repo refes are carved in stone for that version
    • settings: repo refes used in that version are not saved
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73
  • I included the wrong version of the pom.xml. I've updated my question with the correct pom.xml. The one I included previously was the one using git submodule to include the dependency we're trying to use maven for. – KG6ZVP Mar 09 '17 at 00:37
  • Would you recommend declaring repositories in the pom.xml? It's currently configured in the settings.xml file. – KG6ZVP Mar 09 '17 at 01:55
1

You can add <jar-file> element, containing path to the jar with entity clases, to the persistence.xml or describe all entity classes using <class> element.

Also, you can add entity classes programmatically using some package scanning approach. I have collected useful links and libraries for such approach here:

https://github.com/v-ladynev/hibernate-scanners-test

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
  • Adding a seems like a very bad idea with Maven and using is highly undesirable. What exactly is happening to the entity classes in the separate Maven artifact vs inside the project? On startup, the container appears to scan them properly. – KG6ZVP Mar 06 '17 at 17:00
  • @KG6ZVP I don't really know what happens there. Scanning for classes is not a simply task in Java. Jars are processed separately as zip archives. I have updated my answer. – v.ladynev Mar 06 '17 at 17:46
  • I'm trying to avoid adding anything for the classes besides the maven dependency and any 'regular' code that would make use of them. Since there are ways to avoid this in other projects, I'm trying to figure out how to do this while also mixing in Maven. – KG6ZVP Mar 07 '17 at 01:18