Java Load a script by default in ScriptEngine - java

Is there any way to include (or load) a external script to the script engine so that all the functions defined in the external script are available in the engine.eval() method ?
In our application we execute some java script code based on user inputs. When a user requests comes the application create a ScriptEngine instance and execute the appropriate javascript code based on the input parameters.
The problem here is there are some repeated functionality in the javascript. Consider an example :
Scenario 1 : Calculate distance when user input is decimal latitudes and longitudes
-> Here I can simply calculate and return the distance.
Scenario 2 : Calculate distance when user input is Degrees-Minutes-Seconds latitudes and longitudes.
-> Here convert the Degrees-Minutes-Seconds input into decimal latitudes and longitudes and then process same as Scenario 1.
As they are different scenario calculateDistance code is duplicated.
So is there any way I could have an script containing reusable functions and load it when I create a ScriptEngine instance.
Note : I am using Java 8 along with the bundled Nashorn JavaScript Engine.
Any ideas and/or suggestion ?

You can use the load() function in your javascript code (doc here). Someting like :
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("load('myScript.js');");
It's an easy way, but doesn't fit for deployment (relative paths always change, ressources access may be different in your IDE, Jar, war...).
I personnaly use a very simple interface to provide the script content, which then came from a ressource, external file, DB... and then use the result in eval().
public interface ScriptLoader {
public String getScriptContent(String relativePath);
}
ScriptLoader loader;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(loader.getScriptContent('myScript.js'));
If your script source is not dynamic, it may also be usefull to keep your engine's instance cached, as the first cold start/parsing can be very long.

Related

Parsing non-fixed format binary payload with a custom javascript conversion in Vorto

