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

ServletContext null - Jersey + Grizzly2 Standalone - 1.5.x #1103

Closed
BGaunitz opened this issue May 26, 2015 · 8 comments
Closed

ServletContext null - Jersey + Grizzly2 Standalone - 1.5.x #1103

BGaunitz opened this issue May 26, 2015 · 8 comments
Labels
Milestone

Comments

@BGaunitz
Copy link

When using Grizzly2 in standalone mode, ServletContext is not available.

NPE at

  • com.wordnik.swagger.jaxrs.listing.ApiListingResource.scan(ApiListingResource.java:47)
  • com.wordnik.swagger.jaxrs.listing.ApiListingResource.getListingJson(ApiListingResource.java:68)

https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e2742 [3.6]

@webron webron added this to the v1.5 milestone May 28, 2015
@webron webron modified the milestones: v1.5, v1.5.1 Jun 8, 2015
@Plonk42
Copy link

Plonk42 commented Jun 11, 2015

Same for me, using:

        <dependency>
            <groupId>org.glassfish.grizzly</groupId>
            <artifactId>grizzly-http-servlet-server</artifactId>
            <version>2.3.21</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
            <version>2.18</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-jersey2-jaxrs</artifactId>
            <version>1.5.0</version>
        </dependency>
java.lang.NullPointerException
    at io.swagger.jaxrs.listing.ApiListingResource.getListingJson(ApiListingResource.java:90)

Line 90 being:

        Swagger swagger = (Swagger) context.getAttribute("swagger");

Maybe related to: http://stackoverflow.com/questions/29974887/jersey-containerrequestfilter-does-not-get-context-servletrequest

@webron
Copy link
Contributor

webron commented Jun 11, 2015

Yeah, it's related to Grizzly not using a servlet container. We need to find a work around for it.

@BGaunitz
Copy link
Author

Hi, I fixed it quick and dirty which is sufficient for me. May be it can be used for a solid solution.

Best regards,
Benjamin

package com.wordnik.swagger.jaxrs.listing;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
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.MediaType;
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;

import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.config.FilterFactory;
import com.wordnik.swagger.config.Scanner;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.core.filter.SpecFilter;
import com.wordnik.swagger.core.filter.SwaggerSpecFilter;
import com.wordnik.swagger.jaxrs.Reader;
import com.wordnik.swagger.jaxrs.config.JaxrsScanner;
import com.wordnik.swagger.models.Swagger;
import com.wordnik.swagger.util.Yaml;

@Path("/")
public class ApiListingResource {
    Logger LOGGER = LoggerFactory.getLogger(ApiListingResource.class);

    static boolean initialized = false;
    static Swagger swagger = null;

    @Context
    ServletContext context;

