Anyone have a pattern for loading a JS file into load() using using Javascript scripting engine
?
by default you can use:
load('path/url to JS file');
But you can also do load({script: "my script wrapped in a string", name: "myscript.js"});
I was getting the bytes[] of the js file i deployed along side of the bpmn file. But i cannot seem to get the bytes to convert to a string.
Looking for other patterns that you may have used as well.
I have loaded the file from a URL, but there seems to be a relatively “significant” delay for the file to load from a url.
With from deployment, do you mean deployment in terms of Camunda API or application deployment (e.g. WAR file)?
@thorben: deployment from camunda API
Given that you have the bytes of the deployment resource, here is how you convert it to a String in Nashorn Javascript:
var String = Java.type("java.lang.String");
load({ script: new String("print('hello')".getBytes("UTF-8"), "UTF-8"), name: "myscript.js"});
@thorben
So if i have something like:
var processDefinitionId = execution.getProcessDefinitionId();
var deploymentId = execution.getProcessEngineServices().getRepositoryService().getProcessDefinition(processDefinitionId).getDeploymentId();
var resources = execution.getProcessEngineServices().getRepositoryService().getDeploymentResources(deploymentId);
var file = '';
for each (var resource in resources){
if (resource.getName() == 'my-script.js'){
file = resource.getBytes('UTF-8');
}
}
var String = Java.type("java.lang.String");
load({ script: new String(file, "UTF-8"), name: "my-script.js"});
You expect this to work?
The load() / conversion into a string will not seem to read the bytes returned by getDeploymentResources
Hi Stephen,
I believe Resource#getBytes
has no String
argument. If you remove that, it might work (although Resource#getBytes
is not public API, so if you want to stay with public API, you should go via RepositoryService#getResourceAsStream
. What is the error you get when you try this?
Cheers,
Thorben
var processDefinitionId = execution.getProcessDefinitionId();
var deploymentId = execution.getProcessEngineServices().getRepositoryService().getProcessDefinition(processDefinitionId).getDeploymentId();
var resource = execution.getProcessEngineServices().getRepositoryService().getResourceAsStream(deploymentId, 'my-script.js');
var String = Java.type("java.lang.String");
load({ script: new String(resource, "UTF-8"), name: "my-script.js"});
resource
returns a java.io.ByteArrayInputStream
But the above code also fails.
Exception while closing command context: java.lang.NoSuchMethodException: None of the fixed arity signatures [(byte[], java.lang.String), (byte[], int)] of method java.lang.String.<init> match the argument types [java.io.ByteArrayInputStream, java.lang.String]
java.lang.RuntimeException: java.lang.NoSuchMethodException: None of the fixed arity signatures [(byte[], java.lang.String), (byte[], int)] of method java.lang.String.<init> match the argument types [java.io.ByteArrayInputStream, java.lang.String]
I am no Java expert. So I may be missing something here. But based on my understanding, and other java examples I have looked at, this should work?
You are missing code that reads the input stream into a byte array. This is surprisingly painful in plain Java. I think Apache’s IOUtils have convenience methods for that. See for example https://stackoverflow.com/questions/1264709/convert-inputstream-to-byte-array-in-java. Also, for the sake of quick testing, what happens when you use Resource#getBytes
?
Ha! yes tried getBytes ;). NoMethodFound
@thorben okay this works to render the file:
var processDefinitionId = execution.getProcessDefinitionId();
var deploymentId = execution.getProcessEngineServices().getRepositoryService().getProcessDefinition(processDefinitionId).getDeploymentId();
var resource = execution.getProcessEngineServices().getRepositoryService().getResourceAsStream(deploymentId, 'my-script.js');
var IOUtils = Java.type('org.apache.commons.io.IOUtils');
var String = Java.type('java.lang.String');
load({ script: new String(IOUtils.toByteArray(resource), 'UTF-8'), name: 'my-script.js'});
1 Like
Cool. Perhaps you can extract this logic into a separate Javascript file, put it somewhere on the shared classpath and then load your loader utility via load('classpath:path/to/resourceLoader.js')'
. That would keep the logic in one place. See https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions (load
section) for all the ways how to load scripts in Nashorn.
1 Like
Good idea. Knew about the feature, but had not thought about that use case!
One problem i have noticed with the load({ script: new String(IOUtils.toByteArray(resource), 'UTF-8'), name: 'my-script.js'});
strategy is that the JS file is loaded differently than with use load('http://...')
. Seems to be mainly issues with escaping quotes.
Just a FYI for anyone that comes across this.