NCEAS / metadig-engine

MetaDig Engine: multi-dialect metadata assessment engine
7 stars 5 forks source link

Upgrade Java #308

Closed gothub closed 1 year ago

gothub commented 2 years ago

metadig-engine is currently built and run under OpenJDK 8.

This should be upgraded to a newer or current version, see https://openjdk.java.net/projects/jdk/

To accomplish this:

gothub commented 2 years ago

Metadig-engine Java source code compiles fine using Java 9.4.0, which was downloaded and installed on my MBP macOS 11.6.5 (Big Sur). Java was downloaded from https://jdk.java.net/archive/. Note that this website warns:

Warning: These older versions of the JDK are provided to help developers debug issues in older systems. They are not updated with the latest security patches and are not recommended for use in production.

However, when I attempt to run with this compiled version, the DataONE libraries that metadig-engine is dependant on produce the following errors:

org.dataone.exceptions.MarshallingException
    at org.dataone.service.util.TypeMarshaller.unmarshalTypeFromStream(TypeMarshaller.java:299)
    at edu.ucsb.nceas.mdqengine.Controller.processQualityRequest(Controller.java:372)
    at edu.ucsb.nceas.mdqengine.Controller.main(Controller.java:169)
Caused by: javax.xml.bind.JAXBException
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:242)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:460)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:652)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:599)
    at org.dataone.service.util.TypeMarshaller.getJAXBContext(TypeMarshaller.java:131)
    at org.dataone.service.util.TypeMarshaller.unmarshalTypeFromStream(TypeMarshaller.java:296)
    ... 2 more
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    at javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:578)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:240)
    ... 7 more
org.dataone.exceptions.MarshallingException
    at org.dataone.service.util.TypeMarshaller.unmarshalTypeFromStream(TypeMarshaller.java:299)
    at edu.ucsb.nceas.mdqengine.Controller.processQualityRequest(Controller.java:372)
    at edu.ucsb.nceas.mdqengine.Controller.main(Controller.java:169)
Caused by: javax.xml.bind.JAXBException
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:242)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:460)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:652)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:599)
    at org.dataone.service.util.TypeMarshaller.getJAXBContext(TypeMarshaller.java:131)
    at org.dataone.service.util.TypeMarshaller.unmarshalTypeFromStream(TypeMarshaller.java:296)
    ... 2 more
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    at javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:578)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:240)
    ... 7 more
Exception in thread "main" java.lang.NullPointerException
    at edu.ucsb.nceas.mdqengine.Controller.processQualityRequest(Controller.java:384)
    at edu.ucsb.nceas.mdqengine.Controller.main(Controller.java:169)

Therefore, it is not possible currently to upgrade Java until the DataONE libraries have been upgraded to a newer version of Java. The current Java version is 18.

taojing2002 commented 1 year ago

Hi @jeanetteclark, in the dataone-indexer pom.xml, I added those dependencies to work around the issue:

<!-- API, java.xml.bind module -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
            </dependency>
        <!-- Runtime, com.sun.xml.bind module -->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.2</version>
        </dependency>

The full pom.xml can be found: https://github.com/DataONEorg/dataone-indexer/blob/develop/pom.xml

Here is the link for this issue:

https://mkyong.com/java/java-lang-classnotfoundexception-com-sun-xml-bind-v2-contextfactory/

jeanetteclark commented 1 year ago

Docker base images and the pom have both been updated, and everything seems to be working locally. Will test more full on k8s once a few other issues in this release have been addressed

jeanetteclark commented 1 year ago

okay so this is not working and we could use some ideas -

The error that is thrown is from d1_libclient_java - MultipartD1Node.deserializeServiceType:870 ... following the stack further down we get to: Unmarshaller jaxbUnmarshaller = TypeMarshaller.getJAXBContext(domainClass).createUnmarshaller(); which throws the JAXB exception java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory.

things I have tried:

Adding this set of dependencies to the pom.xml (per @taojing2002 above)

<!-- API, java.xml.bind module -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
            </dependency>
        <!-- Runtime, com.sun.xml.bind module -->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.2</version>
        </dependency>

using this for the runtime instead of glassfish, from this SO post

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
    <scope>runtime</scope>
</dependency>

using this set of dependencies instead: (from the same post as above)

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0.1</version>
</dependency>

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.1</version>
</dependency>

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.25.0-GA</version>
</dependency>

creating a jaxb.properties file as described here and here.

Nothing is working. @taojing2002 and I spent about 90 minutes reviewing the jar file and all of the classes, everything looks like it is in place correctly so we must be missing something. Any ideas you have @mbjones would be welcome

mbjones commented 1 year ago

@jeanetteclark for this to work in Bookkeeper, I had to explicitly exclude the jaxb dependency from the d1_libclient jar file, like so (in addition to including the jackson dependencies Jing listed above):

        <dependency>
            <groupId>org.dataone</groupId>
            <artifactId>d1_libclient_java</artifactId>
            <version>${d1libclient.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.xml.bind</groupId>
                    <artifactId>jaxb-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

I also had to exclude jaxb from our dropwizard dependencies, which included it indirectly. The way I tracked this down is to run mvn dependency:tree and search for any indirect dependencies on jaxb jars, and be sure to exclude those (but not the jackson ones which I wanted to keep).

taojing2002 commented 1 year ago

@jeanetteclark I made it work. The pom.xml file already has the dependency EclipseLink MOXy, which is a jaxb implementation. So we don't need glassfish. In order to make the EclipseLink MOXy implementation work, I have to add the jaxb.properties files into the java class model directories. After I did that, the code work under java 17.

jeanetteclark commented 1 year ago

Thank you Jing! it works for me as well