joeferner / node-java

Bridge API to connect with existing Java APIs.
MIT License
1.88k stars 282 forks source link

java.lang.NoClassDefFoundError #402

Open blulas opened 7 years ago

blulas commented 7 years ago

I have created a very small node.js application with Nodeclipse (Eclipse plugin). This small application simply calls a Java facade using a static method, and that facade in turn calls APIs for a commercial product, via a large set of JAR file dependancies.

I have a JAR file with custom java code which wraps the commercial product API. I compile this JAR file outside of node-js using JDK 8, BTW. My code around this API works fine within JUnit, since I have control over my classpath when running from JUnit. There are nearly 40 JAR files that are required to be on the classpath in order for my custom code to run, even though from a compiling perspective only one of those 40 JAR files are required.

In my node-js application I am using java.classpath.push() for each of those 40 JAR files. I have verified that the JARs are on the application classpath, as I have dumped the classpath in my Java wrapper to the console.

My Java code works fine from node-js until it reaches a line of code which calls the product API, and then it simply returns a java.lang.NoClassDefFoundError for the product API class that I am calling. It seems clear that the product API classes are not on the node-js classpath for some reason.

I have also verified that I am getting into my custom Java methods from node-js, so the failure is clearly at the point in the code where I need to reference the product API.

Any and all help would be greatly appreciated!!

blulas commented 7 years ago

I have resolved this issue by pointing my java.classpath.push() calls using the direct path of the JAR files rather than a relative path.

MPBatista commented 7 years ago

I have the same error:

C:\Projects\testMQ\node_modules\java\lib\nodeJavaBridge.js:227 var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. ^

Error: Could not create class MyClass java.lang.NoClassDefFoundError: MyClass Caused by: java.lang.ClassNotFoundException: MyClass at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

My codes are: node.js var java = require('java'); java.classpath.push( ".");

var MyClass = java.import("MyClass"); var result = MyClass.addNumbersSync(1, 2); console.log(result);
JAVA: public class MyClass { public static void main(String[] args){ System.out.println("Now the output is redirected!"); } public static int addNumbers(int a, int b) { return a + b; } }

joeferner commented 7 years ago

Can you try console.log(path.resolve(".")); java.classpath.push(path.resolve(".")); to make sure the directory that you intended to add to the class path is correct.

On Wed, Jul 5, 2017 at 8:46 AM, Mateus Pereira Batista < notifications@github.com> wrote:

I have the same error:

C:\Projects\testMQ\node_modules\java\lib\nodeJavaBridge.js:227 var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. ^

Error: Could not create class MyClass java.lang.NoClassDefFoundError: MyClass Caused by: java.lang.ClassNotFoundException: MyClass at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

My codes are: node.js var java = require('java'); java.classpath.push( ".");

var MyClass = java.import("MyClass"); var result = MyClass.addNumbersSync(1, 2); console.log(result); JAVA: public class MyClass { public static void main(String[] args){ System.out.println("Now the output is redirected!"); } public static int addNumbers(int a, int b) { return a + b; } }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/joeferner/node-java/issues/402#issuecomment-313092299, or mute the thread https://github.com/notifications/unsubscribe-auth/AAxXma9AtuaPmNJQdwfbw1dDGcXvx7I-ks5sK4WIgaJpZM4OJ24y .

MPBatista commented 7 years ago

Hi, after I put the "path" component, everything is working well, thanks!

blulas commented 7 years ago

I’ve tried this and I get an exception that path is unresolved.

Barry Lulas | Principal Decision Management Architect | Apex Process Consultants | 727-433-9839 On Wed, Jul 5, 2017 at 8:52 AM, Joe Ferner notifications@github.com wrote: Can you try console.log(path.resolve(".")); java.classpath.push(path.resolve(".")); to make sure the directory that you intended to add to the class path is correct.

On Wed, Jul 5, 2017 at 8:46 AM, Mateus Pereira Batista < notifications@github.com> wrote:

I have the same error:

