Tomcat Classloader findet bei JPA-Persistierung die Persistence Unit nicht.

Ich verstehe nicht, wieso ich eine einfache Entity-Klasse (mit dem Namen Entity) nicht vermittels JPA persistieren kann. Der Apache-Log sagt:



15-Sep-2019 09:48:24.223 SEVERE [http-nio-8080-exec-20] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [DB] in context with path [/mave] threw exception

[ObjectDB 2.8.1] javax.persistence.PersistenceException

Persistence unit 'entities' is not found (by org.apache.catalina.loader.ParallelWebappClassLoader) (error 222)
at com.objectdb.jpa.Provider.createEntityManagerFactory(Provider.java:88)
at com.objectdb.jpa.Provider.createEntityManagerFactory(Provider.java:32)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:74)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:49)
at com.mavenproject.mave.PersistEntity.persist(PersistEntity.java:26)
at com.mavenproject.mave.DB.write(DB.java:152)
at com.mavenproject.mave.DB.doPost(DB.java:82)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:835)

Caused by: com.objectdb.o.UserException: Persistence unit 'entities' is not found (by org.apache.catalina.loader.ParallelWebappClassLoader)

at com.objectdb.o.MSG.a(MSG.java:64)
at com.objectdb.o.UNM.q(UNM.java:79)
at com.objectdb.jpa.Provider.createEntityManagerFactory(Provider.java:58)
... 30 more

Nun sieht die Sache bei mir so aus, dass ich eine PersistEntity-Klasse habe, in der ich eine persist-Methode aufrufe, der ein String übergeben ist. Jedoch scheitert es schon bei der Erschaffung der EntityManagerFactory:



Java:
/*

* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.

*/

package com.mavenproject.mave;

import javax.persistence.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class PersistEntity {

private static final String PERSISTENCE_UNIT_NAME = "entities";
private static EntityManagerFactory factory;
private static final Logger LOGGER = Logger.getLogger(PersistEntity.class.getName());

void persist(String data) {

LOGGER.log(Level.SEVERE, "Create entity manager.");

factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

// EntityManager em = factory.createEntityManager();

LOGGER.log(Level.SEVERE, "Entity manager created.");

. . .

         }

}

Dabei habe ich eine persistence.xml, mit welcher das gehen müsste:


HTML:
<persistence>
<persistence-unit name="entities">
<class>com.mavenproject.mave.Entity</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/userdata;create=true"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="eclipselink.logging.level" value="SEVERE"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
</properties>
</persistence-unit>
</persistence>

Die Struktur meines Webprojekts habe ich mal als Anhang angefügt.
 

Anhänge

Leider ist da erneut etwas, das ich nicht verstehe. Zwar kann ich nun wie gesagt eine EntityManagerFactory erzeugen, aber schon bei dem Entity Manager tritt ein neues Problem auf, das ich nicht verstehe. Meine persistence.xml sieht wie folgt aus:

HTML:
<persistence version="2.0" 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">   
        
    <persistence-unit name="entity" transaction-type="RESOURCE_LOCAL">           
        <class>com.mavenproject.mave.Entity</class> 
      
    <properties> 
    <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
    <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/userdata"/>
    <property name="javax.persistence.jdbc.user" value="root"/> 
    <property name="javax.persistence.jdbc.password" value="root"/> 
    <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
    <property name="eclipselink.logging.level" value="SEVERE"/> 
    <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/> 
    </properties> 
      
     </persistence-unit>
            
    </persistence>
Ich habe auf meinem Datenbankserver eine Datenbank namens userdata angelegt. Wenn ich nun die Entity persistieren will, kommt der Fehler: "Failed to create a new file 'jdbc:mysql://localhost:3306/userdata", diese Exception wird bei dem Methodenaufruf "factory.createEntityManager();" ausgelöst:

