Reputation: 43
I have been using SAXON HE 9.5.1-5 for a while, successfully. We are doing a general upgrade of some versions of components in our platform, and included in this was moving to Saxon 9.8.0-8 The code fails using that version. The following is in our Spring beans file:
<bean id="xpathFactory" class="net.sf.saxon.xpath.XPathFactoryImpl" factory-method="newInstance"/>
<bean id="xpath" factory-bean="xpathFactory" factory-method="newXPath"/>
<bean id="myRequestValidator" class="gov.dhs.ice.prime.query.RequestValidator">
<constructor-arg index="0" ref="xpath"/>
As you can see, the last bean is passed the result of the "newXPath" method. For debug, I get the name of the passed in object. When using 9.5.1-5, the incoming object is a net.sf.saxon.xpath.XPathEvaluator object Now with 9.8.0-8, I am receiving an org.apache.xpath.jaxp.XPathImpl object
The RequestValidator program then does some XPath compiles as part of the constructor. With the XPathEvaluator object, everything as fine (as it has been all along)
Now that I am getting an org.apache.xpath.jaxp.XPathImpl object, the constructor fails when the program attempts to compile a V2 XPath statement. V1 works fine.
So, why is this newer version returning a different object than before?
I did try just constructing the net.sf.saxon.xpath.XPathEvaluator directly..
<bean id="xpath" class="net.sf.saxon.xpath.XPathEvaluator"/>
<bean id="myRequestValidator" class="gov.dhs.ice.prime.query.RequestValidator">
<constructor-arg index="0" ref="xpath"/>
And that worked with the new version. But, it seems like the docs recommend the earlier approach.
Any ideas what is going on here? Thanks
Upvotes: 1
Views: 138
Reputation: 167716
Saxon for some releases does no longer register itself as a JAXP XPathFactory, see http://saxonica.com/html/documentation9.8/xpath-api/jaxp-xpath/factory.html:
The JAXP API is designed on the basis that when your application invokes XPathFactory.newInstance(), an XPath engine is selected by examining the values of system properties and searching the classpath. If you rely on this mechanism, then your application may end up running with an XPath engine on which it has never been tested. Since different XPath engines can differ in many significant respects (most notably, the version of XPath that they support), this can easily lead to application failures. Saxon therefore no longer identifies itself (in the JAR file manifest) as a JAXP XPath supplier. If you want to load Saxon as your XPath engine, you need to select it explicitly; it's not enough to just put it on the classpath
And the newInstance
method you think you are calling on net.sf.saxon.xpath.XPathFactoryImpl
is in reality the method of the abstract base class https://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance-- and that is calling the other overload https://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance-java.lang.String- of the base class that is supposed to load the JAXP registered XPathFactory.
So what you ought to do is: "If you want to use Saxon as your XPath implementation, you must instantiate the class net.sf.saxon.xpath.XPathFactoryImpl directly.", e.g. in Java code new net.sf.saxon.xpath.XPathFactoryImpl()
.
I am not sure how that is expressed in that bean syntax declarative way but perhaps you know that or someone else can help with that.
Upvotes: 2