3

I use amazing J2V8 java library which allows execute any Javascript code in your Java application furthermore it can integrates a nodeJS engine.

But i have encountered with a next issue. This code interrupts a Java application immediately after nodejs invokes a callback function of setTimeout which throw an exception although there is a try..carch block. The exception doesn't even enter into the try..catch block.

// It is an example, in real case it can be a some erorr in a code.
nodeJS = NodeJS.createNodeJS();
try {
    nodeJS.getRuntime().executeVoidScript("setTimeout(function(){throw 'Error'}, 1000);"); 
} catch (Exception e) {
    e.printStackTrace();
}

The application is interrupted with message:

undefined:1
setTimeout(function(){throw 'Error'}, 10000);
                  ^
Error
Process finished with exit code 1

Another example shows that exceptions are not a cause of interruption of an application always and it is a 'normal' case.

nodeJS = NodeJS.createNodeJS();
try {
    nodeJS.getRuntime().executeVoidScript("throw 'Error'");
} catch (Exception e) {
    e.printStackTrace();
}

In this case we see the only a error message in console but the application still works.

Exception in thread "Thread-2" undefined:1: Error
throw 'Error'
^
com.eclipsesource.v8.V8ScriptExecutionException
    at com.eclipsesource.v8.V8._executeScript(Native Method)
    at com.eclipsesource.v8.V8.executeScript(V8.java:940)
    at com.eclipsesource.v8.V8.executeScript(V8.java:595)
    at com.eclipsesource.v8.V8.executeObjectScript(V8.java:625)
    at com.eclipsesource.v8.V8.executeObjectScript(V8.java:608)
    at org.efc.origamiapp.v8.V8Environment.run(V8Environment.java:383)

The examples above are in the try..catch blocks, and you can see trace stack below it. So the interruption is fired in Native Method (the secod example), but in the first case the JS exception just kills the Java application without any explanations in a console or in a trace log.

3 Answers3

1

It looks like the error you are throwing in the javascript code is being propagated into the java environment. This is what one would expect to see given the js code you are trying to execute (throw 'Error'). What did you expect to happen? Simply catch any exceptions in java and handle appropriately - maybe by logging?

try {
    nodeJS.getRuntime().executeVoidScript("throw 'Error'"); 
}
catch(Exception e) { 
    System.out.println(e.toString()); 
}
Tom
  • 7,994
  • 8
  • 45
  • 62
  • Actually, try..catch block does not help. The application is interrupted by some internal reason – Anton Prokopenko Oct 15 '16 at 11:21
  • Is there any more to the stack trace? Is there any more code? – Tom Oct 15 '16 at 11:31
  • I've tried to debug quite deep but the error is raised from a native method. The application just suddenly stops when a inner timer of v8 triggers the invalid code. There isn't more trace log than i placed above. – Anton Prokopenko Oct 15 '16 at 19:27
  • It seems you don't understand the situation. The examples above are in the try..catch blocks, and you can see trace stack below it. So the interruption is fired in Native Method (the secod example), but in the first case the JS exception just kills Java the application without any explanations. – Anton Prokopenko Oct 16 '16 at 05:17
  • You may still be able to catch the exception with an unhandled exception handler: http://stackoverflow.com/questions/588634/is-there-an-unhandled-exception-handler-in-java – Tom Oct 25 '16 at 01:14
1

This is the best and correct solution.

process.on('unhandledRejection', (err) => {
    console.error('Unhandled promise rejection',err);
});
process.on('uncaughtException', (err) => {
    console.error('Uncaught exception',err);
});

For more information see the nodeJS documentation: Event: 'uncaughtException'

0

For now my workaround is this script.

let nativeSetTimeout = setTimeout;
setTimeout = function(fn, t){
    let safeFn = () => {
        try {
            fn();
        } catch(e){
            console.log(e);
        }
    };
    return nativeSetTimeout(safeFn,t);
} 


let nativeNextTick = process.nextTick;
process.nextTick = function(){
    let args = Array.prototype.slice.call(arguments);
    let fn = args[0];
    let safeFn = () => {
        try {
            fn.apply(null,args.slice(1));
        } catch(e){
            console.log(e);
        }
    };
    return nativeNextTick(safeFn);
}

I invoke this script in a beginning of an application.

nodeJS.getRuntime().executeVoidScript(workaroundScript);