We are using Vorto now mainly as a normalized format and are starting to look into using the mapping engine for mapping different payload formats to Vorto model as well. I more or less understand how to map functionblock properties from JSON or binary payload using xpath and the conversion functions. However, I'm not clear how to support parsing of non-fixed format binary payload using this method.
For instance we have an off the shelf LoRaWAN sensor which transmits in the following format:
<length><frame type>[<sensor-id><sensor-value>] where length is the total frame length and sensor-id (for eg temperature, humidity, battery, ...) describes how to parse the sensor-value (ie length, datatype). In one frame multiple of these readings may be present in random order.
Parsing this can be done easily in for instance loraserver.io using a small javascript function which iterates over all the bytes en returns the parsed properties. The same way will work in the Ditto payload mapping engine afaik.
However, currently I don't see how to do something similar in Vorto mapping. This is just one specific sensor example of course, but more examples exist on the market using similar dynamic payload format. I know there is already an open issue (#1535) to improve the documentation, but it would already be helpful to know if such flexible parsing would be possible using the mapping DSL.
I tried passing the raw payload as bytearray to the javascript function. In order to test this I duplicated the org.eclipse.vorto.mapping.engine.converter.binary.BinaryMappingTest#testMappingBinaryContaining2DataPoints and adapted the model to use a custom javascript function like this
evaluator.addScriptFunction(new ScriptClassFunction("extractTemperature",
"function extractTemperature(value) { " +
" print(\"parameter of type \" + typeof value + \", value = \" + value);" +
" print(value[1]);" +
"}"));
The output of this function is
parameter of type number, value = 1
undefined
Where the value 1 is the first element of the bytearray used.
So the function does not seem to receive the parameter as bytarray.
The model is configured with .withXPathStereotype("custom:extractTemperature(data)", "demo") so the payload is passed (as BinaryData) in the same way as in the testMappingBinaryContaining2DataPoints test (.withXPathStereotype("custom:convert(vorto_conversion1:byteArrayToInt(data,0,0,0,2))", "demo")). The only difference I see now is that in the testMappingBinaryContaining2DataPoints test is that the byetarray parameter is passed to a Java function instead of a javascript function. Or am I missing something?
Also, I noticed that loop keywords like for and while are not allowed in the javascript code. So even if I can access the bytearray parameter in the javascript function I see no way for now how to iterate over this.
On gitter I received following reply (together with the suggestion to move discussion to SO)
You are right. We restricted the Javascript function usage to very rudimentary set of language keywords excluding for loops as nasty stuff can be implemented there. What you could do Instead is to register a java function In your own namespace to the mapping engine. That function can hold a byte array. Later this function can be contributed to the mapping engine as a standard function to extract a certain value out for other developers to reuse.
I don't think this is solution to the problem however. As mentioned above this is just one example of an off the shelf sensor payload format, and I don't see how this can be generalized enough to include as a generic function in the mapping engine. And I don't think it should be required to implement a sensor specific conversion in Java, since (as an end-user of an IoT platform wanting to deploy a new sensor type) this is more complex to develop and deploy than a little javascript function which can be altered at runtime in the mapping spec. I see a lot of value in being able to do simple mappings in javascript, just like this can be done in for example loraserver.io and Eclipse Ditto.
I think being able to pass a byte array to javascript is a first step. Also I wonder where exactly the risk is in allowing loops in the javascript? For example Ditto also has some restrictions in the javascript sandbox (see here) but this allows loops and only prevents endless looping and recursion.
They state the following:
Using Rhino instead of Nashorn, the newer JavaScript engine shipped with Java, has the benefit that sandboxing can be applied in a better way.
Sandboxing of different payload scripts is required as Ditto is intended to be run as cloud service where multiple connections to different endpoints are managed for different tenants at the same time. This requires the isolation of each single script to avoid interference with other scripts and to protect the JVM executing the script against harmful code execution.
Would using Rhino in Vorto as well allow to control the risks you see and allow loop construct in Vorto mapping?
PS: can someone with enough SO reputation points add the tag eclipse-vorto please?
I created an issue for you request to support this in the Javascript converters: https://github.com/eclipse/vorto/issues/2029
As stated in the issue, as a current workaround, you can register your own custom converter function with Java and re-use this function across your mappings. In these java converter functions, you have all the power of the java language to convert to extract the right property from the arbitrary list.
In order to find out how to implement your own custom converter function with Java, take a look here: https://github.com/eclipse/vorto/tree/master/mapping-engine#Advanced-Usage
Since Eclipse Vorto 0.12.3 release, a fix for your request is available. With this it is possible to pass array object to javascript Converter as well as use for loops inside javascript functions. You might wanna give it a try.
See release notes https://github.com/eclipse/vorto/blob/master/docs/release-notes.md

Elki plots from pure Java API

I've been searching for a way to export ELKI generated visualization into SVG file, which can later be displayed on my application. However, I could not find any example code which uses typical java constructors. My goals are:
input Results in a Visualization.
set VisualizerParameterizer constructor, adding the previous Visualization.
set ExportVisualizations constructor properly to write the file.
For instance, let's say I already have an OutlierResult instance and now I want to plot the scores using BubbleVisualization and produce an SVG file? How can I do that using the pure Java API?
Some classes like VisualizerParameterizer can be a bit annoying to set up manually, because this involves finding all desired visualization factories from the service loader - there is a plug-in layer there, that allows to add new visualizations to be rendered automatically.
Because of this, the easiest way is to use the parameterization API, for example (git style):
ExportVisualizations export = new ELKIBuilder<>(ExportVisualizations.class)
.with(ExportVisualizations.Parameterizer.FOLDER_ID, "folder")
.build();
or if you are still using an old release / do not like builders:
ListParameterization params = new ListParameterization();
params.addParameter(ExportVisualizations.Parameterizer.FOLDER_ID, "folder");
ExportVisualizations export = ClassGenericsUtil.parameterizeOrAbort(
ExportVisualizations.class, params);
Because you only need to give mandatory parameters, and it can construct nested objects. In this case, it will also construct the VisualizerParameterizer, so you can also add options for that class, such as
.with(VisualizerParameterizer.Parameterizer.ENABLEVIS_ID, "scatter")
to only enable scatter plot visualizations.

