Skip to content
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

java.lang.NoClassDefFoundError: javax/servlet/ServletConfig with Jersey 2 without Servlet #1913

Closed
Tpt opened this issue Sep 6, 2016 · 5 comments

Comments

@Tpt
Copy link

Tpt commented Sep 6, 2016

When following the tutorial described [here](https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5#using-a-custom-application-subclass here) to setup Swagger with Jersey 2.23.2 with the "Using a custom Application subclass" approach. The following error is thrown:

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

Se also this StackOverflow discussion: http://stackoverflow.com/questions/38891661/swagger-with-jersey-2-throws-java-lang-noclassdeffounderror-javax-servlet-servl

@fehguy
Copy link
Contributor

fehguy commented Dec 24, 2016

This was answered on stackoverflow. Just add the servlet dependency

@fehguy fehguy closed this as completed Dec 24, 2016
@ajayyadava
Copy link

Hi @fehguy

I ran into the same problem. I am using GrizzlyServer. I would like to avoid switching the server. Is it possible to use swagger without switching away from Grizzly? If yes, then what dependency should I add to my pom.xml?

@ajayyadava
Copy link

Adding the following dependency worked for me.

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-servlet</artifactId>
    </dependency>

@NunuM
Copy link

NunuM commented May 17, 2019

Hi,

After 3 years we have the same bug, why do I need to change to a servlet-based project while I have an already running Java HTTP server like a grizzly HTTP server, without all servlet weird configurations?

This occurs because in the dependency swagger-jersey2-jaxrs the class ApiListingResource wants the servlet instance to be injected. Why not provide a different implementation (this is one that runs on a non-servlet server, is not already parameterized, is just an example that works):

package me.nunum.whereami.facade;

import io.swagger.annotations.ApiOperation;
import io.swagger.config.FilterFactory;
import io.swagger.config.Scanner;
import io.swagger.config.SwaggerConfig;
import io.swagger.core.filter.SpecFilter;
import io.swagger.core.filter.SwaggerSpecFilter;
import io.swagger.jaxrs.Reader;
import io.swagger.jaxrs.config.JaxrsScanner;
import io.swagger.jaxrs.config.ReaderConfig;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;

import java.util.*;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Path("/api/doc")
@Singleton
public class ApiListingResource {
    static boolean initialized = false;
    Logger LOGGER = LoggerFactory.getLogger(io.swagger.jaxrs.listing.ApiListingResource.class);


    public Swagger mSwaggerConfig;

    public ApiListingResource() {
        mSwaggerConfig = new Swagger();
        mSwaggerConfig.setBasePath("/");
    }

    public ApiListingResource(Swagger swagger){
        this.mSwaggerConfig = swagger;
    }

    protected synchronized Swagger scan(Application app) {
        Swagger swagger = null;
        Scanner scanner = new Scanner() {
            @Override
            public Set<Class<?>> classes() {
                return app.getClasses();
            }

            @Override
            public boolean getPrettyPrint() {
                return false;
            }

            @Override
            public void setPrettyPrint(boolean b) {

            }
        };
        this.LOGGER.debug("using scanner " + scanner);
        SwaggerSerializers.setPrettyPrint(scanner.getPrettyPrint());
        swagger = this.mSwaggerConfig;
        new HashSet();
        Set classes;

        if (scanner instanceof JaxrsScanner) {
            classes = null;
        } else {
            classes = scanner.classes();
        }

        if (classes != null) {
            Reader reader = new Reader(swagger, new ReaderConfig() {
                @Override
                public boolean isScanAllResources() {
                    return false;
                }

                @Override
                public Collection<String> getIgnoredRoutes() {
                    return new ArrayList<>();
                }
            });
            swagger = reader.read(classes);
            if (scanner instanceof SwaggerConfig) {
                swagger = ((SwaggerConfig)scanner).configure(swagger);
            } else {
                SwaggerConfig configurator = new SwaggerConfig() {
                    @Override
                    public Swagger configure(Swagger swagger) {
                        return swagger;
                    }

                    @Override
                    public String getFilterClass() {
                        return "";
                    }
                };
                this.LOGGER.debug("configuring swagger with " + configurator);
                configurator.configure(swagger);
            }

        }

        initialized = true;
        return swagger;
    }

    @GET
    @Produces({"application/json"})
    @Path("/swagger.json")
    @ApiOperation(
            value = "The swagger definition in JSON",
            hidden = true
    )
    public Response getListingJson(@Context Application app, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
        Swagger swagger = this.mSwaggerConfig;
        if (!initialized) {
            this.mSwaggerConfig = this.scan(app);
        }

        if (swagger != null) {
            SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
            if (filterImpl != null) {
                SpecFilter f = new SpecFilter();
                swagger = f.filter(swagger, filterImpl, this.getQueryParams(uriInfo.getQueryParameters()), this.getCookies(headers), this.getHeaders(headers));
            }

            return Response.ok().entity(swagger).build();
        } else {
            return Response.status(404).build();
        }
    }

    @GET
    @Produces({"application/yaml"})
    @Path("/swagger.yaml")
    @ApiOperation(
            value = "The swagger definition in YAML",
            hidden = true
    )
    public Response getListingYaml(@Context Application app, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
        Swagger swagger = this.mSwaggerConfig;
        if (!initialized) {
            this.mSwaggerConfig = this.scan(app);
        }

        try {
            if (swagger != null) {
                SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
                this.LOGGER.debug("using filter " + filterImpl);
                if (filterImpl != null) {
                    SpecFilter f = new SpecFilter();
                    swagger = f.filter(swagger, filterImpl, this.getQueryParams(uriInfo.getQueryParameters()), this.getCookies(headers), this.getHeaders(headers));
                }

                String yaml = Yaml.mapper().writeValueAsString(swagger);
                String[] parts = yaml.split("\n");
                StringBuilder b = new StringBuilder();
                String[] arr$ = parts;
                int len$ = parts.length;

                for(int i$ = 0; i$ < len$; ++i$) {
                    String part = arr$[i$];
                    int pos = part.indexOf("!<");
                    int endPos = part.indexOf(">");
                    b.append(part);
                    b.append("\n");
                }

                return Response.ok().entity(b.toString()).type("application/yaml").build();
            }
        } catch (Exception var16) {
            var16.printStackTrace();
        }

        return Response.status(404).build();
    }

    protected Map<String, List<String>> getQueryParams(MultivaluedMap<String, String> params) {
        Map<String, List<String>> output = new HashMap();
        if (params != null) {
            Iterator i$ = params.keySet().iterator();

            while(i$.hasNext()) {
                String key = (String)i$.next();
                List<String> values = (List)params.get(key);
                output.put(key, values);
            }
        }

        return output;
    }

    protected Map<String, String> getCookies(HttpHeaders headers) {
        Map<String, String> output = new HashMap();
        if (headers != null) {
            Iterator i$ = headers.getCookies().keySet().iterator();

            while(i$.hasNext()) {
                String key = (String)i$.next();
                Cookie cookie = (Cookie)headers.getCookies().get(key);
                output.put(key, cookie.getValue());
            }
        }

        return output;
    }

    protected Map<String, List<String>> getHeaders(HttpHeaders headers) {
        Map<String, List<String>> output = new HashMap();
        if (headers != null) {
            Iterator i$ = headers.getRequestHeaders().keySet().iterator();

            while(i$.hasNext()) {
                String key = (String)i$.next();
                List<String> values = (List)headers.getRequestHeaders().get(key);
                output.put(key, values);
            }
        }

        return output;
    }
}

I am saying this because if you pick Jersey startup project from Maven archive, you end with "jersey-container-grizzly2-http" dependency, newer people will not have in mind the confusion around containers/servlets and will not conclude swagger set up.

@salah3x
Copy link

salah3x commented Apr 2, 2020

This is my solution to this issue:

package com.example;

import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.ApiOperation;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

@Path("/docs")
@ApplicationScoped
public class ApiListingResource {

    private final Swagger swagger;

    public ApiListingResource() {
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setTitle("MY REST API");
        beanConfig.setVersion("v1");
        beanConfig.setBasePath("/api");
        beanConfig.setResourcePackage("com.example.resource");
        beanConfig.setScan(true);
        this.swagger = beanConfig.getSwagger();
    }

    @GET
    @Produces({"application/json"})
    @Path("/swagger.json")
    public Response getListingJson() {
        return Response.ok(this.swagger).build();
    }

    @GET
    @Produces({"application/yaml"})
    @Path("/swagger.yaml")
    public Response getListingYaml() throws JsonProcessingException {
        String yaml = Yaml.mapper().writeValueAsString(this.swagger);
        return Response.ok(yaml).build();
    }
}

I registred this resource instead of the one provided by io.swagger.jaxrs.listing
The rest of the configuration is the same as described in the docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants