I am trying to get a project working using GeoTools with a dependency that uses Saxonica. So far, no luck
Project pom.xml
dependencies:
<dependencies>
<dependency>
<groupId>org.auscope.portal</groupId>
<artifactId>portal-core</artifactId>
<version>${portal.core.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>14.2</version>
</dependency>
</dependencies>
portal-core
pom.xml
relaveant dependencies:
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>saxon-xom</artifactId>
<version>8.7</version>
</dependency>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>saxon-xpath</artifactId>
<version>8.7</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>saxon-dom</artifactId>
<version>8.7</version>
<optional>false</optional>
</dependency>
SLDController.java
code:
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
StyledLayerDescriptor sld = styleFactory.createStyledLayerDescriptor();
sld.setName("example");
sld.setAbstract("Example Style Layer Descriptor");
UserLayer layer = styleFactory.createUserLayer();
layer.setName("layer");
FeatureTypeConstraint constraint = styleFactory.createFeatureTypeConstraint("Feature", Filter.INCLUDE, null);
layer.layerFeatureConstraints().add(constraint);
Style style = styleFactory.createStyle();
style.getDescription().setTitle("Style");
style.getDescription().setAbstract("Definition of Style");
layer.userStyles().add(style);
sld.layers().add(layer);
SLDTransformer styleTransform = new SLDTransformer();
String xml = styleTransform.transform(sld);
Stack trace:
net.sf.saxon.trans.XPathException: The SAX2 parser org.geotools.xml.transform.TransformerBase$XMLReaderSupport does not support setting the 'namespaces' feature to true
net.sf.saxon.event.Sender.configureParser(Sender.java:562)
net.sf.saxon.event.Sender.sendSAXSource(Sender.java:313)
net.sf.saxon.event.Sender.send(Sender.java:152)
net.sf.saxon.IdentityTransformer.transform(IdentityTransformer.java:39)
org.geotools.xml.transform.TransformerBase$Task.run(TransformerBase.java:300)
org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:133)
org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:121)
org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:162)
org.auscope.portal.server.web.controllers.SLDController.getOilAndGasStyle(SLDController.java:53)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:177)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:82)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
I'm guessing this an issue that can be fixed using Maven, but I'm a bit lost. How do I ensure that my project uses the right XSLT processor for GeoTools while not breaking the configuration of the portal-core dependency?
Well, the message in the stack trace tells you exactly what's wrong:
The SAX2 parser org.geotools.xml.transform.TransformerBase$XMLReaderSupport does not support setting the 'namespaces' feature to true
Saxon by default gets hold of a SAX2 parser using the JAXP factory mechanism, and the parser it has found is one that belongs to the geotools project.
The SAX2 specification says: "All XMLReaders are required to support setting http://xml.org/sax/features/namespaces to true" but it appears that this particular XMLReader does not allow this setting, and the result is that Saxon is unable to use this parser.
There are all sorts of workarounds that might be possible, but devising one is going to need some knowledge of geotools, which I certainly don't have. For example, I have no idea whether this parser is actually needed for the task in hand, or whether a different one would do.
The stack trace also shows that geotools is trying to do an identity transformation, and is using Saxon for the purpose. It's probably picked up whatever transformer is lying around on the classpath, by using the JAXP factory mechanism to load it. That's a bad strategy: if you're going to use the JAXP mechanism to load your identity transformer, then you should test your code first to check that it works with the most common ones. It might be possible to persuade geotools to use a different identity transformer by setting the relevant JAXP system property.