I'm trying to build an isomorphic app in React + Spring + Nashorn, however, I am encountering the following error:
jdk.nashorn.internal.runtime.ECMAException: ReferenceError: "Map" is not defined.
What can be done to correct this?
It seems I've provided too little details. What I'm doing is:
1. I've created 2 js modules: vendor.js (for node_modules) and app.js (my application) (using plugin webpack.optimize.CommonsChunkPlugin)
2. Defined nashorn-polyfill.js as follows:
var global = this;
var window = this;
var process = {env:{}};
var console = {};
console.debug = print;
console.log = print;
console.warn = print;
console.error = print;
Created class React which uses Nashorn Javascript Engine to load the 3 js files.
#Component
public class React {
private static final Logger logger = LogManager.getLogger(React.class);
#Value(value = "classpath:static/build/nashorn-polyfill.js")
private Resource nashornPolyfillFile;
#Value(value = "classpath:static/build/vendor.js")
private Resource vendorFile;
#Value(value = "classpath:static/build/app.js")
private Resource bundleJsFile;
public String renderEntryPoint() throws ScriptException, IOException {
NashornScriptEngine nashornScriptEngine = getNashornScriptEngine();
try {
Object html = nashornScriptEngine.invokeFunction("renderServer");
return String.valueOf(html);
} catch (Exception e) {
throw new IllegalStateException("Error! Failed to render react component!", e);
}
}
private NashornScriptEngine getNashornScriptEngine() throws ScriptException, IOException {
NashornScriptEngine nashornScriptEngine = (NashornScriptEngine) new ScriptEngineManager().getEngineByName("nashorn");
nashornScriptEngine.eval("load('"+nashornPolyfillFile.getURL()+"')");
nashornScriptEngine.eval("load('"+vendorFile.getURL()+"')");
nashornScriptEngine.eval("load('"+bundleJsFile.getURL()+"')");
return nashornScriptEngine;
}
}
It seems that line nashornScriptEngine.eval("load('"+vendorFile.getURL()+"')"); gives the mentioned error
2018-01-19 10:17:59.400 ERROR 1332 --- [nio-8095-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in con
text with path [] threw exception [Request processing failed; nested exception is javax.script.ScriptException: ReferenceError: "Map" is not defined in file
/build/resources/main/static/build/vendor.js at line number 11241] with root cause
jdk.nashorn.internal.runtime.ECMAException: ReferenceError: "Map" is not defined
at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57) ~[nashorn.jar:na]
at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:319) ~[nashorn.jar:na]
at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:291) ~[nashorn.jar:na]
at jdk.nashorn.internal.objects.Global.noSuchProperty(Global.java:1441) ~[nashorn.jar:na]
Let me know if you need more details.
Related
I am getting error:
Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=1, WKJavaScriptExceptionMessage=SyntaxError: Unexpected end of script, WKJavaScriptExceptionColumnNumber=0, WKJavaScriptExceptionSourceURL=file:///Users/rb/Library/Developer/CoreSimulator/Devices/675AC846-408B-486C-AE49-3F2187728698/data/Containers/Bundle/Application/7D63B436-AD1F-4CE5-857D-698EE857CC7D/flockmail.app/Frameworks/RichEditorView.framework/rich_editor.html, NSLocalizedDescription=A JavaScript exception occurred}
when executing following Javascript function using evaluateJavaScript.
/*jshint esversion: 6 */
function replaceLinkURL(jsonData) {
var userData = JSON.parse(jsonData);
var div = [...document.querySelectorAll('div.class1')].filter(function(el) {
return !el.querySelector('blockquote');
});
var correctDiv = div.filter(function(el) {
return !el.getElementsByClassName('.classLink').length;
});
correctDiv.forEach(function(el) {
el.getElementsByClassName('.classLink').href = userData.link;
});
}
Being new to Javascript, I can't figure out the issue, also I validated Javascript and its correct. There is no other handling I did in WKWebview for this.
I have a path (eg: "C:/Users/aaa/bbb/ccc/"), my aim to get the parent path (i.e. "C:/Users/aaa/bbb/")
For this I tried using java.nio.file.Paths, which worked in java and I tried converting the same into nashorn js:
import java.nio.file.Paths;
public class ReadPropertiesFile {
public static void main(String[] args) {
String myPath = "C:/Users/aaa/bbb/ccc/";
System.out.println(Paths.get(myPath).getParent());
}
}
Nashorn script:
var testPath = "C:/Users/aaa/bbb/ccc/";
var Paths = java.import("java.nio.file.Paths");
try{
var test = Paths.get(testPath).getParent();
console.log("++++++MyFINALPATH+++++"+test);
}catch (e){ console.log("++++++MyFINALPATH+++++"+e);
}
Expected output: C:/Users/aaa/bbb/
Error-
TypeError: Paths.get(...).getParent is not a function
You need to use this instead:
var Paths = Java.type("java.nio.file.Paths");
https://docs.oracle.com/javase/9/scripting/using-java-scripts.htm#JSJSG117
when I try to run child process and put to it stdin some text it throws error.
here is code of child process:
import java.io.Console;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("started");
Console console = System.console();
while (true) {
String s = console.readLine();
System.out.println("Your sentence:" + s);
}
}
}
code of script which run this process:
var spawn = require('child_process').spawn;
var child = spawn('java', ['HelloWorld', 'HelloWorld.class']);
child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);
child.stdin.write("tratata\n");
// child.stdin.end();
it throws:
events.js:161
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at exports._errnoException (util.js:1028:11)
at Pipe.onread (net.js:572:26)
notice, when I uncomment line with child.stdin.end(); it only ends whithout any reaction
The one thing you need to make the script work was to add:
process.stdin.pipe(child.stdin);
If you added this before the child.stdin.write, that would solve half the problem. The other half had to do with the Java side. If the java program is not launched from a console by typing java HelloWorld, then Console will return null thus you will get a NullPointerException if you tried to use Console.readLine. To fix, this use BufferedReader instead.
Change your script to this:
const spawn = require('child_process').spawn;
const child = spawn('java', ['HelloWorld'], {
stdio: ['pipe', process.stdout, process.stderr]
});
process.stdin.pipe(child.stdin);
setTimeout(() => {
child.stdin.write('tratata\n');
}, 1000);
Then change your java code to this:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class HelloWorld {
public static void main(String[] args) throws IOException {
System.out.println("started");
try(BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
for (String line = console.readLine(); line != null; line = console.readLine()) {
System.out.printf("Your sentence: %s\n", line);
}
}
}
}
See:
NodeJS Spawn Command
System.console() returns null
I am working on a project that requires that a Java class be called from a piece of Javascript that was executed by a separate piece of Java code. It did originally work in Java 7.51 but it needs to work in Java 1.6.0_27 as well but fails with a function importclass must be called with a class error message.
The two JARs were generated through Eclipse Indigo using the Export > JAR command.
I created a simple MCVE as below to demonstrate the problem. The stack trace from executing with the following command line...
java -cp Sanity.jar;SanityCheck.jar -jar SanityCheck.jar
...is the following:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: Function importClass must be called with a class; had "[JavaPackage com.sanity.Sanity]" instead. (<Unknown source>#1) in <Unknown source> at line number 1
at com.sun.script.javascript.RhinoScriptEngine.eval(Unknown Source)
at com.sun.script.javascript.RhinoScriptEngine.eval(Unknown Source)
at javax.script.AbstractScriptEngine.eval(Unknown Source)
at com.sanity.SanityCheck.<init>(SanityCheck.java:22)
at com.sanity.SanityCheck.main(SanityCheck.java:52)
Exception in thread "main" java.lang.NullPointerException
at com.sanity.SanityCheck.invoke(SanityCheck.java:31)
at com.sanity.SanityCheck.main(SanityCheck.java:53)
Can anyone see where I am going wrong here?
Sanity.java (in its own JAR of the same name)
package com.sanity;
public class Sanity {
public Sanity() {}
public void doCheck() {
System.out.println("Sanity Check Passed!");
}
}
SanityCheck.java (in its own JAR of the same name)
package com.sanity;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class SanityCheck {
private Invocable invoker;
public SanityCheck(String script) {
try {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.eval(script);
invoker = (Invocable) engine;
} catch (ScriptException e) {
e.printStackTrace();
}
}
public void invoke() {
try {
invoker.invokeFunction("run");
} catch (ScriptException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
StringBuilder builder = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("Sanity.js")));
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
reader.close();
SanityCheck check = new SanityCheck(builder.toString());
check.invoke();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sanity.js
importClass(Packages.com.sanity.Sanity);
function run() {
var sanObj = new Sanity();
sanObj.doCheck();
}
I have good news: the problem has nothing to do with your Java or JavaScript code. It has to do with the effect of the command:
java -cp [...] -jar <jar-file>
When executing that command, the -cp argument is ignored, and the <jar-file> is used as the entire classpath.
From the Java 6 documentation for the -jar option to the java tool:
When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.
So a version of your command that would work is:
java -cp Sanity.jar;SanityCheck.jar com.sanity.SanityCheck
I reproduced your example with the following directory structure, without modifying your code:
Sanity.js
com/
sanity/
Sanity.java
SanityCheck.java
... and then ran the following command from the top-level directory:
$ /usr/lib/jvm/java-1.6.0-openjdk-amd64/bin/javac com/sanity/*.java && /usr/lib/jvm/java-1.6.0-openjdk-amd64/bin/java -classpath . com.sanity.SanityCheck
... and got
Sanity Check Passed!
The error was down to the JAR file that was being called from the Javascript was compiled against Java 7, not Java 6. A quick test trying to run a main method in Eclipse soon revealed this.
A quick recompilation of the JAR file and now it works.
Title says it all. I am wondering if i can display javascript console.log in eclipse console rather than web browser's dev console?
Just found an article regarding this.
This is How it works(For Window 7).
Install Node.js javascript engine at Node.js
Open your Eclipse, in the menu
Run->External Tools->External Tools Configuration
Create new launch configuration under program category.
Set
Location : C:\WINDOWS\system32\cmd.exe
Working Directory : C:\WINDOWS\system32
Argument : /c "node ${resource_loc}"
Now create new environment variable 'node' refers to node.exe file(wherever you installed)
All done.
Redirect javascript console.logs, in Java console
Here is my solution to get javascript console messages in Java (with SWT browser)
create shell SWT and SWT browser see: Shell + Browser
create custom function SWT see: call Java from JavaScript
Add listener on error events in javascript see: mdn event error
Override console object in javascript and call custom java function (2.)
Here is my example snippet:
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class Snippet307d3 {
public static final Shell createShell() {
final var display = new Display();
final var shell = new Shell(display);
shell.setText("Snippet DEBUG");
shell.setLayout(new FillLayout());
shell.setBounds(10, 10, 300, 200);
return shell;
}
public static final Browser createBrowser(Shell shell) {
try {
return new Browser(shell, SWT.NONE);
} catch (final SWTError e) {
System.out.println("Could not instantiate Browser: " + e.getMessage());
shell.getDisplay().dispose();
System.exit(-1);
return null;
}
}
public static final void runShell(Shell shell) {
shell.open();
final var display = shell.getDisplay();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
public static void main(String[] args) {
// -> Create shell
final var shell = createShell();
// -> Create browser
final var browser = createBrowser(shell);
browser.setJavascriptEnabled(true);
// -> set HTML or use setUrl
browser.setText(createHTML());
// browser.setUrl(URL_DOCUMENT_HTML_TEST);
// -> Create custom function
final BrowserFunction function = new CustomFunction(browser, "theJavaFunctionDebugInEclipse");
// -> Register function for cleanup
browser.addProgressListener(ProgressListener.completedAdapter(event -> {
browser.addLocationListener(new LocationAdapter() {
#Override
public void changed(LocationEvent event) {
browser.removeLocationListener(this);
System.out.println("left java function-aware page, so disposed CustomFunction");
function.dispose();
}
});
}));
// -> 6) Start shell
runShell(shell);
}
private static class CustomFunction extends BrowserFunction {
public CustomFunction(Browser browser, String name) {
super(browser, name);
}
#Override
public Object function(Object[] arguments) {
for (final Object v : arguments)
if (v != null)
System.out.println(v.toString());
return new Object();
}
}
private static String createHTML() {
return """
<!DOCTYPE>
<html lang='en'>
<head>
<title>DEBUG SWT</title>
<script>
const console = {
log : function(args) {
try {
theJavaFunctionDebugInEclipse('redirect > ' + args);
} catch (_e) {
return;
}
},
error : function(args) {
this.log(args);
},
exception : function(args) {
this.log(args);
},
debug : function(args) {
this.log(args);
},
trace : function(args) {
this.log(args);
},
info : function(args) {
this.log(args);
}
};
window.addEventListener('error', function(e) {
console.log(e.type + ' : ' + e.message);
console.log(e);
});
</script>
</head>
<body>
<input id=button type='button' value='Push to Invoke Java'
onclick='function1();'>
<p>
<a href='http://www.eclipse.org'>go to eclipse.org</a>
</p>
<script>
// bad char sequence .. send error
eeeee
function function1() {
let result;
try {
// Call bad function java .. send log
result = badFunctionJava(12, false, null, [ 3.6,
[ 'swt', true ] ], 'eclipse');
} catch (e) {
console.log('a error occurred: ' + e.message);
return;
}
}
</script>
</body>
</html>
""";
}
}
Further to #ringord's answer here, these would be the commands for your External Tools Configuration on Linux:
Location : /home/<user>/.nvm/versions/node/<version>/bin/node (or wherever you installed node)
Working Directory : /home/<user>
Arguments : ${container_loc}/${resource_name}