Sign in to follow this  
  • entries
    4
  • comments
    8
  • views
    8538

Extending Java classes from JavaScript

Sign in to follow this  
TheChubu

2269 views

Hi! So this entry will be dealing with the Nashorn JavaScript engine found in Java 8+, specifically, how to extend a Java class from JavaScript and use the resulting JavaScript object in the Java side.

Extending Java classes from JavaScript



First this what I want to do:

  • Extend a Java class from JavaScript implementing a specific method.
  • Fetch the resulting object from Java and call that method.

    So lets start by initializing the script engine:
    String[] options = new String[] { "--language=es6" }; NashornScriptEngineFactory factory = new NashornScriptEngineFactory();NashornScriptEngine engine = (NashornScriptEngine) factory.getScriptEngine(options);
    That will get us a Nashorn JS engine instance supporting some ECMAScript 6 features (the ones I want specifically are 'let' and 'const'). I spent hours Googling for a way to pass the "--language=es6" argument to the engine initialization since I was creating it with Java's "standard" script engine API instead of using the Nashorn factory object directly.

    Now we need to load the script file, for that I'll use my ResourceManager and TxtFileLoader classes:// Create a manager at top level folder at 'res'.ResourceManager rm = new ResourceManager( "res" );// Now register the text file loader at sub folder 'script'.rm.registerResource( StringBuilder.class, new TxtFileLoader(), "script" );// Now load the script named 'testEntitySystem.js'.String scriptSource = rm.get( StringBuilder.class, "testEntitySystem.js" ).toString();
    The long term goal is allowing me to have some EntitySystems implemented in JavaScript, so what we'll do on the JS side is to extend an EntitySystem and give it some implementation of 'processEntities(entities)' method, here is the script file:function main(){ // We need this one for initializing the EntitySystem. const Aspect = Java.type("com.artemis.Aspect") // Now fetch the type. const EntitySystem = Java.type("com.artemis.EntitySystem") // Prepare for extension. const JSEntitySystem = Java.extend(EntitySystem) // Now return an instance that implements the abstract 'processEntities' method. return new JSEntitySystem(Aspect.EMPTY_ASPECT) { processEntities: function(entities) print("Extended from JavaScript!") }}// Calling the function so it will return the EntitySystem instance to Java after execution. main()
    Now all we need to do is to eval the script (or compile then execute) with the Nashorn engine instance and call the method:Object jsSystem = null;try{ jsSystem = engine.eval( scriptSource );}catch ( ScriptException e ){ e.printStackTrace();}// Lets see what kind of class it is...System.out.println(jsSystem.getClass());// Is it really a subclass of EntitySystem?System.out.println(jsSystem instanceof EntitySystem);// Now lets try to run the JS implementation!((EntitySystem)jsSystem).process();
    And this outputs:[quote]
    class com.artemis.EntitySystem$$NashornJavaAdapter
    true
    Extended from JavaScript![/quote]

    We see that it really is an instance of EntitySystem, it executes the JS implementation just fine, and it seems the Nashorn engine is creating an adhoc adapter class for extension purposes, cool!

    The fun thing here is that I can do "gameWorld.addObserver(jsSystem)" just fine and it will get iterated over like any other EntitySystem in the engine, so I can have systems both implemented in Java and in JavaScript working side to side.

    Given how easy is the integration I'm pretty sure I'll be using this a lot in the future for scripting all sort of things. Thats all, cya later!
Sign in to follow this  


3 Comments


Recommended Comments

I'd love to put some space in between paragraphs and the code blocks but the editor eats the new lines away (and also did eat 80% of the entry the first time I previewed it). So just be glad this one wasn't in a PDF like the last one :P

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now