Trying to setup my first REST API (using Jersey 2 and Gradle) and add some documentation to it by using swagger. But when adding swagger dependencies and following this swagger documentation, "Using a custom Application subclass" approach, it throws me this exception, when executing the main method from Eclipse:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/ServletConfig
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.glassfish.jersey.server.model.IntrospectionModeller$2.run(IntrospectionModeller.java:253)
at java.security.AccessController.doPrivileged(Native Method)
at org.glassfish.jersey.server.model.IntrospectionModeller.getAllDeclaredMethods(IntrospectionModeller.java:247)
at org.glassfish.jersey.server.model.IntrospectionModeller.checkForNonPublicMethodIssues(IntrospectionModeller.java:172)
at org.glassfish.jersey.server.model.IntrospectionModeller.doCreateResourceBuilder(IntrospectionModeller.java:119)
at org.glassfish.jersey.server.model.IntrospectionModeller.access$000(IntrospectionModeller.java:80)
at org.glassfish.jersey.server.model.IntrospectionModeller$1.call(IntrospectionModeller.java:112)
at org.glassfish.jersey.server.model.IntrospectionModeller$1.call(IntrospectionModeller.java:109)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.model.IntrospectionModeller.createResourceBuilder(IntrospectionModeller.java:109)
at org.glassfish.jersey.server.model.Resource.from(Resource.java:797)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:465)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:184)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:350)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:347)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:347)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:299)
at org.glassfish.jersey.jdkhttp.JdkHttpHandlerContainer.<init>(JdkHttpHandlerContainer.java:98)
at org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer(JdkHttpServerFactory.java:111)
at org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer(JdkHttpServerFactory.java:93)
at example.MyApp.main(MyApp.java:21)
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletConfig
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 29 more
My code looks like this:
package example;
import static org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import com.sun.net.httpserver.HttpServer;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
public class MyApp extends ResourceConfig {
public static void main(String[] args) throws Throwable {
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9999).build();
HttpServer server = createHttpServer(baseUri, new MyApp());
System.out.println("SERVICE started at: " + baseUri);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop(0);
}));
}
public MyApp() {
packages("example");
register(SwaggerSerializers.class); // <-- swagger specific
register(ApiListingResource.class); // <-- swagger specific
register(JacksonFeature.class);
}
}
My gradle dependencies
dependencies {
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:+'
compile 'org.glassfish.jersey.containers:jersey-container-jdk-http:+'
compile 'org.glassfish.jersey.media:jersey-media-moxy:+'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:+'
compile 'io.swagger:swagger-jersey2-jaxrs:1.5.9'
}
Using jdk1.8.0_77
on Windows 7
However, if I comment out the swagger dependency and the swagger specifics in the code, then the actual REST service works as expected. How can I make swagger work without using a servlet container? The REST service can work without it
dependencies {
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:+'
compile 'org.glassfish.jersey.containers:jersey-container-jdk-http:+'
compile 'org.glassfish.jersey.media:jersey-media-moxy:+'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:+'
// compile 'io.swagger:swagger-jersey2-jaxrs:1.5.9'
}
code:
package example;
import static org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import com.sun.net.httpserver.HttpServer;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
public class MyApp extends ResourceConfig {
public static void main(String[] args) throws Throwable {
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9999).build();
HttpServer server = createHttpServer(baseUri, new MyApp());
System.out.println("SERVICE started at: " + baseUri);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop(0);
}));
}
public MyApp() {
packages("example");
// register(SwaggerSerializers.class); // <-- swagger specific
// register(ApiListingResource.class); // <-- swagger specific
register(JacksonFeature.class);
}
}
So it looks like the issue is derived from you running in a non-servlet environment. While Jersey supports it, swagger-core... not so much. This poses some issues with specific deployment, although they are less common.
The easiest solution would, obviously, be to use a servlet-container engine. Something lightweight like Jetty would work.