Java:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mavenproject.mave;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class PersistEntity {

    private static final String PERSISTENCE_UNIT_NAME = "entity";
    private static EntityManagerFactory factory;

    private static final Logger LOGGER = Logger.getLogger(PersistEntity.class.getName());

    void persist(String data) {

        LoggerSetup.getInstance().doSetup(LOGGER);

        try {

            factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

        } catch (Exception e) {

            LOGGER.log(Level.SEVERE, "Encountered PersistException. - " + e.getMessage());

        }

                    LOGGER.log(Level.SEVERE, "Entity manager factory created.");
        
        EntityManager em = null;

        try {

            em = factory.createEntityManager();

        } catch (Exception e) {

            LOGGER.log(Level.SEVERE, "Encountered PersistException. - " + e.getMessage());

        }

        if (em != null) {

            LOGGER.log(Level.SEVERE, "Entity manager created.");
            
            em.getTransaction().begin();

            Entity s1 = new Entity();
                s1.setText(data);

            em.persist(s1);   
                
            em.getTransaction().commit();
            factory.close();
            em.close();

            LOGGER.log(Level.SEVERE, "Transaction done.");

        }
    }

}
Ich habe keine Ahnung, woran das liegen könnte.
 
Der Stacktrace ist dieser:

Code:
Caused by: com.objectdb.o.UserException: Failed to create a new file 'jdbc:mysql://localhost:3306/userdata'
    at com.objectdb.o.MSG.a(MSG.java:77)
    at com.objectdb.o.LFL.m(LFL.java:870)
    at com.objectdb.o.LFL.x(LFL.java:810)
    at com.objectdb.o.DFL.<init>(DFL.java:241)
    at com.objectdb.o.DMG.<init>(DMG.java:27)
    at com.objectdb.o.MST.<init>(MST.java:127)
    at com.objectdb.o.MST.ap(MST.java:109)
    at com.objectdb.o.MSF.Yw(MSF.java:190)
    at com.objectdb.o.OMF.r(OMF.java:783)
    at com.objectdb.jpa.EMF.r(EMF.java:130)
    at com.objectdb.o.OMF.w(OMF.java:694)
    at com.objectdb.jpa.EMF.createEntityManager(EMF.java:149)
    ... 27 more
Caused by: java.io.FileNotFoundException: jdbc:mysql:\localhost:3306\userdata (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
    at java.base/java.io.RandomAccessFile.open0(Native Method)
    at java.base/java.io.RandomAccessFile.open(RandomAccessFile.java:347)
    at java.base/java.io.RandomAccessFile.<init>(RandomAccessFile.java:261)
    at java.base/java.io.RandomAccessFile.<init>(RandomAccessFile.java:216)
    at com.objectdb.o.LFL.m(LFL.java:857)
 
?!? Evtl. wird der mysql-Treiber nicht gefunden und standardmäßig dann auf irgendwas anderes zurückgegriffen...
 
K

kneitzel

Öhm, Du willst doch ObjectDB nutzen. Wieso hast Du dann MySQL? Irgendwie widerspricht sich das doch gerade.

Du kannst JPA mit mysql nutzen, aber dann halt kein ObjectDB. Oder Du hast JPA mit ObjectDB.

Aber für eine Datenbank solltest Du Dich entscheiden.
 
K

kneitzel

Kann es daran liegen, dass er keinen Provider angegeben hat? Also sowas wie
<provider>org.hibernate.ejb.HibernatePersistence</provider>
Wenn kein Provider angegeben wurde, nimmt er meines Wissens nach den ersten, den er findet. Und falls er auch objectdb als Abhängigkeit in maven oder gradle oder so hat, dann zieht er da evtl. den falschen Provider (z.B. com.objectdb.jpa.Provider)?

Aber ohne Details zu wissen, ist das schwer zu urteilen.

Edith meint: der Provider würde in der persistence.xml mit angegeben.
 
Vielen Dank für Eure Beiträge. Jetzt klappt auch dieses. Es scheit ein TimezoneProblem gewesen zu sein:

String url = "jdbc:mysql://"+hostname+":"+port+"/"+dbname+"?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben