Javascript For Java Developers

Javascript For Java Developers

There are times that a java programmer needs to write some javascript functions for an eco system that does not have a framework. For example I am working with BigQuery (google’s big data platform) and writing user functions that are in javascript.

So for example I would like to write a function that returns as an array of all dates between two other dates. This is fairly simple to write, but I need to be able to test my code, and also have automation for the code testing.

I am currently using IntelliJ as my IDE and it does not really support javascript (in the java edition). It does add code insight so that it will complete methods which is very nice. But I don’t have an option to run the code or validate it.

So for testing I use the following site: http://www.webtoolkitonline.com/javascript-tester.html.

But I would like to have automated testing so that if I can run the code and know that it will run properly.

Java does have a built in javascript interpreter and it has been upgraded in java 8. So what I have done is to create a java unit test that invokes the javascript and then validates the results.

First step is to load the javascript file into the engine. To create the engine you can just create it using the manager:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");

Note: You have the option to choose between JavaScript and nashorn for your engine.

You then need to load the javascript file and invoke the method with parameters. So for example I have the following utility method:

   private Object invokeFunction(String name, Object... args) {

       try {
           ScriptEngineManager factory = new ScriptEngineManager();
           ScriptEngine engine = factory.getEngineByName("JavaScript");
           final File file = new File(".", "src/main/resources/js/dateFunctions.js");
           engine.eval(new java.io.FileReader(file));
           Invocable inv = (Invocable) engine;
           return inv.invokeFunction(name, args);
       } catch (Exception e) {
           throw new RuntimeException(e);
       }
   }

Now I can easily create standard JUnit tests to call the javascript functions with parameters and then test the results.

So for example:

@Test
public void getBetweenMonthsInclusiveInternal() throws FileNotFoundException, ScriptException, NoSuchMethodException {
   ScriptObjectMirror res = (ScriptObjectMirror) invokeFunction("getBetweenMonthsInclusiveInternal", "Sat Dec 31 2016 16:00:00 GMT-0800 (PST)", "Sun Jan 01 2017 06:44:58 GMT-0800 (PST)");
   Assert.assertEquals(1, res.size());
   Assert.assertEquals(1, res.get("0"));
}

What you need to check is when writing tests is the return value. If your javascript method returns a primitive like String or Integer, you can cast it directly to that type. In our case we return an array of integers.

Summary

For java programmers that would like to stay within known frameworks can still write code in javascript and have the option to code with java JUnit tests for automation.

For full code examples see the javascript code at:

https://github.com/chaimt/TurelUtils/blob/master/src/main/resources/js/dateFunctions.js

And the unit tests at:

https://github.com/chaimt/TurelUtils/blob/master/src/test/java/com/turel/utils/js/udfScripts.java