C:\Projects\testMQ\node_modules\java\lib\nodeJavaBridge.js:227 var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. ^

Error: Could not create class MyClass java.lang.NoClassDefFoundError: MyClass Caused by: java.lang.ClassNotFoundException: MyClass at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

My codes are: node.js var java = require('java'); java.classpath.push( ".");

var MyClass = java.import("MyClass"); var result = MyClass.addNumbersSync(1, 2); console.log(result); JAVA: public class MyClass { public static void main(String[] args){ System.out.println("Now the output is redirected!"); } public static int addNumbers(int a, int b) { return a + b; } }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/joeferner/node-java/issues/402#issuecomment-313092299, or mute the thread https://github.com/notifications/unsubscribe-auth/AAxXma9AtuaPmNJQdwfbw1dDGcXvx7I-ks5sK4WIgaJpZM4OJ24y .

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub [https://github.com/joeferner/node-java/issues/402#issuecomment-313093964] , or mute the thread [https://github.com/notifications/unsubscribe-auth/AP8tlagQbYgWcFU6H2yJhmiBuoiU_Pbjks5sK4ccgaJpZM4OJ24y] .

MPBatista commented 7 years ago

@blulas, try to run:

npm install path

this installs the package path.

abdulhannanali commented 7 years ago

@MPBatista Although the path package on npm has the same, it's clear something else is wrong, since it comes builtin and there should be need to install it separately on node.js, unless an updated path version is needed for previous versions of node.js

MPBatista commented 7 years ago

Could you test with this:

!/usr/bin/env node

const path = require('path'); console.log( path.resolve("."));

var java = require('java'); var javaLangSystem = java.import('java.lang.System');

javaLangSystem.out.printlnSync('Hello World');

xywang68 commented 6 years ago

Hi, @MPBatista, your script worked. In general your solution worked, but there is a little catch related to where to put the java.classpath.push() call. Please see the below explanation.

on ubuntu oracle java 1.8, node v6.11.1. node-java v0.9.0.

test code:

!/usr/bin/env node

const java = require('java'); const javaLangSystem = java.import('java.lang.System'); console.log(java.classpath); javaLangSystem.out.printlnSync('Hello World'); java.classpath.push(path.resolve('/home/vagrant/Downloads', 'sikulixapi.jar')); console.log(java.classpath); const Screen = java.import('org.sikuli.script.Screen');

output:

vagrant@desktop01:~$ node testjava.js [ '/home/vagrant/node_modules/java/commons-lang3-node-java.jar', '/home/vagrant/node_modules/java/src-java', pushDir: [Function] ] Hello World [ '/home/vagrant/node_modules/java/commons-lang3-node-java.jar', '/home/vagrant/node_modules/java/src-java', '/home/vagrant/Downloads/sikulixapi.jar', pushDir: [Function] ] /home/vagrant/node_modules/java/lib/nodeJavaBridge.js:227 var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. ^

Error: Could not create class org.sikuli.script.Screen java.lang.NoClassDefFoundError: org/sikuli/script/Screen Caused by: java.lang.ClassNotFoundException: org.sikuli.script.Screen at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

at Error (native)
at Java.java.import (/home/vagrant/node_modules/java/lib/nodeJavaBridge.js:227:20)
at Object.<anonymous> (/home/vagrant/testjava.js:10:25)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:389:7)

The above problem is related to where the java.classpath.push() is called. By placing it before the first import the script worked as expected:

test code:

!/usr/bin/env node

const java = require('java'); java.classpath.push('/home/vagrant/Downloads/sikulixapi.jar'); const javaLangSystem = java.import('java.lang.System'); javaLangSystem.out.printlnSync('Hello World'); const Screen = java.import('org.sikuli.script.Screen'); var s = new Screen(); s.click('/home/vagrant/Projects/chrome.png');

output:

Hello World [log] CLICK on L(32,174)@S(0)[0,0 1920x1016] (563 msec)

arjunrai1t commented 6 years ago

