Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null Pointer Exception with p:value-available() #152

alexmilowski opened this issue May 1, 2014 · 5 comments

Null Pointer Exception with p:value-available() #152

alexmilowski opened this issue May 1, 2014 · 5 comments


Copy link

alexmilowski commented May 1, 2014

I am using version 1.0.16-95.

I have a p:value-available in a p:choose:

<p:when test="/app:collection">
<p:choose name="generate-name">
<p:when test="p:value-available('slug')">

Not sure what is happening but I get this:

at com.xmlcalabash.functions.ValueAvailable$ Source)
at net.sf.saxon.lib.ExtensionFunctionCall.effectiveBooleanValue(
at net.sf.saxon.functions.IntegratedFunctionCall.effectiveBooleanValue(
at net.sf.saxon.functions.BooleanFn.effectiveBooleanValue(
at net.sf.saxon.functions.BooleanFn.evaluateItem(
at net.sf.saxon.functions.BooleanFn.evaluateItem(
at net.sf.saxon.expr.Expression.iterate(
at net.sf.saxon.sxpath.XPathExpression.iterate(
at net.sf.saxon.s9api.XPathSelector.iterator(
at com.xmlcalabash.runtime.XAtomicStep.evaluateXPath(Unknown Source)
at com.xmlcalabash.runtime.XWhen.shouldRun(Unknown Source)
at Source)
at Source)
at Source)
at com.xmlcalabash.runtime.XPipeline.doRun(Unknown Source)
at Source)
at org.atomojo.server.xproc.XProcHelper.handle(
at org.atomojo.server.xproc.XProcRestlet.handle(

Copy link

jwcranford commented May 5, 2014

I think this is the same error I ran into using Piperack, a restlet application bundled with Calabash. I also get a NullPointerException (stack trace below), and it seems related to the use of a thread-local variable in XProcExtensionFunctionDefinition, which both ValueAvailableCall and SystemPropertyCall extend. My guess is that the way that restlet uses threads doesn't work with the thread-local variable, but more on that later.

Stack trace first, then steps on how to reproduce. Note that the stack trace below is from the latest commit on the saxon95 branch (commit eb361d9), built with debug symbols.

com.xmlcalabash.core.XProcException: java.lang.NullPointerException
at com.xmlcalabash.piperack.BaseResource.runPipeline(
at org.restlet.resource.ServerResource.doHandle(
at org.restlet.engine.connector.BaseHelper$
at java.util.concurrent.ThreadPoolExecutor.runWorker(
at java.util.concurrent.ThreadPoolExecutor$
Caused by: java.lang.NullPointerException
at com.xmlcalabash.functions.SystemProperty$
at net.sf.saxon.functions.IntegratedFunctionCall.iterate(
at net.sf.saxon.sxpath.XPathExpression.iterate(
at net.sf.saxon.s9api.XPathSelector.iterator(
at com.xmlcalabash.runtime.XAtomicStep.evaluateXPath(
at com.xmlcalabash.runtime.XAtomicStep.computeValue(
at com.xmlcalabash.runtime.XAtomicStep.computeParameters(
at com.xmlcalabash.runtime.XPipeline.doRun(
at com.xmlcalabash.piperack.BaseResource.runPipeline(
... 44 more


$ java -cp calabash.jar:lib/* com.xmlcalabash.drivers.Piperack \
-c test-piperack-config.xml
<!-- test-piperack-config.xml -->
<xproc-config xmlns="">
   <piperack-load-pipeline name="gv">general-values-example.xpl</piperack-load-pipeline>

general-values-example.xpl is copied from and is copied here for convenience:

<!-- general-values-example.xpl -->
<p:declare-step xmlns:p="" version="1.0">
    <p:input port="parameters" kind="parameter"/>
    <p:output port="result"/>
    <p:serialization port="result" indent="true"/>

        <p:input port="source">
                    <para>Some <emph>text</emph> in a paragraph.</para>

    <p:xslt template-name="root">
        <p:input port="stylesheet">
                <xsl:stylesheet xmlns:xsl="" 

                    <xsl:param name="text" required="yes"/>
                    <xsl:param name="gv" required="yes"/>

                    <xsl:template name="root">
                        <root general-values="{$gv}">
                            <xsl:sequence select="$text"/>
        <p:with-param name="text" select="/doc/para"/>
        <p:with-param name="gv" select="p:system-property('cx:general-values')"

$ curl -X POST http://localhost:8088/pipelines/gv/run

And voila! You get the stack trace above in the Piperack output.

Now for the juicy parts: here are lines 70-71 of

70             XProcRuntime runtime = tl_runtime.get();
71             XStep step = runtime.getXProcData().getStep();

tl_runtime.get() is returning a null, which turns into a NPE on line 71.

tl_runtime is declared in XProcExtensionFunctionDefinition, which both ValueAvailableCall and SystemPropertyCall extend.

public abstract class XProcExtensionFunctionDefinition extends ExtensionFunctionDefinition {
    protected ThreadLocal<XProcRuntime> tl_runtime = new ThreadLocal<XProcRuntime>() {
        protected synchronized XProcRuntime initialValue() {
            return null;

Both ValueAvailable and SystemProperty set tl_runtime in the constructor, and both read it from ValueAvailableCall and SystemPropertyCall, respectively, which are inner classes. tl_runtime isn't set anywhere else.

So here's what I think is happening. ValueAvailable and SystemProperty are created in the XProcRuntime constructor, which gets called in the main thread. However, ValueAvailableCall and SystemPropertyCall are called in a different thread via a ThreadPoolExecutor used by restlet (see stack trace above). Because they're called in a different thread, tl_runtime.get() returns the value of initialValue(), which is null.

Thus, it seems like an inherent assumption in the code that XProcRuntime is created in the same thread that executes the pipeline. That works fine for a command-line app, but doesn't seem to work well in restlet.

The same pattern seems to be used by the other extension XPath functions, so I imagine they could suffer from the same problem.

Not sure how to fix this, but I hope this information helps in diagnosing and designing a fix to the problem.

Copy link

jwcranford commented May 5, 2014

After some more digging, this issue seems related to issue 153 in the old Google project (, which is still open.

The thread-local variables were introduced in commit db9ad9b, in response to google issue 153.

Copy link

ndw commented May 5, 2014

That's a very useful analysis. Thank you, Jonathan.

So now I need to figure out some other mechanism for passing information through to the functions...

Copy link

ndw commented May 7, 2014

Ok. I think I've cracked this one. Instead of a thread local variable, I've created a singleton class to serve as a registry for XProcRuntimes. Seems to work.

ndw added a commit that referenced this issue May 8, 2014
@ndw ndw closed this as completed May 8, 2014
Copy link

jwcranford commented Jun 20, 2014

This fixes the problem with NullPointerExceptions, so I have no objection to this particular issue being closed.

However, it seems like it's a step backwards to where the code was before the old google issue 153 was addressed. Is there really a difference between a singleton registry for XProcRuntimes (what the code has now) and simply storing a reference to XProcRuntime in each extension function (the way the code was before commit db9ad9b? (You can follow the link to commit db9ad9b to see the way the code used to be.) If there isn't any real difference, then we may just be back to where we were when google issue 153 was first raised.

In case it helps, comment 3 on the old google issue 153 by Romain Deltour seems to still be relevant and potentially useful, and not addressed in the codebase.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

3 participants