It would be nice if wiremock would be java 9 compatible.
I ran jdeps on our project https://github.com/JabRef/jabref/issues/2594#issuecomment-331638433 and got and it complained/showed the following:
From what I found, this api is now encapsulated in java 9 (https://docs.oracle.com/javase/9/docs/api/java.xml-summary.html)
wiremock-2.8.0.jar -> java.xml
com.github.tomakehurst.wiremock.matching.EqualToXmlPattern$SkipResolvingEntitiesDocumentBuilderFactory -> com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl JDK internal API (java.xml)
I haven't had a lot of time to figure Java 9 out yet. Does the jdeps error indicate it can't be run at all? Or not as part of a modular app?
That class already throws a deprecation error in the build, so I've never liked it. Unfortunately it was the only way we could find to suppress spurious errors being logged to the console by the parser.
It can still be run with java 9, it is just a reminder that it depends on internal apis on which most of them have been already encapsulated:
And from what I saw: the old code has been moved to a new package: http://openjdk.java.net/jeps/255
OK, thanks for pointing this out. I'll add it to the burgeoning list of feature requests...
For those using the standalone JAR with Java 9 you need to add --add-modules java.xml.bind to make it run. ie.
java --add-modules java.xml.bind -jar wiremock-standalone-2.11.0.jar
Otherwise you will get the following
2017-11-28 05:48:14.869 Outgoing bytes: <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Error 500 Server Error</title>
</head>
<body><h2>HTTP ERROR 500</h2>
<p>Problem accessing /sivservice/api/users. Reason:
<pre> Server Error</pre></p><h3>Caused by:</h3><pre>java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
at com.github.tomakehurst.wiremock.common.Encoding.encodeBase64(Encoding.java:29)
at com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.getBodyAsBase64(WireMockHttpServletRequestAdapter.java:134)
at com.github.tomakehurst.wiremock.verification.LoggedRequest.createFrom(LoggedRequest.java:58)
at com.github.tomakehurst.wiremock.stubbing.InMemoryStubMappings.serveFor(InMemoryStubMappings.java:74)
at com.github.tomakehurst.wiremock.core.WireMockApp.serveStubFor(WireMockApp.java:159)
at com.github.tomakehurst.wiremock.http.StubRequestHandler.handleRequest(StubRequestHandler.java:50)
at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:44)
at com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet.service(WireMockHandlerDispatchingServlet.java:102)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at wiremock.org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812)
at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at wiremock.org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
at wiremock.org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:365)
at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)
at wiremock.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at wiremock.org.eclipse.jetty.server.Server.handle(Server.java:499)
at wiremock.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
at wiremock.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
at wiremock.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.base/java.lang.Thread.run(Unknown Source)
</pre>
<hr><i><small>Powered by Jetty://</small></i><hr/>
</body>
</html>
java.xml.bind.DatatypeConverter class shouldn't be used anymore, as it has been removed in Java 11, see JEP 320. Instead, the java.util.Base64 that was introduced in Java SE 8 should be used.
I'm getting below error when I'm running Wiremock with java module.
Java version: 11
Wiremock version: 2.20.0
Can't extract module name from wiremock-standalone-2.20.0.jar: Provider class com.fasterxml.jackson.core.JsonFactory not in module
OpenJDK 11
WireMock 2.21.0
module mymodule {
// (...)
requires wiremock;
// (...)
}
Caused by: java.lang.IllegalAccessError: superclass access check failed: class com.github.tomakehurst.wiremock.common.Xml$SkipResolvingEntitiesDocumentBuilderFactory (in module wiremock) cannot access class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl (in module java.xml) because module java.xml does not export com.sun.org.apache.xerces.internal.jaxp to module wiremock
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1095)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:206)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:761)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:682)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:607)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at [email protected]/com.github.tomakehurst.wiremock.core.WireMockApp.<clinit>(WireMockApp.java:74)
at [email protected]/com.github.tomakehurst.wiremock.WireMockServer.<init>(WireMockServer.java:71)
at [email protected]/com.github.tomakehurst.wiremock.WireMockServer.<init>(WireMockServer.java:118)
Adding requires java.xml; will not help - com.sun.org.apache.xerces.internal.jaxp is not exported from within java.xml module.
This is where problematic class DocumentBuilderFactoryImpl is used:
src/main/java/com/github/tomakehurst/wiremock/common/Xml.java
public static class SkipResolvingEntitiesDocumentBuilderFactory extends DocumentBuilderFactoryImpl {
@Override
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
DocumentBuilder documentBuilder = super.newDocumentBuilder();
documentBuilder.setEntityResolver(new SkipResolvingEntitiesDocumentBuilderFactory.ResolveToEmptyString());
return documentBuilder;
}
private static class ResolveToEmptyString implements EntityResolver {
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
return new InputSource(new StringReader(""));
}
}
}
There is a class DocumentBuilderFactory which already has static newInstance method:
public static DocumentBuilderFactory newInstance() {
return FactoryFinder.find(
/* The default property name according to the JAXP spec */
DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
/* The fallback implementation class name */
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
}
We could make SkipResolvingEntitiesDocumentBuilderFactory extend abstract DocumentBuilderFactory (which resides within exported package java.xml.parsers) instead of current one. Then decorate instance provided by DocumentBuilderFactory#newInstance and delegate all abstract methods calls. All tests passes.
I could prepare pull request if you would like to take a look.
I've been meaning to refactor this code in pretty much exactly the way you've suggested, so I'd be very happy to merge a PR.
Great. PR here: #1098
Merged, thanks @kr5ture
Most helpful comment
For those using the standalone JAR with Java 9 you need to add
--add-modules java.xml.bindto make it run. ie.Otherwise you will get the following