Swagger-core: java.lang.NoClassDefFoundError:์„œ๋ธ”๋ฆฟ์ด ์—†๋Š” Jersey 2๊ฐ€ ์žˆ๋Š” javax/servlet/ServletConfig

์— ๋งŒ๋“  2016๋…„ 09์›” 06์ผ  ยท  5์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: swagger-api/swagger-core

์—ฌ๊ธฐ ์— ์„ค๋ช…๋œ ์ž์Šต์„œ๋ฅผ ๋”ฐ๋ผ "์‚ฌ์šฉ์ž ์ง€์ • ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ํ•˜์œ„ ํด๋ž˜์Šค ์‚ฌ์šฉ" ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ Jersey 2.23.2๋กœ Swagger๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

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

์ด StackOverflow ํ† ๋ก ๋„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค .

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค์Œ ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

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

๋ชจ๋“  5 ๋Œ“๊ธ€

์ด๊ฒƒ์€ stackoverflow์—์„œ ๋‹ต๋ณ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ธ”๋ฆฟ ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋งŒํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @fehguy

๋‚˜๋Š” ๊ฐ™์€ ๋ฌธ์ œ์— ๋ถ€๋”ช์ณค๋‹ค. GrizzlyServer๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ „ํ™˜์„ ํ”ผํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Grizzly์—์„œ ์ „ํ™˜ํ•˜์ง€ ์•Š๊ณ  swagger๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด pom.xml์— ์–ด๋–ค ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๋‹ค์Œ ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

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

์•ˆ๋…•ํ•˜์„ธ์š”,

3๋…„ ํ›„ ์šฐ๋ฆฌ๋Š” ๋™์ผํ•œ ๋ฒ„๊ทธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์„œ๋ธ”๋ฆฟ ์ด์ƒํ•œ ๊ตฌ์„ฑ ์—†์ด ์ด๋ฏธ grizzly HTTP ์„œ๋ฒ„์™€ ๊ฐ™์€ Java HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์™œ ์„œ๋ธ”๋ฆฟ ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ์ข…์†์„ฑ swagger-jersey2-jaxrs ์—์„œ ApiListingResource ํด๋ž˜์Šค๊ฐ€ ์„œ๋ธ”๋ฆฟ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ฃผ์ž…๋˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ 

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")
<strong i="10">@Singleton</strong>
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() {
            <strong i="11">@Override</strong>
            public Set<Class<?>> classes() {
                return app.getClasses();
            }

            <strong i="12">@Override</strong>
            public boolean getPrettyPrint() {
                return false;
            }

            <strong i="13">@Override</strong>
            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() {
                <strong i="14">@Override</strong>
                public boolean isScanAllResources() {
                    return false;
                }

                <strong i="15">@Override</strong>
                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() {
                    <strong i="16">@Override</strong>
                    public Swagger configure(Swagger swagger) {
                        return swagger;
                    }

                    <strong i="17">@Override</strong>
                    public String getFilterClass() {
                        return "";
                    }
                };
                this.LOGGER.debug("configuring swagger with " + configurator);
                configurator.configure(swagger);
            }

        }

        initialized = true;
        return swagger;
    }

    <strong i="18">@GET</strong>
    @Produces({"application/json"})
    @Path("/swagger.json")
    @ApiOperation(
            value = "The swagger definition in JSON",
            hidden = true
    )
    public Response getListingJson(<strong i="19">@Context</strong> Application app, <strong i="20">@Context</strong> HttpHeaders headers, <strong i="21">@Context</strong> 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();
        }
    }

    <strong i="22">@GET</strong>
    @Produces({"application/yaml"})
    @Path("/swagger.yaml")
    @ApiOperation(
            value = "The swagger definition in YAML",
            hidden = true
    )
    public Response getListingYaml(<strong i="23">@Context</strong> Application app, <strong i="24">@Context</strong> HttpHeaders headers, <strong i="25">@Context</strong> 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;
    }
}

Maven ์•„์นด์ด๋ธŒ์—์„œ Jersey ์‹œ์ž‘ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•˜๋ฉด "jersey-container-grizzly2-http" ์ข…์†์„ฑ์œผ๋กœ ๋๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ์‚ฌ๋žŒ๋“ค์€ ์ปจํ…Œ์ด๋„ˆ/์„œ๋ธ”๋ฆฟ์— ๋Œ€ํ•œ ํ˜ผ๋ž€์„ ์—ผ๋‘์— ๋‘์ง€ ์•Š๊ณ  swagger ์„ค์ •์„ ์™„๋ฃŒํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ง์„ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‚˜์˜ ํ•ด๊ฒฐ์ฑ…์ž…๋‹ˆ๋‹ค.

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")
<strong i="6">@ApplicationScoped</strong>
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();
    }

    <strong i="7">@GET</strong>
    @Produces({"application/json"})
    @Path("/swagger.json")
    public Response getListingJson() {
        return Response.ok(this.swagger).build();
    }

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

io.swagger.jaxrs.listing ์ œ๊ณตํ•œ ๋ฆฌ์†Œ์Šค ๋Œ€์‹  ์ด ๋ฆฌ์†Œ์Šค๋ฅผ ๋“ฑ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋จธ์ง€ ๊ตฌ์„ฑ์€ ๋ฌธ์„œ์— ์„ค๋ช…๋œ ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