Swagger documentation with JAX-RS Jersey 2 and Grizzly

假如想象 提交于 2019-11-27 16:17:19
Paul Samsotha

It's times like this (when there is no real explanation for the problem) that I throw in an ExceptionMapper<Throwable>. Often with server related exceptions, there are no mappers to handle the exception, so it bubbles up to the container and we get a useless 500 status code and maybe some useless message from the server (as you are seeing from Grizzly).

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

public class DebugMapper implements ExceptionMapper<Throwable>  {

    @Override
    public Response toResponse(Throwable exception) {
        exception.printStackTrace();
        if (exception instanceof WebApplicationException) {
            return ((WebApplicationException)exception).getResponse();
        }
        return Response.serverError().entity(exception.getMessage()).build();
    }  
}

Then just register with the application

public ApplicationConfig(final AddressBook addressBook) {
    ...
    register(DebugMapper.class);
}

When you run the application again and try to hit the endpoint, you will now see a stacktrace with the cause of the exception

java.lang.NullPointerException
  at io.swagger.jaxrs.listing.ApiListingResource.getListingJson(ApiListingResource.java:90)

If you look at the source code for ApiListingResource.java:90, you will see

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

The only thing here that could cause the NPE is the context, which scrolling up will show you it's the ServletContext. Now here's the reason it's null. In order for there to even be a ServletContext, the app needs to be run in a Servlet environment. But look at your set up:

HttpServer server = GrizzlyHttpServerFactory
        .createHttpServer(uri, new ApplicationConfig(ab));

This does not create a Servlet container. It only creates an HTTP server. You have the dependency required to create the Servlet container (jersey-container-grizzly2-servlet), but you just need to make use of it. So instead of the previous configuration, you should do

ServletContainer sc = new ServletContainer(new ApplicationConfig(ab));
HttpServer server = GrizzlyWebContainerFactory.create(uri, sc, null, null); 
// you will need to catch IOException or add a throws clause

See the API for GrizzlyWebContainerFactory for other configuration options.

Now if you run it and hit the endpoint again, you will see the Swagger JSON. Do note that the response from the endpoint is only the JSON, it is not the documentation interface. For that you need to use the Swagger UI that can interpret the JSON.

Thanks for the MCVE project BTW.

Swagger fixed this issue in 1.5.7. It was Issue 1103, but the fix was rolled in last February. peeskillet's answer will still work, but so will OP's now.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!