Search code examples
javajpaconfigurationjava-9java-platform-module-system

How to create local database using JPA?


I am just starting to use JPA. I am trying to create database based on schema using Persistence.generateSchema("DataLayer", null) method, but i get an exception. As JPA implementation i am using OpenJPA.

My solution is divided into two Eclipse projects. Both use Maven and module-info.java.

1st project is clearly just main method where i call the method above.

2nd one is JPA entities and data access objects.

In 1st project i included dependency to 2nd project. In 2nd project i included dependencies to jpa implementor (openjpa) and database driver (derby). See dependencies part from pom.xml's bellow:

1st project dependency (there is just my 2nd project):

<dependency>
    <groupId>registry</groupId>
    <artifactId>datalayer</artifactId>
    <version>0.0.1</version>
</dependency>

1st project module-info:

module justtestingTEMP
{
    exports justtestingTEMP;

    requires registry.datalayer;
    requires javax.persistence;
}

2nd project dependencies:

<dependencies>
    <dependency>
        <groupId>org.apache.openjpa</groupId>
        <artifactId>openjpa</artifactId>
        <version>3.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.derby</groupId>
        <artifactId>derbyclient</artifactId>
        <version>10.15.2.0</version>
    </dependency>
</dependencies>

2nd project module-info:

module registry.datalayer
{
    exports datalayer.other;
    exports datalayer.dto;
    exports datalayer.dao;

    requires javax.persistence;
}

This is persistence.xml (it is in 2nd project):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
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_2.xsd">
<persistence-unit name="DataLayer"
    transaction-type="RESOURCE_LOCAL">
    <non-jta-data-source>myNonJtaDataSource</non-jta-data-source>
    <properties>
        <property
            name="javax.persistence.schema-generation.database.action"
            value="create" />
    </properties>
</persistence-unit>

This is the exception:

Exception in thread "main" java.lang.NoClassDefFoundError: javax/sql/DataSource
at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newInstance(JDBCBrokerFacto
ry.java:72)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Metho
d)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodA
ccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Delegatin
gMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.openjpa.kernel.Bootstrap.invokeFactory(Bootstrap.java:131)
at org.apache.openjpa.kernel.Bootstrap.newBrokerFactory(Bootstrap.java:66)
at org.apache.openjpa.persistence.PersistenceProviderImpl.getBrokerFactory(Pers
istenceProviderImpl.java:152)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFa
ctory(PersistenceProviderImpl.java:95)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFa
ctory(PersistenceProviderImpl.java:159)
at org.apache.openjpa.persistence.PersistenceProviderImpl.generateSchema(Persis
tenceProviderImpl.java:244)
at javax.persistence@1.1/javax.persistence.Persistence.generateSchema(Persisten
ce.java:188)
at justtestingTEMP/justtestingTEMP.Main.main(Main.java:15)

Caused by: java.lang.ClassNotFoundException: javax.sql.DataSource
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoade
r.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoa
ders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 13 more

Where can i get that javax.sql.DataSource class from? I guess i am missing some dependency or i have configured something wrong.

What i tried: Switch JPA implementation (other exceptions were raised - but about missing classes), add requires java.sql; to module-info.

After adding requires java.sql; to module-info:

Exception in thread "main" java.lang.NoClassDefFoundError: java/lang /instrument/
ClassFileTransformer
at org.apache.openjpa.persistence.PersistenceProviderImpl.loadAgent(Persistence
ProviderImpl.java:365)
at   org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFa
ctory(PersistenceProviderImpl.java:102)
at  org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFa
ctory(PersistenceProviderImpl.java:159)
at  org.apache.openjpa.persistence.PersistenceProviderImpl.generateSchema(Persis
tenceProviderImpl.java:244)
at javax.persistence@1.1/javax.persistence.Persistence.generateSchema(Persisten
ce.java:188)
at justtestingTEMP/justtestingTEMP.Main.main(Main.java:14)

Caused by: java.lang.ClassNotFoundException:   java.lang.instrument.ClassFileTrans
former
at  java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoade
r.java:581)
at        java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoa
ders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 6 more

Solution

  • Found out that required classes were in java.sql and and java.instrument module, so adding these to module-info solve my issue. module-info.java should look like this:

    module justtestingTEMP
    {
        exports justtestingTEMP;
    
        requires java.instrument;
        requires java.sql;
        requires javax.persistence;
        requires registry.datalayer;
    }
    

    Also it is possible to remove module-info.java from 1st project. That resulted in a "correct" error saying that i have not defined jdbc driver and connection properties - that is good. No class not found errors. I can create and connect to database now. That is probably because all required modules are available implicitly. With module-info.java i have to define all required modules.