C# to automate Java application with Java Access Bridge

I have a Java application that I want to automate for testing. Unfortunately, the app window only registers as a SunAWTFrame, which means none of the controls are exposed to typical window analysis and automation tools.
My search has lead me to C# and utilising Java Access Bridge DLLS in a C# program to automate it.
Has anyone had any experience of this?
Oracle provides JavaAccessBridge (JAB) with some DLLS to help with this as I understand it after reading a few articles around the internet. There are some code examples but I'm really not groking it right now. By breaking it down, I think this is what needs to be achieved:
Import / load / parse the JAB dlls
Map functions in the JAB dll to methods / calls within my program
Have the Java application to automate run (with JAB enabled) and get handle of it to my program
Utilise the JAB functions to control the Java application
I don't know C# as well as I know Java, but that's not going to stop me.
If anyone can provide help, guidance, pointers or anything to get me started, that'd be truly awesome.
As of 2019 we have a great tool AccessBridgeExplorer created and open-sourced by google. It's a really good staring point that contains a WindowsAccessBridgeInterop project which encapsulates almost every JAB API into a class oriented, .NET friendly assembly.
One notable thing, AccessBridge.Initialize() must be called in WPF/WinForm UI thread or in your own messaging pump thread, otherwise some methods like AccessBridge.EnumJvms() will always return false/empty.
Building on Stackia's great tip to use Google's AccessBridgeExplorer, Here are some tips to get you going:
Download Access Bridge Explorer
Use the WindowsAccessBridgeInterop.dll in your own (WinForms not Console) project (Add> Project Reference> Select the DLL)
Create a new access bridge object
AccessBridge Java = new AccessBridge();
Initialize the Access Bridge object
Java.Initialize();
Call Application.DoEvents() - A hack to wait for Java.Initialize to complete (My simple understanding is Java Access Bridge Uses a hidden window or similar)
Application.DoEvents(); //this waits for Java Bridge to initilize ;)
Get the handle of the Java Window
(plenty of examples online of how to get a Window Handle in C#)
Get Access to the Java Object that represents the window:
Java.Functions.GetAccessibleContextFromHWND(Handle, out int vmid, out JavaObjectHandle javaObjectHandle);
Get AccessibleWindow Object for Window (so you can find its children)
AccessibleWindow win = Java.CreateAccessibleWindow(handle);
Come up with your own way to cycle through the children, and the childrens children until you find the object you are after:
//Similar to:
foreach(var child in win.GetChildren())
JavaObjectHandle? javaObject = Java.Functions.GetAccessibleChildFromContext(node.JvmId, parentJavaObject, child.GetIndexInParent());
//to get the label or title of the object:
child.GetTitle();
To Interact with an object (eg click a button), do similar to the following:
(please note where it says JavaObject - it means the child java object (eg. to click a button you need to get the JavaObject for that button using GetAccessibleChildFromContext as i mentioned above)
//Get Possible Actions
JavaAutomation.Java.Functions.GetAccessibleActions(VMID, JavaObject, out AccessibleActions accessibleActions);
foreach( var action in accessibleActions.actionInfo)
{
Log.Info($"DoAction: {action.name}");
}
AccessibleActionsToDo accessibleActionsToDo = new AccessibleActionsToDo();
accessibleActionsToDo.actions = accessibleActions.actionInfo;
accessibleActionsToDo.actionsCount = accessibleActions.actionsCount;
//Do Actions
JavaAutomation.Java.Functions.DoAccessibleActions(VMID, JavaObject, ref accessibleActionsToDo, out int failure);

Real Life Scenarios to use ScriptEngineManager in Java

I am aware we can use ScriptEngineManager to execute scripts for example: java script.
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
public class Test {
public static void main(String[] args) throws Exception{
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = "40+2";
System.out.println(engine.eval(foo));
}
}
But this is a very trivial example and I am not sure in what real scenarios ScriptEngineManager can be used? Please elaborate.
Let me try to answer this from my project standpoint.
We have a framework that will make outbound calls and allow the integrators to extract the portions from json response and map it into internal data model.
This is completely driven by metadata, integrator uses the jsonpath (similar to xpath but for json ) to specify what to extract and what to map it to.
But there are times, where the integrator want to specify some of these conditionally.
For example, if the json value extracted is null, I want model to have 0.
If the array length is 0, then i want to use certain value.
We have exposed these logic as javascript. We execute the javascript using this engine to find out what the inetgrator wanted to do with the data ( basically we execute the script provided by integrator on the data obtained and set that value on the model, which eventually gets persisted )
Hope this answers your question.
There are many possible uses. For example: automation. The Microsoft Office programs and also Adobe Photoshop can run scripts to automatically execute functions of the program. You could use the Java script engine API for something similar in a Java application.
I used it once in a project where our software had to do some complex data processing. Certain parts of the processing could be customized by running a script. The advantage of this was that the script could be modified easily; if we would have written the custom processing in Java that would mean that every time when some small change was necessary, we would have to make a whole new build of the system.
Going by the differences, Java is statically typed, implying, the program written in Java, is first compiled and then run but in case of dynamically typed languages, like JavaScript and Python, we can execute even a part of the program for it is not compiled as a whole as such.
Coming to the question, suppose you have a server(eg: WildFly) on which you have deployed your application. Now building and hosting is a time intensive process, thus if you have to make any small change, you'll have to rebuild it and then again go through that time consuming process but if you could have used any dynamically typed language like JavaScript in place of it, it would have taken no time and in the next implementation, you would have been ready with the updated code. That's the main advantage of using JS and thus ScriptEngine was added in JSR.
Currently I'm working with JBoss to add ScriptEngine functionality to their WildFly server so have been spending time with it in the real time.

Custom interpreter in java

Hi
I want to write a program to be able to parse & execute some files
The file consists of some custom commands (I want to be able to define commands and appropriate methods so when program see that command it should execute the appropriate method)
It's grammar is not important for me; I just want to be able to define commands
Something like a simple and small interpreter written in java.
Is there any library for this purpose?
Or I need to write by myself?
Thanks
Java 6 (and newer) have this in the standard library: have a look at the API documentation of the package javax.script. You can use this to run scripts from your Java program (for example to automate your program) using any scripting language for which there is a plug-in engine available for the javax.script API. By default, support for JavaScript is supplied.
See the Java Scripting Programmer's Guide.
Simple example from that guide:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
engine.eval("print('Hello, World')");
}
}
Have you considered looking at BeanShell?
Provides for having Java-like snippets interpreted at runtime.
If you need a bit more than that, then consider embedding e.g. JPython or another small interpreter. Just choose one that is JSR-233 compliant to get generic debugging support.
What you need is called "scripting engine". Quick search reveals Rhino. This is a good option cause it's JavaScript, and many people know JavaScript and there exists a certain amount of third-party extensions (libraries and code snippets) for it.
You could use ANTLR, but you will have to define a grammar (the parser will be generated for you).
Check this expression elevator example, it is similar to your problem, but instead of reading files it reads from the standard input.
If you choose ANTLR, take I look at ANTLRWorks, it is a GUI that will help with ANTLR development (I think it is also available as an Eclipse plugin).
I know this an old thread, but some time ago I've implemented a small interpreter for language similar with JavaScript (with more restrictions), the code is published in Github at https://github.com/guilhermelabigalini/interpreter
But it does support IF/CASE/LOOPS/FUNCTIONs, see below:
function factorial(n) {
if (n == 1)
return 1;
return n * factorial(n - 1);
}
var x = factorial(6);

Categories

Resources