Cant locate swagger.json on Java + Jetty + httpservlet + swagger integration

752 Views Asked by At

I recently followed this blog to integrate swagger in my embedded jetty project but after running, I'm not able to access the swagger.json file on any path combination. Accessing the servlets for the resources work with no error but I get the following errors when I try to get the swagger.json file

http://host:7000/swagger-core  ===> HTTP ERROR 405
http://host:7000/swagger-core/swagger.json ===> HTTP ERROR 404
http://host:7000/user/swagger.json ===> HTTP ProfileServlet response, not swagger.json
http://host:7000/user ===> HTTP ProfileServlet response, not swagger.json
http://host:7000/swagger.json ===> HTTP ERROR 404
http://host:7000/api/swagger.json ===> HTTP ERROR 404
http://host:7000/ ===> Static swagger sample page (Pet store), not swagger.json

Main.java

 public static void main(String[] args) throws Exception {
   Server server = initializeApi(properties);
    server.start();
    logger.info("Api resource service started");
    server.join();
 }

 private static Server initializeApi(Properties properties) {
    logger.info("Initializing user profile server...");
    new UserDao();
    Server server = new Server(Integer.parseInt(properties.getProperty(Config.JETTY_SERVICE_PORT)));
    ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
    servletContextHandler.setContextPath("/");
    server.setHandler(servletContextHandler);
    //Setup APIs

    ServletHolder apiservlet = servletContextHandler.addServlet(ProfileServlet.class, "/user/*");
    apiservlet.setInitOrder(1);
    apiservlet.setInitParameter("com.sun.jersey.config.property.packages", "com.api.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing");
    logger.info("User profile server initialized.");

        // Setup Swagger servlet
        ServletHolder swaggerServlet = servletContextHandler.addServlet(DefaultJaxrsConfig.class, "/swagger-core");
        swaggerServlet.setInitOrder(2);
        swaggerServlet.setInitParameter("api.version", "1.0.0");

        // Setup Swagger-UI static resources
        String resourceBasePath = Main.class.getResource("/webapp").toExternalForm();
        servletContextHandler.setWelcomeFiles(new String[] {"index.html"});
        servletContextHandler.setResourceBase(resourceBasePath);
        servletContextHandler.addServlet(new ServletHolder(new DefaultServlet()), "/*");

        return server;
    }
}

ProfileServlet.java

@SwaggerDefinition(


info = @Info(
           title = "User Profile Servlet",
           version = "1.0.0",
           description = "Servlet that handles basic CRUD operations to the user profile data source",
           contact = @Contact(name = "XYZ", email = "XYZ", url = "XYZ"),
           termsOfService = "XYZ",
           license = @License(name = "XYZ", url = "XYZ")
   ),
        basePath = "/",
        consumes = {"application/json"},
        produces = {"application/json"},
        schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS},
        tags = {@Tag(name = "users", description = "CRUD operations on user datatype")}
)
@Api(value = "/user", description = "performs CRUD operations on a user profile")
public class ProfileServlet extends HttpServlet {
    Logger logger = Logger.getLogger(ProfileServlet.class.getSimpleName());

    public ProfileServlet(){

    }

    @ApiOperation(httpMethod = "GET", value = "Returns a list of the user profile datatype", notes = "", response = UserDatatype.class, nickname = "getUser", tags = ("User"))
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Succssful retrieval of user profiles", response = UserDatatype.class),
            @ApiResponse(code = 500, message = "Internal server error")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "profile id", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "firstname", value = "First name of user", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lastname", value = "Last name of user", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "phone", value = "phone number of user", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "signup", value = "Sign up date of user, in dd-MM-yyyy forma", required = false, dataType = "java.sql.Date", paramType = "query")
    })
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RpcLogTemplate logTemplate = new RpcLogTemplate(req.getRemoteHost(),req.getParameter("client"), req.getParameter("clientapp"), Config.localhost, Config.SERVICE_INSTANCE, Config.SERVICE_APP, req.getParameterMap(), new Date().getTime() );
        logger.debug("Received request: GET");
        handleGet(req, resp, logTemplate);
        logTemplate.setResponseTimestamp(new Date().getTime());
        //LoggerService.INSTANCE.addLog(logTemplate);
    }

    private void handleGet(HttpServletRequest request, HttpServletResponse response, RpcLogTemplate logTemplate) throws IOException {
        Gson gson = new Gson();
        String param = null;
        param = request.getParameter("id");
        if(param!= null){
            logger.info("Query by ID received. All other params would be ignored");
            UserDatatype userDatatype = UserDao.INSTANCE.findById(param);
            if(userDatatype == null){
                response.setStatus(HttpServletResponse.SC_OK);
                logger.info("Null object returned");
                return;
            }else{
                response.setStatus(HttpServletResponse.SC_OK);
                PrintWriter printWriter = response.getWriter();
                printWriter.write(gson.toJson(userDatatype, UserDatatype.class));
                printWriter.flush();
                printWriter.close();
            }
        }else{
            Map<String, String> queryString = new HashMap<>();
            //TODO: optimize this
            param = request.getParameter("firstname");
            if(param != null)
                queryString.put("firstname", param);
            param = request.getParameter("lastname");
            if(param != null)
                queryString.put("lastname", param);
            param = request.getParameter("phone");
            if(param != null)
                queryString.put("phone", param);
            param = request.getParameter("signup");
            if(param != null)
                queryString.put("signup", param);
            UserDatatype[] userDatatypes = UserDao.INSTANCE.findByParams(queryString);
            if(userDatatypes == null){
                response.setStatus(HttpServletResponse.SC_OK);
                logger.info("Null object returned");
                return;
            }else{
                response.setStatus(HttpServletResponse.SC_OK);
                PrintWriter printWriter = response.getWriter();
                printWriter.write(gson.toJson(userDatatypes, UserDatatype[].class));
                printWriter.flush();
                printWriter.close();
            }
        }
    }

 }

