Summary: I am trying to use the documentation on JavaScript SPARQL Functions to get a minimal working example of calling a custom javascript function, but it results in a scriptEngine null error.
Details: I setup a fuseki environment following the Docker instructions, so:
docker build --force-rm --build-arg JENA_VERSION=3.16.0 -t fuseki .
I then create a functions.js
file per the documentation on JavaScript SPARQL Functions and launch the Docker container with:
docker run -i --rm -p "3030:3030" --name sparql1 -v `pwd`/functions.js:/functions.js -t fuseki --update --set arq:js-library=/functions.js --mem /ds
So far, so good. I have confirmed this works for simple update and queries, so the container appears sound. However, if I now create a query.rq
file containing the example in the docs:
query=PREFIX js: <http://jena.apache.org/ARQ/jsFunction#>
SELECT ?input (js:toCamelCase(?input) AS ?X)
{
VALUES ?input { "some woRDs to PROCESS" }
}
and then proceed to dispatch this query to my container:
curl -X POST -d @query.rq localhost:3030/ds/query
then the console in which the container is running looks as follows:
% docker run -i --rm -p "3030:3030" --name sparql1 -v `pwd`/functions.js:/functions.js -t fuseki --update --set arq:js-library=/functions.js --mem /ds
[2022-03-09 16:47:20] INFO Server :: Apache Jena Fuseki 3.16.0
[2022-03-09 16:47:20] INFO Server :: Dataset Type: in-memory
[2022-03-09 16:47:20] INFO Server :: Path = /ds
[2022-03-09 16:47:20] INFO Server :: System
[2022-03-09 16:47:20] INFO Server :: Memory: 2.0 GiB
[2022-03-09 16:47:20] INFO Server :: Java: 17-ea
[2022-03-09 16:47:20] INFO Server :: OS: Linux 5.10.76-linuxkit amd64
[2022-03-09 16:47:20] INFO Server :: PID: 1
[2022-03-09 16:47:20] INFO Server :: Start Fuseki (port=3030)
[2022-03-09 16:47:23] INFO Fuseki :: [1] POST http://localhost:3030/ds/query
[2022-03-09 16:47:23] INFO Fuseki :: [1] Query = PREFIX js: <http://jena.apache.org/ARQ/jsFunction#>SELECT ?input (js:toCamelCase(?input) AS ?X){ VALUES ?input { "some woRDs to PROCESS" }}
[2022-03-09 16:47:24] WARN Fuseki :: [1] RC = 500 : Cannot invoke "javax.script.ScriptEngine.eval(java.io.Reader)" because "scriptEngine" is null
java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(java.io.Reader)" because "scriptEngine" is null
at org.apache.jena.sparql.function.js.JSEngine.build(JSEngine.java:75) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.function.js.JSEngine.<init>(JSEngine.java:61) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.function.js.EnvJavaScript.build(EnvJavaScript.java:103) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.function.js.EnvJavaScript.<init>(EnvJavaScript.java:99) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.function.js.EnvJavaScript.create(EnvJavaScript.java:52) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.function.js.EnvJavaScript.get(EnvJavaScript.java:66) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.expr.E_Function.evalSpecial(E_Function.java:66) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.expr.ExprFunctionN.eval(ExprFunctionN.java:100) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.core.VarExprList.get(VarExprList.java:106) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIterAssign.accept(QueryIterAssign.java:62) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIterProcessBinding.hasNextBinding(QueryIterProcessBinding.java:69) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIterConvert.hasNextBinding(QueryIterConvert.java:58) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:38) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:38) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.ResultSetStream.hasNext(ResultSetStream.java:74) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.sparql.engine.ResultSetCheckCondition.hasNext(ResultSetCheckCondition.java:55) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.SPARQLQueryProcessor.executeQuery(SPARQLQueryProcessor.java:324) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.SPARQLQueryProcessor.execute(SPARQLQueryProcessor.java:273) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.SPARQLQueryProcessor.executeWithParameter(SPARQLQueryProcessor.java:222) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.SPARQLQueryProcessor.execute(SPARQLQueryProcessor.java:207) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.ActionService.executeLifecycle(ActionService.java:58) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.SPARQLQueryProcessor.execPost(SPARQLQueryProcessor.java:83) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.ActionProcessor.process(ActionProcessor.java:34) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.ActionBase.process(ActionBase.java:55) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.ActionExecLib.execAction(ActionExecLib.java:107) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.server.Dispatcher.dispatchAction(Dispatcher.java:115) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.server.Dispatcher.process(Dispatcher.java:107) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.server.Dispatcher.dispatch(Dispatcher.java:101) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.apache.jena.fuseki.servlets.FusekiFilter.doFilter(FusekiFilter.java:51) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.Server.handle(Server.java:500) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383) ~[jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) [jena-fuseki-server-3.16.0.jar:3.16.0]
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938) [jena-fuseki-server-3.16.0.jar:3.16.0]
at java.lang.Thread.run(Unknown Source) [?:?]
[2022-03-09 16:47:24] INFO Fuseki :: [1] 500 Cannot invoke "javax.script.ScriptEngine.eval(java.io.Reader)" because "scriptEngine" is null (212 ms)
It's at this point I'm totally lost ... why would scriptEngine be null here?
In Apache Jena 3.16.0, the JS engine was Nashorn. Nashorn was deprecated in Java 11 and removed in Java17.
An earlier Java version will have Hashorn in.
Now Jena version 4.4.0 uses the javascript engine of choice which has been added to the classpath, and hence needs to be in the dockerfile. Jena testing uses GraalVM.