eclipse-ee4j / glassfish

Eclipse GlassFish
https://eclipse-ee4j.github.io/glassfish/
371 stars 138 forks source link

How to use Oracle database driver with EclipseLink? #24212

Open mheydem opened 1 year ago

mheydem commented 1 year ago

I am trying to upgrade form

to

Java SE 8 - GF 6.0

For using the Oracle database driver with EclipseLink the ojdbc8.jar was placed in

glassfish/domains/domain/lib/ext

and in domain.xml this was specified

<jvm-options>-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext</jvm-options>

Looks like described in this quite old description https://docs.oracle.com/cd/E19798-01/821-1752/beaml/index.html

Java SE 17 - GF 6.2.5

Now, with Java SE 17 the java.ext.dirs option is not valid any longer. The current glassfish documentation seems not to explain how to to it under the new circumstances. If I place the ojdbc8.jar in the glassfish/domains/domain/lib directory directly, an exception is raised during application startup:

java.lang.NoClassDefFoundError: oracle/sql/TIMESTAMP
    at org.eclipse.persistence.platform.database.oracle.Oracle9Platform.<clinit>(Oracle9Platform.java:134)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
    at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:347)
    at java.base/java.lang.Class.newInstance(Class.java:645)
    at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.newInstanceFromClass(PrivilegedAccessHelper.java:524)
    at org.eclipse.persistence.sessions.DatasourceLogin.setPlatformClassName(DatasourceLogin.java:557)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.updateLogins(EntityManagerSetupImpl.java:2450)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.updateSession(EntityManagerSetupImpl.java:2847)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:750)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:222)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:330)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:350)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
    at org.glassfish.persistence.jpa.JPADeployer$2.visitPUD(JPADeployer.java:469)
    at org.glassfish.persistence.jpa.JPADeployer$PersistenceUnitDescriptorIterator.iteratePUDs(JPADeployer.java:544)
    at org.glassfish.persistence.jpa.JPADeployer.iterateInitializedPUsAtApplicationPrepare(JPADeployer.java:520)
    at org.glassfish.persistence.jpa.JPADeployer.event(JPADeployer.java:205)
    at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:107)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:467)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:199)
    at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:467)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:516)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:512)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/javax.security.auth.Subject.doAs(Subject.java:376)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:511)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:542)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:534)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/javax.security.auth.Subject.doAs(Subject.java:376)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:533)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1441)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1823)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1699)
    at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:510)
    at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:200)
    at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:150)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:440)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:144)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:174)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:153)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:196)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:34)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ClassNotFoundException: oracle.sql.TIMESTAMP
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    at org.apache.felix.framework.ExtensionManager$ExtensionManagerWiring.getClassByDelegation(ExtensionManager.java:1212)
    at org.apache.felix.framework.BundleWiringImpl.searchImports(BundleWiringImpl.java:1606)
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1522)
    at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1970)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 60 more

Possibly this bug report in Payara is related: https://github.com/payara/Payara/issues/4613

Would you please explain how this should be done correctly?

mheydem commented 1 year ago

The workaround described here is working for me: https://github.com/icatproject-contrib/icat-ansible/pull/83#issuecomment-1080535203

  1. Move down glassfish/domains/domain/lib/ext/ojdbc8.jar to glassfish/domains/domain/lib
  2. Move glassfish/modules/org.eclipse.persistence.oracle.jar to glassfish/domains/domain/lib

I leave this bug report open, as this is just a workaround.

OndroMih commented 1 year ago

This is an issue with classloading which on Java 8 used to be fixed with java.ext.dirs mechanism. In short, the JDBC driver is OK to be placed in domain/lib/ojdbc8.jar but it won't see the Oracle EclipseLink extension needed for correct JPA mappings to the Oracle DB. The solution to move glassfish/modules/org.eclipse.persistence.oracle.jar is OK because it moves the Oracle Eclipselink extension on the same level as the JDBC driver.

We'll need to investigate more how to solve this without the work-around. Until then, we could at least document this as the recommended workaround. @mheydem If you can contribute the documentation, we'd greatly appreciate it. Installing the Oracle JDBC driver is mentioned in the Administration guide and Application development guide. The Asciidoc sources are here: https://github.com/eclipse-ee4j/glassfish/tree/master/docs

However, this issue might be complicated to fix properly without any hacks. I recommend seeking professional services from companies that provide commercial support for Eclipse GlassFish, see: https://glassfish.org/support.html

github-actions[bot] commented 4 months ago

This issue has been marked as inactive and old and will be closed in 7 days if there is no further activity. If you want the issue to remain open please add a comment