Bootstrap.java

public class Bootstrap  extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
    super.init(config);

    BeanConfig beanConfig = new BeanConfig();
    beanConfig.setVersion("1.0.2");
    beanConfig.setSchemes(new String[]{"http"});
    beanConfig.setHost("localhost:7000");
    beanConfig.setBasePath("/");
    beanConfig.setResourcePackage("io.swagger.resources");
    beanConfig.setScan(true);
    beanConfig.setPrettyPrint(true);
}

}

All help appreciated.

EDIT: Quick update. After modifying the initializeAPI method to the original Servlet class in the blog(see below), I was able to get some response from the swagger-ui on http://host:7000/api/swagger.json. But I it seems like swagger wasnt able to parse my servlet annotations

http://host:7000/api/swagger.json ===> {"swagger":"2.0","info":{"version":"1.0.0","title":""}}

UPDATED CODE

private static Server initializeApi(Properties properties) {
    logger.info("Initializing user profile server...");
    new UserDao();
    Server server = new Server(Integer.parseInt(properties.getProperty(Config.JETTY_SERVICE_PORT)));
    ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
    servletContextHandler.setContextPath("/");
    server.setHandler(servletContextHandler);
    //Setup APIs
    ServletHolder apiservlet = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
    apiservlet.setInitOrder(1);
    apiservlet.setInitParameter("com.sun.jersey.config.property.packages", "com.api.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing");

    apiservlet = servletContextHandler.addServlet(ProfileServlet.class, "/user/*");
    //apiservlet.setInitOrder(1);
    apiservlet.setInitParameter("com.sun.jersey.config.property.packages", "com.api.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing");
    logger.info("User profile server initialized.");

    // Setup Swagger servlet
    ServletHolder swaggerServlet = servletContextHandler.addServlet(DefaultJaxrsConfig.class, "/swagger-core");
    swaggerServlet.setInitOrder(2);
    swaggerServlet.setInitParameter("api.version", "1.0.0");

    // Setup Swagger-UI static resources
    String resourceBasePath = Main.class.getResource("/webapp").toExternalForm();
    servletContextHandler.setWelcomeFiles(new String[] {"index.html"});
    servletContextHandler.setResourceBase(resourceBasePath);
    servletContextHandler.addServlet(new ServletHolder(new DefaultServlet()), "/*");

    return server;
}
1

There are 1 best solutions below

0
On

So thanks to the Swagger google group who figured out what was wrong with my code. Two things:

1.You have to add your package (the one that contains the servlets as an initialization parameter to the ServletContainer class. So under Main.class in the initializeApi() method, I changed it from:

//Setup APIs
ServletHolder apiservlet = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
apiservlet.setInitOrder(1);       apiservlet.setInitParameter("com.sun.jersey.config.property.packages", "com.api.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing");

to this:

//Setup APIs
ServletHolder apiservlet = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
apiservlet.setInitOrder(1);
apiservlet.setInitParameter("com.sun.jersey.config.property.packages", "com.api.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing; {path/to/package}");

In my case {path/to/package} was com.coreservice.servlets

2.Add your package name as a resource to the Swagger initialization servlet. In my project, it was the Bootstrap.java class. So my new Bootstrap.java class looks like this

public class Bootstrap  extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
    super.init(config);

    BeanConfig beanConfig = new BeanConfig();
    beanConfig.setVersion("1.0.2");
    beanConfig.setSchemes(new String[]{"http"});
    beanConfig.setHost("localhost:7000");
    beanConfig.setBasePath("/");
    beanConfig.setResourcePackage("com.coreservice.servlets");
    beanConfig.setScan(true);
    beanConfig.setPrettyPrint(true);
}