Search code examples
javaeclipsejpaeclipselinkpersistence.xml

Eclipselink: error writing objects to/retrieving objects from persistence database


I recently switched development machines and now writing objects to/retrieving objects from the persistence database is not working any longer. This happens when I try to debug the webapp project on my new machine. It works on my old laptop but somehow won't on the new one. I also deployed the webapp to an server and there everything works as expected.

I get the following two error message while interacting with the database:

Writing objects to the database:

SEVERE: Exception sending context initialized event to listener instance of class org.example.webapp.startup.ServletContextClass
java.lang.IllegalArgumentException: Object: org.example.utility.trs.objects.ChangeLog@789a464b is not a known entity type.
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4222)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:496)
    at org.example.webapp.changelog.dao.ChangeLogDao.addChangeLog(ChangeLogDao.java:42)
    at org.example.webapp.startup.ServletContextClass.initializeChangeLog(ServletContextClass.java:104)
    at org.example.webapp.startup.ServletContextClass.contextInitialized(ServletContextClass.java:59)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Code to write to the database:

public void addChangeLog(ChangeLog changeLog, EntityManagerFactory emf) {

    String changeLogId = changeLog.getModelResource();

    if(!contentProvider.containsKey(changeLogId)) {

        //create new user
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();

        em.persist(changeLog);

        em.getTransaction().commit();
        em.close();

        contentProvider.put(changeLogId, changeLog);
    }

Retrieving objects from the database:

SEVERE: Exception sending context initialized event to listener instance of class org.example.webapp.startup.ServletContextClass
java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Problem compiling [SELECT c FROM ChangeLog c]. 
[14, 23] The abstract schema type 'ChangeLog' is unknown.
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1585)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1605)
    at org.example.webapp.startup.ServletContextClass.contextInitialized(ServletContextClass.java:59)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Code to read from the database:

List<ChangeLog> changeLogList = em.createQuery("SELECT c FROM ChangeLog c",
                                                ChangeLog.class).getResultList();

Here is how the ChangeLog class looks like:

package org.example.utility.trs.objects;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@NamedQuery(name="ChangeLog.findAll", query="SELECT c FROM ChangeLog c")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ChangeLog  implements Serializable {

    private static final long serialVersionUID = 123L;

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long changeLogId;
    ...
}

This is the persistence.xml file:

<?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="webapp-name"  transaction-type="RESOURCE_LOCAL">

        <class>org.example.utility.trs.objects.ChangeLog</class>

        <exclude-unlisted-classes>false</exclude-unlisted-classes>

        <properties>        

            <!-- mysql persistence driver -->
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/persistence"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.username" value="admin"/>
            <property name="javax.persistence.jdbc.password" value="password"/>

            <!-- EclipseLink should create the database schema automatically -->
            <property name="eclipselink.ddl-generation.output-mode" value="database" />
            <property name="javax.persistence.jdbc.user" value="admin"/>
        </properties>
    </persistence-unit>
</persistence>

Here is the part of the pom.xml file that includes the persistence libraries. I can post the whole file if this of any assistence:

<!-- persistence api -->
<dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.0-api</artifactId>
    <version>1.0.1.Final</version>
</dependency>

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.5.0</version>
</dependency>

I can connect to the database and there is a table with content that I was able to create and read on my old development machine. Thus I assume that the issue is rather with the configuration of eclipselink than an actual problem in the code. Maybe it is an issue with the configuration of the JPA facet in the eclipse project.

However I have no idea how to debug this issue.

On the other hand the ChangeLog class is in a from a different project that is stored in my local Maven repository and is not defined in the webapp project. So this might be an issue. This was never a problem on my old machine though.

Any help is appreciated


Solution

  • So after some testing I finally figured out what went wrong. I leave this here if anyone else comes across this problem.

    It turned out that while deploying the code to the new development machine I changed some of the dependency versions in my pom.xml file. So I created the database table with version 2.6.4 of the eclipselink API.

    On the new development machine I changed it to version 2.5 and recompiled the project which broke the extraction of the objects from the database.

    Once I changed the version back it worked again.