0

We are building a common component that is a dependency for multiple other projects.

Our project does some XSLT transformations and we need to use the Saxon engine.

We have full control over the specific XSLT transformation that must use Saxon, but no control over the classpath of the applications that are dependent on us, and we don't want to force them to use Saxon for other XML work.

We can manually invoke the Saxon library directly when doing our transformations using the API provided by those factories.

The problem is that Saxon uses the ServiceLoader pattern to inject itself as the TransformerFactory implementation using this file in the jar:

[saxon.jar]/META-INF/services/javax.xml.transform.TransformerFactory

This means that applications that use us as a dependency might end up using Saxon instead of their existing XML libraries. Asking those applications to change their code to invoke their specific implementation is not an option.

Is there any way we can 'override' the Saxon library to remove the ServiceLoader implementation? Either using Maven, Java or some other process?

J Barclay
  • 481
  • 2
  • 7
  • 18
  • Near-duplicate of http://stackoverflow.com/questions/35334749/best-way-to-set-xslt-processor-in-java – Michael Kay Sep 08 '16 at 13:50
  • This is not a similar issue to the question you linked - we are trying to change the way our transitive Saxon dependency effects consumers of our framework so that they don't have to manually update their implementation. This is an easy problem to solve if we force our dependent projects to update their code. – J Barclay Sep 09 '16 at 02:06

2 Answers2

0

Unfortunately it's all too common to find yourself using libraries that have been written to use the JAXP pluggability mechanism to pick up whatever XSLT processor is on the classpath, but which will actually only work if that processor happens to be Xalan.

For the XPath scenario this problem was so acute that the Saxon META-INF no longer declares itself as an XPath service provider (although it still implements all the JAXP interfaces). But for XSLT that solution wouldn't be acceptable.

I would think that for most situations, setting the Java system property javax.xml.transform.TransformerFactory to the relevant classname for Xalan should solve the problem.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thanks for the suggestion, but unfortunately we don't control the project's that use us a dependency and therefore can't set the system property for them. We are hoping there's a way we can use Saxon directly in our library without altering the default JAXP implementation for dependent projects. – J Barclay Sep 08 '16 at 22:12
  • You might be able to do something with custom ClassLoaders, but I'm afraid I'm rather out of my depth on that. If it's Saxon-HE then of course you're in an open source world and you can rebuild the JAR file to change the META-INF. – Michael Kay Sep 09 '16 at 10:39
0

Answering this for any future developers with the same issue.

We were not able to find a way to solve this issue. We considered writing a Maven plugin to remove the META-INF/services/ file from the JAR but ultimately decided this was not an appropriate solution.

We are now in the same position we started - dependent applications end up with Saxon as a registered provider and it might override their existing configuration.

For those applications that must use a specific XSLT processer we have asked them to set the system property, e.g. javax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl

J Barclay
  • 481
  • 2
  • 7
  • 18