its common problem of this api . I also faced this type problem.

MPBatista commented 6 years ago

Hi @xywang68, you can just put the jar inside the same directory where is the code nodejs.

This is happen because nodejs doesn't work well with the relative path, so you need to force the code to find the class.

arjunrai1t commented 6 years ago

i also done this but same things happens..

On 19-Dec-2017 11:33 pm, "Mateus Pereira Batista" notifications@github.com wrote:

Hi @xywang68 https://github.com/xywang68, you can just put the jar inside the same directory where is the code nodejs.

This is happen because nodejs doesn't work well with the relative path, so you need to force the code to find the class.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/joeferner/node-java/issues/402#issuecomment-352838723, or mute the thread https://github.com/notifications/unsubscribe-auth/AEU96LnzhMVYGeFeRli5e12_AcVsxxrOks5tB_p_gaJpZM4OJ24y .

MPBatista commented 6 years ago

Following how I use to find the jars:

!/usr/bin/env node

const path = require('path'); console.log(path.resolve(".")); // var java = require('java'); java.classpath.push( "."); java.classpath.push( "../lib/com.ibm.mq.headers.jar"); java.classpath.push( "../lib/com.ibm.mq.jar"); java.classpath.push( "../lib/com.ibm.mq.jmqi.jar"); java.classpath.push( "../lib/com.ibm.mq.postcard.jar"); java.classpath.push( "../lib/com.ibm.mq.commonservices.jar"); java.classpath.push( "../lib/commons-logging.jar"); java.classpath.push( "../lib/connector-api-1.5.jar"); java.classpath.push( "../lib/jta-1.1.jar");

var MqSeries = java.newInstanceSync( "ca.commun.mq.MqSeries", config[ENV].nomRequete, config[ENV].nomProgramme, config[ENV].localQManager, config[ENV].sendQManager, config[ENV].sendQ, config[ENV].replyQManager, config[ENV].replyQ, config[ENV].channel, config[ENV].hostName, config[ENV].port, config[ENV].userId, config[ENV].password );

var message = MqSeries.sendReceiveSync( requete);

console.log( "Message=" + message);

joeferner commented 6 years ago

You can also use https://github.com/joeferner/node-java-maven which I wrote to help with Maven like dependencies.

arjunrai1t commented 6 years ago

Please give me example for find jar in windows with path

On 22 December 2017 at 03:15, Joe Ferner notifications@github.com wrote:

You can also use https://github.com/joeferner/node-java-maven which I wrote to help with Maven like dependencies.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/joeferner/node-java/issues/402#issuecomment-353465444, or mute the thread https://github.com/notifications/unsubscribe-auth/AEU96GPRGguZzVJdsB0zU2ojdAxUU9LQks5tCtFxgaJpZM4OJ24y .

aakashkumar667 commented 6 years ago

Hi All, I am also getting the same error i tried all the above suggestions nothing is working for me. Any help is appreciated.

/opt/demo/node_modules/java/lib/nodeJavaBridge.js:227 var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved. ^

Error: Could not create class com.aline.demo.Demo1 java.lang.NoClassDefFoundError: com/aline/demo/Demo1 Caused by: java.lang.ClassNotFoundException: com.aline.demo.Demo1 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

at Error (native)
at Java.java.import (/opt/demo/node_modules/java/lib/nodeJavaBridge.js:227:20)
at Object.<anonymous> (/opt/demo/test5.js:9:27)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:383:7)
RenanChagas commented 6 years ago

Hi @xywang68, Im trying to use the same example that you did with sikulix on mac but it didnt output anything.

The java logo appear on the doc and thats it. Any ideas of what could have happen?

Im trying to implement the sikulix to create a image recognition framework on nodeJS

xywang68 commented 6 years ago

Hi, @RenanChagas , most likely it is due to javaclass path configuration. The example I provided above is based on Linux (ubuntu 16.04), and we are able to run in ubuntu-desktop, xvfb-run and docker configurations.