payara / Payara

Payara Server is an open source middleware platform that supports reliable and secure deployments of Java EE (Jakarta EE) and MicroProfile applications in any environment: on premise, in the cloud or hybrid.
http://www.payara.fish
Other
883 stars 307 forks source link

Eclipselink with OracleChangeNotificationListener throws java.lang.ClassNotFoundException: oracle.jdbc.dcn.DatabaseChangeListener / FISH-6633 #5981

Open luisdanielmesa opened 2 years ago

luisdanielmesa commented 2 years ago

Brief Summary

When using the property eclipselink.cache.database-event-listener in persistence.xml set to org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener or to DCN server startup fails with an exception java.lang.ClassNotFoundException: oracle.jdbc.dcn.DatabaseChangeListener.

Caused by: java.lang.ClassNotFoundException: oracle.jdbc.dcn.DatabaseChangeListener at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) 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:521) ... 59 more

Removing the property allows the app to start normally.

I'm using Oracle 19.3.0 SE2 in a docker container locally as a test environment. Oracle JDK 11.0.8 Payara 5.2022.3 persistence.xml <persistence version="2.2" ...

I'm evaluating Payara Server Full with the hopes of being able to deploy using Payara Micro in a Kubernetes cluster afterwards.

Expected Outcome

I would expect the server to start without an exception.

eclipse-ee4j/eclipselink persistence.xml example

eclipse-ee4j/eclipselink

Current Outcome

image

Reproducer

  1. Create a simple project that uses EclipseLink JPA in conjunction with an Oracle database
  2. Here's a list of autogenerated projects
  3. Add the above-mentioned property to the persistence.xml
  4. Deploy to Payara Server Full 5.2022.3 (I'm testing in full locally, to try to use Micro in a Kubernetes cluster in the final deployment) Tried many examples

Operating System

Windows 10 Pro

JDK Version

Oracle JDK 11.0.8

Payara Distribution

Payara Server Full Profile

luisdanielmesa commented 2 years ago

If I'm missing something or made a mistake somewhere, you can point me to a working example of the usage of this property within the context of Payara's repackaged Eclipselink (2.7.9.payara-p2) and close the issue. Thanks!

felixif commented 2 years ago

Hi luisdanielmesa,

Thank you for raising the issue, unfortunately, we don't have an example I can refer you to. I was unable to configure the environment the same way you described it, could you please share the exact configuration of your docker database image, and a small sample application to test with?

Best regards, Felix

felixif commented 2 years ago

Hi luisdanielmesa,

I created this sample application on the same environment as described in your issue, in order to try to reproduce the errors that you encountered. I was able to persist the object in the database with no issues and no errors/warnings from Payara Server.

I attached in this message a .zip archive with my project, please let me know if it works for you.

oracle-demo.zip

luisdanielmesa commented 2 years ago

Hi, thanks for taking the time to make the demo. Unfortunately I'm using EclipseLink, instead of Hibernate, as stated in the title. I have created a small project, inspired by yours, to reproduce.

I've intentionally left the full logging turned on in case you need it, you might want to turn it off if you don't need it.

#f03c15 WARNING: I've used drop-and-create as schema generation strategy, the scripts are right beside persistence.xml, don't use on any database that you care about too dearly.

#00ff00 Steps

  1. Download the demo project below
  2. Check the code and compile it
  3. Deploy it into Payara.
  4. Hit the employee endpoint
  5. Check it works, if it does work then continue to next step, if it doesn't then reply here what I did wrong
  6. Edit persistence.xml and uncomment the eclipselink.cache.database-event-listener line
  7. Go to step 2

#1589F0 Demo project oracle-change-notification.zip

felixif commented 2 years ago

Hi @luisdanielmesa,

Thank you very much for reporting this issue, I was able to reproduce it using your project. I have raised a Jira issue with the internal id FISH-6633. We always encourage you to contribute, so if you feel confident to do you please raise a PR and a member of the development team will gladly review the changes. If not, we will pick this issue up in the future.

Thanks, Felix

smillidge commented 2 years ago

Have you added the Oracle JDBC driver containing oracle.jdbc.dcn.DatabaseChangeListener to you server classpath?

luisdanielmesa commented 2 years ago

Hi, I have it inside my packaged app. I also tried placing it in several locations as per: this post but it seems in neither of the locations it got picked up...

I did not try the add-library command because I'm not very familiar with it and wanted to have all non-provided dependencies inside my packaged application. I'm testing multiple servers and I tried to make it as portable as I could to ease my testing.

I also tried your answer to this question where you seemed to suggest just adding it to WEB-INF/lib was enough, but the examples you linked are not accessible and then I didn't try the other answers when I got a little discouraged.

Edit: I don't know if this is useful but I'll paste the screenshot of the exception I get, as well as the dependencies I'm using... thanks for taking the time, I really appreciate it.

Exception image Declared dependencies image Built dependencies image persistence.xml image

luisdanielmesa commented 1 year ago

I've been digging and I've gotten as far as checking osgi.properties Which location(s) are supposed to be supported to place the ojdbc driver? I just want to test in different locations, but I don't want to try randomly.

luismesa-io commented 1 year ago

Is there any update on this? Is there a way I can help?

lprimak commented 1 year ago

Have you seen / implemented this: https://docs.payara.fish/community/docs/documentation/payara-server/classloading.html

You would need to do both payara-web.xml with delegate set to false and the system property to turn it off globally

luismesa-io commented 1 year ago

Hi @lprimak thank you for the answer. I thought I was adding a library that Payara didn't contain. Can you explain why turning off class-loading delegation solves this issue? Maybe I'm missing something. Thank you again.

lprimak commented 1 year ago

Does it work? The article has all the answers that I have :) I think EclipseLink includes some oracle stuff so it clashes unless you turn off delegation

luismesa-io commented 1 year ago

I tried adding:

<class-loader delegate="false"/>

but I still get the java.lang.NoClassDefFoundError: oracle/jdbc/dcn/DatabaseChangeListener error.

lprimak commented 1 year ago

Did you also include the system property fish.payara.classloading.delegate to false? You need to do both

luismesa-io commented 1 year ago

I just tried that, but I still get the error, don't worry and thanks for the help, I'll just use Debezium and get the change capture that way... I still think I was on the right track checking this

Screenshot 2023-02-16 211054 Screenshot 2023-02-16 211128 Screenshot 2023-02-16 211008
lprimak commented 1 year ago

Did you put your JDBC driver into /lib directory? And make sure it's not anywhere else in your project as a dependency? If it is, it will "block" the right classes from loading.

luisdanielmesa commented 1 year ago

I was wondering if anyone had found a way to make this work. I couldn't. Seems the classloading is a bit sketchy now, because you might also need to delegate the classloading for other libraries. It happened to me recently when using Jackson. It wouldn't work if I had delegate=false