5

I have been trying to use swagger to document my jaxrs-resteasy service. I want to configure this programmatically in a embedded jetty server setting. Here are my Resource,Server and Application classes. I can access http://127.0.0.1:9091/rest/hello and verify that my rest service is working.. but when i try to access http://127.0.0.1:9091/rest/api-docs i cant get it working, but see a 404 not found instead. Can someone point me towards what i could be doing wrong while configuring Swagger.

Resource file

@Api(value = "/", description = "Index")
@Path("/")
public class Index {

    @GET
    @ApiOperation(
                value = "call Index",
                response = Response.class,
                responseContainer = "Object"
            )
    @Produces("text/html")
    public Response  index() throws URISyntaxException { 
        File f = new File(System.getProperty("user.dir")+"/index.html");
        String mt = new MimetypesFileTypeMap().getContentType(f);
        return Response.ok(f, mt).build();   
    }

    @GET
    @Path("/hello")
    @ApiOperation(
                value = "hello Get",
                response = Response.class,
                responseContainer = "Object"
            )
    public Response  helloGet() {     
        return Response.status(200).entity("HTTP GET method called").build();
    }

}

Server

public class JettyServer {

    public static void main(String[] args) throws IOException {

        Server server = new Server(9091);
        final HandlerList handlers = new HandlerList();

        ServletHolder h = new ServletHolder(new HttpServletDispatcher());
        h.setInitParameter("javax.ws.rs.Application", "com.all.MyServices");

//      h.setInitOrder(1);

        ServletContextHandler restContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        restContextHandler.setContextPath("/rest");
        restContextHandler.addServlet(h, "/*");

        handlers.addHandler(restContextHandler);

        server.setHandler(handlers);

        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Service file

public class MyServices extends Application  {

    private static Set<Index> services = new HashSet<>(); 

    public  MyServices() {     

        System.out.println( "Initializing Swagger BeanConfig" );
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setResourcePackage( Index.class.getPackage().getName() );
        beanConfig.setBasePath( "http://localhost:9091/api" );
        beanConfig.setDescription( "My RESTful services" );
        beanConfig.setTitle( "My RESTful API" );
        beanConfig.setScan( true );

        services.add(new Index());
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public  Set getSingletons() {
        return services;
    }  

    @SuppressWarnings("rawtypes")
    public  static Set getServices() {  
        return services;
    } 
}
Anusha Pachunuri
  • 1,389
  • 4
  • 18
  • 39
  • Did you ever find a solution? I'm having a similar problem, always get a 404 where I think the Swagger info should be. – medloh Aug 22 '14 at 16:49
  • Just a guess: Did you configure the basepath in your beanConfig correctly? You are trying to access http://localhost:9091/rest/api-docs but your basepath is http://localhost:9091/api. In my bootstrap class for swagger I also configured the api path (same value like basePath), in my case: ConfigFactory.config().setApiPath("myPath"); – ulrich Jan 30 '15 at 09:14

1 Answers1

0

I know this is an old question, but this may help someone, so here goes.

I'm not sure what versions of what you're using, but this matches an issue I've come across more than once with several different versions of Swagger. One thing I'm noticing is that nowhere are you registering the ApiListingResourceJSON, ApiDeclarationProvider, or ResourceListingProvider classes which come with Swagger. These classes are required in order to provide the /api-docs/ resource.

Additionally, typical configuration did not work for me. Using BeanConfig only resulted in an empty JSON Swagger element. If this happens, I solved this problem by creating a custom configuration.

public class CustomSwaggerConfig extends HttpServlet {
    public static final String PACKAGE = "com.shorecg.eureka";

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);
        ConfigFactory.setConfig(new WebXMLReader(servletConfig));
        ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
        scanner.setResourcePackage(PACKAGE);
        ScannerFactory.setScanner(scanner);
        ClassReaders.setReader(new DefaultJaxrsApiReader());
    }

    class ReflectiveJaxrsScanner implements JaxrsScanner {
        private String resourcePackage;

        public String getResourcePackage() {
            return resourcePackage;
        }

        public ReflectiveJaxrsScanner setResourcePackage(String resourcePackage) {
            this.resourcePackage = resourcePackage;
            return this;
        }

        @Override
        public List<Class<?>> classes() {
            Reflections reflections = new Reflections(resourcePackage);
            Set<Class<?>> clsses = reflections.getTypesAnnotatedWith(Api.class);
            return JavaConversions.asScalaSet(clsses).toList();
        }

        @Override
        public List<Class<?>> classesFromContext(Application aplctn, ServletConfig sc) {
            return classes();
        }

    }
}

This isn't a perfect solution. For example, if you have resources which aren't registered, they'll still show up in Swagger if you use this custom swagger config. It did, however, get me to the point that swagger actually worked. Hope this helps.

ironhardchaw
  • 149
  • 3
  • 10