    protected synchronized Swagger scan(Application app, ServletConfig sc) {
        Scanner scanner = ScannerFactory.getScanner();
        LOGGER.debug("using scanner " + scanner);

        if (scanner != null) {
            SwaggerSerializers.setPrettyPrint(scanner.getPrettyPrint());
            if (context != null) {
                swagger = (Swagger) context.getAttribute("swagger");
            } else {
                swagger = new Swagger();
            }
            Set<Class<?>> classes = new HashSet<Class<?>>();
            if (scanner instanceof JaxrsScanner) {
                JaxrsScanner jaxrsScanner = (JaxrsScanner) scanner;
                classes = jaxrsScanner.classesFromContext(app, sc);
            } else {
                classes = scanner.classes();
            }
            if (classes != null) {
                Reader reader = new Reader(swagger);
                swagger = reader.read(classes);
                if (scanner instanceof SwaggerConfig)
                    swagger = ((SwaggerConfig) scanner).configure(swagger);
                else {
                    SwaggerConfig configurator = (SwaggerConfig) context
                            .getAttribute("reader");
                    if (configurator != null) {
                        LOGGER.debug("configuring swagger with " + configurator);
                        configurator.configure(swagger);
                    } else
                        LOGGER.debug("no configurator");
                }

            }
        }
        initialized = true;
        return swagger;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/swagger.json")
    @ApiOperation(value = "The swagger definition in JSON", hidden = true)
    public Response getListingJson(@Context Application app,
            @Context ServletConfig sc, @Context HttpHeaders headers,
            @Context UriInfo uriInfo) {
        if (!initialized)
            swagger = scan(app, sc);
        if (swagger != null) {
            SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
            if (filterImpl != null) {
                SpecFilter f = new SpecFilter();
                swagger = f.filter(swagger, filterImpl,
                        getQueryParams(uriInfo.getQueryParameters()),
                        getCookies(headers), 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 ServletConfig sc, @Context HttpHeaders headers,
            @Context UriInfo uriInfo) {
        // Swagger swagger = (Swagger) context.getAttribute("swagger");
        if (!initialized)
            swagger = scan(app, sc);
        try {
            if (swagger != null) {
                SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
                LOGGER.debug("using filter " + filterImpl);
                if (filterImpl != null) {
                    SpecFilter f = new SpecFilter();
                    swagger = f.filter(swagger, filterImpl,
                            getQueryParams(uriInfo.getQueryParameters()),
                            getCookies(headers), getHeaders(headers));
                }

                String yaml = Yaml.mapper().writeValueAsString(swagger);
                String[] parts = yaml.split("\n");
                StringBuilder b = new StringBuilder();
                for (String part : parts) {
                    int pos = part.indexOf("!<");
                    int endPos = part.indexOf(">");
                    b.append(part);
                    b.append("\n");
                }
                return Response.ok().entity(b.toString()).type("text/plain")
                        .build();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Response.status(404).build();
    }

    protected Map<String, List<String>> getQueryParams(
            MultivaluedMap<String, String> params) {
        Map<String, List<String>> output = new HashMap<String, List<String>>();
        if (params != null) {
            for (String key : params.keySet()) {
                List<String> values = params.get(key);
                output.put(key, values);
            }
        }
        return output;
    }

    protected Map<String, String> getCookies(HttpHeaders headers) {
        Map<String, String> output = new HashMap<String, String>();
        if (headers != null) {
            for (String key : headers.getCookies().keySet()) {
                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<String, List<String>>();
        if (headers != null) {
            for (String key : headers.getRequestHeaders().keySet()) {
                List<String> values = headers.getRequestHeaders().get(key);
                output.put(key, values);
            }
        }
        return output;
    }
}

@ralf0131
Copy link

ralf0131 commented Nov 2, 2015

I am using swagger on Jersey based RESTful service, onr service simply runs on JDK HttpServer so there is no chance to get context injected into ApiListResource. Therefore NPE will be thrown in line 90 if accessing /swagger.json:

Swagger swagger = (Swagger) context.getAttribute("swagger");

configuration:

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

I am +1 on not relying on ServletContext to initialize swagger instance.
I checked the source code in v1.5.4 and develop-2.0 branch, which has still not beeb fixed.
Is there plan about when to fix it?

@fehguy
Copy link
Contributor

fehguy commented Nov 2, 2015

I suggest you send a PR then, you can even base it on the previous comments.

@ralf0131
Copy link

ralf0131 commented Nov 3, 2015

Thanks for your comments. I will send out a PR later.

ralf0131 added a commit to ralf0131/swagger-core that referenced this issue Nov 3, 2015
…gger instance.

Instead, allow initialize swagger via ResourceConfig.
@ralf0131
Copy link

ralf0131 commented Nov 3, 2015

Hi @fehguy I've filed the PR. Could you please take some time to review it?

@fehguy fehguy modified the milestones: v1.5.5, v1.5.6 Dec 23, 2015
janusdn added a commit to janusdn/swagger-core that referenced this issue Jan 5, 2016
@fehguy fehguy modified the milestones: v1.5.6, v1.5.7 Jan 6, 2016
@fehguy fehguy modified the milestones: v1.5.7, v1.5.8 Feb 5, 2016
@frantuma
Copy link
Member

fixed in #1611

hidn added a commit to hidn/swagger-core that referenced this issue Mar 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants