简体   繁体   English

Swagger 与 Jersey 2 抛出 java.lang.NoClassDefFoundError: javax/servlet/ServletConfig

[英]Swagger with Jersey 2 throws java.lang.NoClassDefFoundError: javax/servlet/ServletConfig

Trying to setup my first REST API (using Jersey 2 and Gradle) and add some documentation to it by using swagger.尝试设置我的第一个 REST API(使用 Jersey 2 和 Gradle)并使用 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:但是,当添加 swagger 依赖项并遵循swagger 文档“ 使用自定义应用程序子类”方法时,当从 Eclipse 执行 main 方法时,它会抛出此异常:

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我的gradle依赖

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 7Windows 7上使用jdk1.8.0_77

However, if I comment out the swagger dependency and the swagger specifics in the code, then the actual REST service works as expected.但是,如果我注释掉代码中的 swagger 依赖项和 swagger 细节,那么实际的 REST 服务会按预期工作。 How can I make swagger work without using a servlet container?如何在不使用 servlet 容器的情况下使 swagger 工作? The REST service can work without it REST 服务可以在没有它的情况下工作

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.所以看起来这个问题源于您在非 servlet 环境中运行。 While Jersey supports it, swagger-core... not so much.虽然 Jersey 支持它,但 swagger-core ... 不是那么多。 This poses some issues with specific deployment, although they are less common.这给特定部署带来了一些问题,尽管它们不太常见。

The easiest solution would, obviously, be to use a servlet-container engine.显然,最简单的解决方案是使用 servlet 容器引擎。 Something lightweight like Jetty would work.像 Jetty 这样轻量级的东西会起作用。

I know that is a litlle bit late, but I have the same issue and came up with a solution to run swagger on a non-servlet environment.我知道这有点晚了,但我遇到了同样的问题,并提出了在非 servlet 环境中运行 swagger 的解决方案。

Hope to be helpful for the next devs.希望对以后的开发者有所帮助。

pom.xml pom.xml

    <dependencies>

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

        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>

         <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
        </dependency>

        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>org.eclipse.persistence.jpa</artifactId>
            <version>2.7.1</version>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.196</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-jersey2-jaxrs</artifactId>
            <version>1.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>

    </dependencies>
...
 <properties>
        <jersey.version>2.28</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

Main.java主程序

package me.nunum.whereami;

import me.nunum.whereami.facade.ApiListingResource;
import me.nunum.whereami.framework.interceptor.PrincipalInterceptor;
import org.glassfish.grizzly.http.server.CLStaticHttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.ServerConfiguration;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;


import java.io.IOException;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Main class.
 */
public class Main {
    // Base URI the Grizzly HTTP server will listen on
    private static final String BASE_URI = "http://0.0.0.0:8080";

    private static final  Logger LOGGER = Logger.getLogger("Main");

    /**
     * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
     *
     * @return Grizzly HTTP server.
     */
    public static HttpServer startServer() {

        // create a resource config that scans for JAX-RS resources and providers
        // in me.nunum.whereami.facade package
        final ResourceConfig rc = new ResourceConfig().packages("me.nunum.whereami.facade");
        rc.setApplicationName("where");

        rc.register(PrincipalInterceptor.class);
        rc.register(ApiListingResource.class);
        rc.register(io.swagger.jaxrs.listing.SwaggerSerializers.class);

        // create and start a new instance of grizzly http server
        // exposing the Jersey application at BASE_URI
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
    }

    /**
     * Main method.
     *
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        final HttpServer server = startServer();


        ClassLoader loader = Main.class.getClassLoader();
        CLStaticHttpHandler docsHandler = new CLStaticHttpHandler(loader, "swagger-ui/dist/");
        docsHandler.setFileCacheEnabled(false);

        ServerConfiguration cfg = server.getServerConfiguration();
        cfg.addHttpHandler(docsHandler, "/docs/");

        Main.LOGGER.log(Level.INFO,"Jersey app started with WADL available at "
                + "{0} \nHit enter to stop it...", BASE_URI);
        System.in.read();
        server.shutdown();
    }
}

Refactor io.swagger.jaxrs.listing.ApiListingResource class into a new class (created in my facade package) to work on a non-servlet environment.将 io.swagger.jaxrs.listing.ApiListingResource 类重构为一个新类(在我的外观包中创建)以在非 servlet 环境中工作。

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;
    }
}

Any questions, please ask.有任何问题,请追问。

I was facing the same issue, I solved it by following the same swagger documentation , The only difference is that I provided my own ApiListingResource implementation我遇到了同样的问题,我按照相同的swagger 文档解决了它,唯一的区别是我提供了自己的 ApiListingResource 实现

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();
    }
}

Then I registered the resource along with the SwaggerSerializers provider.然后我将资源与SwaggerSerializers提供程序一起注册。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 泽西Servlet-java.lang.NoClassDefFoundError:javax / xml / bind / JAXBException - Jersey Servlet - java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException 在服务器上运行时,Eclipse - Tomcat - java.lang.NoClassDefFoundError:javax / servlet / ServletConfig - When Run As at Server,Eclipse - Tomcat - java.lang.NoClassDefFoundError: javax/servlet/ServletConfig java.lang.NoClassDefFoundError: javax/servlet/ServletContext - java.lang.NoClassDefFoundError: javax/servlet/ServletContext 在Tomcat上实现Jersey时出现“ javax.servlet.ServletException:java.lang.NoClassDefFoundError” - “javax.servlet.ServletException: java.lang.NoClassDefFoundError” when implementing Jersey on Tomcat 与JSP一起使用的速度抛出javax.servlet.ServletException:java.lang.NoClassDefFoundError: - Velocity used with JSP throws javax.servlet.ServletException: java.lang.NoClassDefFoundError: Java Spring MVC - java.lang.NoClassDefFoundError:javax / servlet / ServletContext - Java Spring MVC - java.lang.NoClassDefFoundError: javax/servlet/ServletContext SpringMVC-java.lang.NoClassDefFoundError:javax / servlet / ServletContext - SpringMVC - java.lang.NoClassDefFoundError: javax/servlet/ServletContext java.lang.NoClassDefFoundError:javax / servlet / ServletContextListener错误 - java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener error java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest - java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest 字节好友 - java.lang.NoClassDefFoundError: javax/servlet/ServletRequest - Byte Buddy - java.lang.NoClassDefFoundError: javax/servlet/ServletRequest
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM