Skip to content

Unable to create XsltPayloadTransformer when Saxon HE is in the classpath. #2723

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

Closed
stoussaint opened this issue Jan 29, 2019 · 4 comments · Fixed by #2724
Closed

Unable to create XsltPayloadTransformer when Saxon HE is in the classpath. #2723

stoussaint opened this issue Jan 29, 2019 · 4 comments · Fixed by #2724
Assignees
Milestone

Comments

@stoussaint
Copy link

stoussaint commented Jan 29, 2019

Affects Version(s): 4.3.19.RELEASE


After upgrading to spring-integration-xml:4.3.19.RELEASE (from 4.3.18.RELEASE), my application failed to start with the following exception :

Error creating bean with name 'XsltPayloadTransformer': Invocation of init method failed;

...

Caused by: java.lang.IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD

The cause of the exception seems to be related to the following changes

- transformerFactory = TransformerFactory.newInstance();
+ transformerFactory = TransformerFactoryUtils.newInstance();

The TransformerFactoryUtils.newInstance() force the XMLConstants.ACCESS_EXTERNAL_DTD property which doesn't seems to be supported by Saxon. If I quote answers from Michael Kay about similar subject, I understand that Saxon does not handle Xml Parser related properties.

Saxon doesn't have control of the XML parsing: we invoke the parser that the application supplies and configures.

As the problem is related to a third party dependency, I provide a side sample project as a regression test case

@garyrussell garyrussell added the status: waiting-for-triage The issue need to be evaluated and its future decided label Jan 29, 2019
@garyrussell
Copy link
Contributor

This is fixed in spring-ws on master but it looks like it is not yet in a build.

/cc @gregturn

@artembilan
Copy link
Member

I think the store is about:

if (this.templates == null) {
			TransformerFactory transformerFactory;
			if (this.transformerFactoryClassName != null) {
				transformerFactory = TransformerFactory.newInstance(this.transformerFactoryClassName, this.classLoader);
			}
			else {
				transformerFactory = TransformerFactoryUtils.newInstance();
			}
			transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
			transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "file,jar:file");
			try {
				this.templates = transformerFactory.newTemplates(createStreamSourceOnResource(this.xslResource));
			}
			catch (TransformerConfigurationException | IOException e) {
				throw new IllegalStateException(e);
			}
		}

exactly in the XsltPayloadTransformer. So, that is what we have to fix here in SI.

As a workaround you can inject Templates into this XsltPayloadTransformer based on the default TransformerFactoryUtils.newInstance().

@artembilan artembilan added type: bug backport 5.0.x and removed status: waiting-for-triage The issue need to be evaluated and its future decided labels Jan 29, 2019
@artembilan artembilan added this to the 5.1.3 milestone Jan 29, 2019
@stoussaint
Copy link
Author

stoussaint commented Jan 29, 2019

Maybe the following method could be added to (spring-ws) TransformerFactoryUtils :

public static TransformerFactory newInstance(Class<? extends TransformerFactory> transformerFactoryClass, ClassLoader classLoader)

Then XsltPayloadTransformer.onInit() can be factored this way :

TransformerFactory transformerFactory;
if (this.transformerFactoryClassName != null) {
    transformerFactory = TransformerFactoryUtils.newInstance(this.transformerFactoryClassName, this.classLoader);
} else {
    transformerFactory = TransformerFactoryUtils.newInstance();
}

Hence the unsupported properties will be ignored (with warning) in a centralized manner.

@artembilan
Copy link
Member

I factored XsltPayloadTransformer to this:

if (this.transformerFactoryClassName != null) {
			@SuppressWarnings("unchecked")
			Class<TransformerFactory> transformerFactoryClass =
					(Class<TransformerFactory>) ClassUtils.forName(this.transformerFactoryClassName, this.classLoader);
			transformerFactory = TransformerFactoryUtils.newInstance(transformerFactoryClass);
		}
		else {
			transformerFactory = TransformerFactoryUtils.newInstance();
		}
		try {
			transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "file,jar:file");
		}
		catch (IllegalArgumentException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("The '" + XMLConstants.ACCESS_EXTERNAL_STYLESHEET + "' property is not supported by "
						+ transformerFactory.getClass().getCanonicalName());
			}
		}

so, no need to add anything new to S-WS.

artembilan added a commit to artembilan/spring-integration that referenced this issue Jan 29, 2019
Fixes spring-projects#2723

Not all XML components support all the configuration properties.
For example Saxon HE doesn't support `XMLConstants.ACCESS_EXTERNAL_DTD`
and end up with an exception like:
`IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD`

* Change `XsltPayloadTransformer` to re-use `TransformerFactoryUtils`
from spring-ws as a centralized source of `TransformerFactory`
configuration.
* Wrap `XMLConstants.ACCESS_EXTERNAL_STYLESHEET` to the `try..catch`
and log INFO about not supported property

**Cherry-pick to 5.0.x & 4.3.x**
garyrussell pushed a commit that referenced this issue Jan 29, 2019
Fixes #2723

Not all XML components support all the configuration properties.
For example Saxon HE doesn't support `XMLConstants.ACCESS_EXTERNAL_DTD`
and end up with an exception like:
`IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD`

* Change `XsltPayloadTransformer` to re-use `TransformerFactoryUtils`
from spring-ws as a centralized source of `TransformerFactory`
configuration.
* Wrap `XMLConstants.ACCESS_EXTERNAL_STYLESHEET` to the `try..catch`
and log INFO about not supported property

**Cherry-pick to 5.0.x & 4.3.x**
garyrussell pushed a commit that referenced this issue Jan 29, 2019
Fixes #2723

Not all XML components support all the configuration properties.
For example Saxon HE doesn't support `XMLConstants.ACCESS_EXTERNAL_DTD`
and end up with an exception like:
`IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD`

* Change `XsltPayloadTransformer` to re-use `TransformerFactoryUtils`
from spring-ws as a centralized source of `TransformerFactory`
configuration.
* Wrap `XMLConstants.ACCESS_EXTERNAL_STYLESHEET` to the `try..catch`
and log INFO about not supported property

**Cherry-pick to 5.0.x & 4.3.x**
garyrussell pushed a commit that referenced this issue Jan 29, 2019
Fixes #2723

Not all XML components support all the configuration properties.
For example Saxon HE doesn't support `XMLConstants.ACCESS_EXTERNAL_DTD`
and end up with an exception like:
`IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD`

* Change `XsltPayloadTransformer` to re-use `TransformerFactoryUtils`
from spring-ws as a centralized source of `TransformerFactory`
configuration.
* Wrap `XMLConstants.ACCESS_EXTERNAL_STYLESHEET` to the `try..catch`
and log INFO about not supported property

**Cherry-pick to 5.0.x & 4.3.x**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants