Screwtape
Screwtape

Reputation: 1367

What could be causing NullPointerException in Camel XSLT processing?

For the last few weeks, I have been trying to deal with an intermittent problem on a camel route using XSLT processing following aggregation. It is intermittent in the sence that while it frequently raises this exception, I can re-run the data extract and processing that failed a few seconds later and it usually succeeds. I have yet to find any data that fails consistently.

I am assuming that the aggregation is causing the problem, but I can't for the life of me understand why. I thought it might be the custom aggregation bean I was using, so I replaced it with XSLTAggreationStrategy, but it still intermittently gives this issue, either when further transforming the aggregated XML, or when just writing it out to the a file.

This is executing in an Apache-Karaf environment, and I have Camel-Saxon 2.21.2 and Apache ServiceMix Saxon-HE 9.8.0.8_1 bundles loaded.

Thanks for looking.

The abridged stack trace is:

... Caused by: [java.lang.NullPointerException - null]java.lang.NullPointerException at net.sf.saxon.dom.DOMNodeWrapper$ChildEnumeration.skipFollowingTextNodes(DOMNodeWrapper.java:1149) at net.sf.saxon.dom.DOMNodeWrapper$ChildEnumeration.next(DOMNodeWrapper.java:1178) at net.sf.saxon.tree.util.Navigator$EmptyTextFilter.next(Navigator.java:1078) at net.sf.saxon.tree.util.Navigator$AxisFilter.next(Navigator.java:1039) at net.sf.saxon.tree.util.Navigator$AxisFilter.next(Navigator.java:1017) at net.sf.saxon.expr.parser.ExpressionTool.effectiveBooleanValue(ExpressionTool.java:643) at net.sf.saxon.expr.Expression.effectiveBooleanValue(Expression.java:532) at net.sf.saxon.pattern.PatternWithPredicate.matches(PatternWithPredicate.java:141) at net.sf.saxon.trans.Mode.searchRuleChain(Mode.java:570) at net.sf.saxon.trans.Mode.getRule(Mode.java:476) at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:1041) at net.sf.saxon.expr.instruct.ApplyTemplates.apply(ApplyTemplates.java:281) at net.sf.saxon.expr.instruct.ApplyTemplates.processLeavingTail(ApplyTemplates.java:241) at net.sf.saxon.expr.instruct.Template.applyLeavingTail(Template.java:239) at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:1057) at net.sf.saxon.expr.instruct.ApplyTemplates.apply(ApplyTemplates.java:281) at net.sf.saxon.expr.instruct.ApplyTemplates.process(ApplyTemplates.java:237) at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:431) at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:373) at net.sf.saxon.expr.instruct.Template.applyLeavingTail(Template.java:239) at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:1057) at net.sf.saxon.Controller.transformDocument(Controller.java:2080) at net.sf.saxon.Controller.transform(Controller.java:1903) at org.apache.camel.builder.xml.XsltBuilder.process(XsltBuilder.java:141) at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103) at org.apache.camel.component.xslt.XsltEndpoint.onExchange(XsltEndpoint.java:138) ...

Upvotes: 0

Views: 316

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

In 9.8.0.8, the class net.sf.saxon.dom.DOMNodeWrapper has only 1144 lines, so a stacktrace showing line 1178 suggests there's some kind of versioning problem.

The class DOMNodeWrapper was first introduced in 9.5 (previously it was called NodeWrapper), and the line numbers are just one off from those in the current 9.5 source, so I suspect what you have loaded is some sub-release of the 9.5 branch. Other line numbers in the stack trace are also consistent with this being 9.5.

That of course doesn't explain the problem, but it might give a clue.

My immediate instinct was that over the years since 9.5 we might have fixed a multi-threading bug. DOM is not thread-safe, so Saxon takes considerable care to synchronize its access. Saxon bug https://saxonica.plan.io/issues/2376 addresses this problem. On the 9.5 branch this was first fixed in maintenance release 9.5.1.11, so it's possible you don't have that patch. I think it would be useful to investigate why you are loading an old version of Saxon, and another useful angle would be to discover exactly which version it is (the static method net.sf.saxon.Version.getProductVersion() will give you this information.)

Incidentally, if you are using multi-threaded access to a DOM tree then you should ask yourself whether this is a good idea. Saxon access to DOM is slow at the best of times (compared to JDOM and XOM, let alone to Saxon's native tree model), and the lack of thread safety and the need for synchronisation makes it a pretty poor choice in a multi-threaded application.

Also, note that Saxon can synchronize its own access to the DOM, but it can't synchronize with third-party code that might also be using the DOM.

Upvotes: 3

Related Questions