I’m attempting to writing a simple HTTP API to query a server for information. I’m using spark to build the API and am bundling with gradle. I am running into the issue that, although javax.servlet-api
is bundled in my jar, the Minecraft launch loader cannot find it:
mc | java.lang.NoClassDefFoundError: javax/servlet/ServletContext
mc | at org.eclipse.jetty.server.Server.doStart(Server.java:356) ~[Server.class:?]
mc | at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) ~[AbstractLifeCycle.class:?]
mc | at spark.embeddedserver.jetty.EmbeddedJettyServer.ignite(EmbeddedJettyServer.java:149) ~[EmbeddedJettyServer.class:?]
mc | at spark.Service.lambda$init$2(Service.java:496) ~[Service.class:?]
mc | at java.lang.Thread.run(Thread.java:748) [?:1.8.0_151]
mc | Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
mc | at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101) ~[launchwrapper-1.12.jar:?]
mc | at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_151]
mc | at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_151]
mc | ... 5 more
mc | [04:54:15 ERROR] [STDERR]: Exception in thread "Thread-3" java.lang.NoClassDefFoundError: javax/servlet/ServletContext
mc | [04:54:15 ERROR] [STDERR]: at org.eclipse.jetty.server.Server.doStart(Server.java:356)
mc | [04:54:15 ERROR] [STDERR]: at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
mc | [04:54:15 ERROR] [STDERR]: at spark.embeddedserver.jetty.EmbeddedJettyServer.ignite(EmbeddedJettyServer.java:149)
mc | [04:54:15 ERROR] [STDERR]: at spark.Service.lambda$init$2(Service.java:496)
mc | [04:54:15 ERROR] [STDERR]: at java.lang.Thread.run(Thread.java:748)
mc | [04:54:15 ERROR] [STDERR]: Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
mc | [04:54:15 ERROR] [STDERR]: at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101)
mc | [04:54:15 ERROR] [STDERR]: at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
mc | [04:54:15 ERROR] [STDERR]: at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
mc | [04:54:15 ERROR] [STDERR]: ... 5 more
However, if I do the following before calling into Spark, everything loads just fine:
ClassLoader loader = HttpApiPlugin.class.getClassLoader();
try {
loader.loadClass("javax/servlet/ServletContext");
} catch (final ClassNotFoundException e) {}
Alternatively, relocating javax.servlet
to ca.brennie.vendor.javax.servlet
also results in a working plugin.
I have a minimum working example at this gist. I’d be happy for any help as to why this is happening. (I took a peek at the source for LaunchClassLoader and see that it excludes javax.
classpaths from its transformations, but shrug). Would adding my own exclusion for javax.servlet
work? Is that the correct way to handle this?