jpmml / jpmml-transpiler

Java Transpiler (Translator + Compiler) API for PMML
GNU Affero General Public License v3.0
28 stars 2 forks source link

ClassNotFoundException when loading transpiled model #5

Closed ahmed-shariff closed 4 years ago

ahmed-shariff commented 4 years ago

I get the following error when I try to load the transpiled models:

java.lang.NoClassDefFoundError: org/dmg/pmml/PMML
    at java.lang.ClassLoader.defineClass1 (Native Method)
    at java.lang.ClassLoader.defineClass (ClassLoader.java:757)
    at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass (URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100 (URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run (URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run (URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged (Native Method)
    at java.net.URLClassLoader.findClass (URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:419)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:352)
    at java.lang.Class.forName0 (Native Method)
    at java.lang.Class.forName (Class.java:348)
    at java.util.ServiceLoader$LazyIterator.nextService (ServiceLoader.java:370)
    at java.util.ServiceLoader$LazyIterator.next (ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next (ServiceLoader.java:480)
    at org.jpmml.model.ServiceLoaderUtil.load (ServiceLoaderUtil.java:30)
    at org.jpmml.model.PMMLUtil.load (PMMLUtil.java:46)
    at com.umanitoba.hci.washinghands.App.main (App.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
    at java.lang.Thread.run (Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.dmg.pmml.PMML
    at java.net.URLClassLoader.findClass (URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:419)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:352)
    at java.lang.ClassLoader.defineClass1 (Native Method)
    at java.lang.ClassLoader.defineClass (ClassLoader.java:757)
    at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass (URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100 (URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run (URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run (URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged (Native Method)
    at java.net.URLClassLoader.findClass (URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:419)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:352)
    at java.lang.Class.forName0 (Native Method)
    at java.lang.Class.forName (Class.java:348)
    at java.util.ServiceLoader$LazyIterator.nextService (ServiceLoader.java:370)
    at java.util.ServiceLoader$LazyIterator.next (ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next (ServiceLoader.java:480)
    at org.jpmml.model.ServiceLoaderUtil.load (ServiceLoaderUtil.java:30)
    at org.jpmml.model.PMMLUtil.load (PMMLUtil.java:46)
    at com.umanitoba.hci.washinghands.App.main (App.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
    at java.lang.Thread.run (Thread.java:748)

I tried the following:

              // ============approach 1===============
               Evaluator evaluator = new ServiceLoadingModelEvaluatorBuilder()
            .loadService((f.toURI()).toURL())
            .build();
              // ============approach 2===============
               URL[] classpath = {
            (f.toURI()).toURL()
        };
        try(URLClassLoader clazzLoader = new URLClassLoader(classpath)){
            PMML javaPmml = PMMLUtil.load(clazzLoader);
            Evaluator evaluator = new ModelEvaluatorBuilder(javaPmml)
                .build();
                }

I've attached the associated jar file for your reference. Any help or pointers would be much appreciated.

vruusmann commented 4 years ago

That must be a classpath issue on your side.

The generated Service JAR file is not completely self-contained; it depends on the JPMML-Evaluator library, which in turn depends on the JPMML-Model library.

The org.dmg.pmml.PMML class resides inside the JPMML-Model library JAR file (Apache Maven coordinates org.jpmml:pmml-model). Please make sure that this artifact is on your application classpath.

ahmed-shariff commented 4 years ago

You were right, I added the PMML classes ClassLoader as the parent to the URLClassLoader, and it solves the problem:

...
try(URLClassLoader clazzLoader = new URLClassLoader(classpath, PMML.class.getClassLoader())){
...