Search code examples
jenafuseki

Jena JavaScript custom functions scriptEngine null error


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?


Solution

  • 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.