0

I am currently creating a plugin for the Bukkit-Server, but i have a problem using the Nashorn scripting engine. I am evaluating the external javascript file from my Java-Plugin. I cant get my javascript to import the classes from my plugin, only standard java classes are working (like var JavaBool = Java.type('java.lang.Boolean');, but not var Holder = Java.type('io.github.advtest1.js.JSHolder');)

Whenever I try to load one of these I get the following error:

Caused by: java.lang.ClassNotFoundException: io.github.advtest1.js.JSHolder

After a bit of researching i found that it has something to do with my plugin-classes beeing in the classpath, but how can i add it to the classpath when Bukkit itself loads the plugin and i don't want any other startoptions for the server then java -jar bukkit.jar?

Feel free to ask, if you need additional information. Thanks in advance!

5
  • This looks like only Java and not JavaScript... Commented Nov 26, 2015 at 19:07
  • does it help to set the context classloader before you create the scriptengine, as explained here stackoverflow.com/a/30251930/3215527 Commented Nov 26, 2015 at 19:12
  • @wero I will try this, one moment! And to Arg0n: yeah the examples above are all javascript, because this is a javascript problem. if i dont use any other classes evaluating scripts from within java works perfect. Commented Nov 26, 2015 at 19:40
  • @wero well i am stuck with that link... how exactly can i get the context classloader and set it to the thread? Commented Nov 26, 2015 at 19:44
  • Okay i got it now, but now it throws this: javax.script.ScriptException: TypeError: [JavaClass io.github.advtest1.Log] has no such function "warnSel" in <eval> at line number 20 Oh and yeah the warnSel()-method is public and static Commented Nov 26, 2015 at 19:50

2 Answers 2

4
  • Nashorn uses the thread context loader found at the time of engine creation to find Java classes from Java.type API.

  • Nashorn also uses another loader if you use "-classpath" nashorn command line option. Nashorn tries to load classes using a fresh loader created during engine creation initialized with that classpath specified. Note that nashorn command line options can be passed via "nashorn.args" Java System property. So, if you specific -Dnashorn.args="-classpath your_path" elsewhere (say, in your config), then Nashorn can access classes from that your_path specified.

If cannot pass Nashorn engine options via System property [or via command line in the case "jjs" tool use], you can set thread context loader to be appropriate loader as suggested by an earlier answer.

If that is not desired because of other application dependencies, you get java.lang.Class object of the desired class and expose the same as variable to the script (from your Java code, you could get Class object and call ScriptEngine.put method). The script then can access "static" property on that to get 'type' object. With type object, usual "new", static method calls etc. work as expected.

Example:

import javax.script.*;

public class Main {
   public static void main(String[] args) throws Exception {
       ScriptEngineManager m = new ScriptEngineManager();
       ScriptEngine e = m.getEngineByName("nashorn");
       e.put("Vec", java.util.Vector.class); // replace it with any Class object
       e.eval("var T = Vec.static; var obj = new T()"); // create new Vector
       e.eval("print(obj.getClass())");
   }
}
Sign up to request clarification or add additional context in comments.

Comments

2

As @wero mentioned, I needed to add

ClassLoader cl = plugin.getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);

before I invoke the js-function from java.

plugin stands for the main class (the class which extends JavaPlugin)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.