I tend to agree with the opinion of the author (@searchengine27) of the first comment on the accepted answer. Patching container configuration doesn't look like a robust and maintainable solution.
For instance, with the JBoss Wildfly installation, I got only one place where the mentioned module was defined, but with the JBoss EAP 7.4 patched to work under Java 17 there were two places, thus having the container updated just ruined the working program.
It's also worth mentioning that JBoss is provided with the particular implementation of javax.api
on purpose (tested security, etc.) and one should think twice before deciding to turn it off.
I encountered the same problem with a third-party library instantiating Schemafactory
and setting the accessExternalDTD
property to it.
Everything worked well when the application was running in a Docker container under OpenJDK17 and got into trouble running inside the JBoss container.
The solution I propose is to provide with your program an implementation of SchemaFactory
that leverages either org.apache.xerces
implementation, or the default one from the JDK (OpenJDK17 in my case).
I've chosen the latter because I found it newer and supports the next version of the JAXP standard.
Here is the code of the Jdk17DefaultSchemaFactoryWrapper
class:
package my.package.utils.jaxp;
import lombok.experimental.Delegate;
import javax.xml.validation.SchemaFactory;
public class Jdk17DefaultSchemaFactoryWrapper extends SchemaFactory {
@Delegate
SchemaFactory factory = SchemaFactory.newDefaultInstance();
}
Instead SchemaFactory.newDefaultInstance()
probably SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI, "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", ClassLoader.getSystemClassLoader())
could be used to make sure that the SchemaFactory
from the JDK gets used.
And the Jdk17DefaultSchemaFactoryWrapper
class has to be registered as javax.xml.validation.SchemaFactory
. I've done it via creating a file META-INF/services/javax.xml.validation.SchemaFactory
and putting the full quilified name of the Jdk17DefaultSchemaFactoryWrapper
class as its contents.
As Mr. @Appernicus provided in his answer to this question, other ways could be approached to get done the same.
Alternative Solution
An alternative solution would be to use the implementation provided by the container.
To do that, one would need to add the org.apache.xerces
dependency with the scope: provided
to their POM and the following XMLSchemaFactoryWrapper
implementation:
package com.temenos.multifonds.integration.integrationBroker.utils.jaxp;
import lombok.experimental.Delegate;
import org.apache.xerces.jaxp.validation.XMLSchemaFactory;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import javax.xml.XMLConstants;
import javax.xml.validation.SchemaFactory;
public class XMLSchemaFactoryWrapper extends SchemaFactory {
@Delegate(excludes = DelegateExclude.class)
SchemaFactory factory = new XMLSchemaFactory();
@Override
public void setProperty(String name, Object object) throws SAXNotRecognizedException, SAXNotSupportedException {
if (XMLConstants.ACCESS_EXTERNAL_DTD.equals(name))
return;
super.setProperty(name, object);
}
private interface DelegateExclude {
void setProperty(String name, Object value);
}
}
As you might notice, the problem with this solution is that the accessExternalDTD
property actually gets ignored.
In my case, it wasn't a problem because XML schemas didn't use external schemas and the property was set by the third party to cover some future cases.
Though, knowing pros and cons and limitations of the provided solutions it should be possible to find the one that suits your particular case.