Configuring swagger on embedded Tomcat without web.xml

1,073 views
Skip to first unread message

Lokuma

unread,
Feb 26, 2015, 12:51:37 PM2/26/15
to swagger-sw...@googlegroups.com
Hello everybody,

I am trying to configure Swagger in an embedded application with REST API using jersey without web.xml.
I am expecting swagger to scrape the resources and return an appropriate JSON. Instead I am getting the following response in the browser:


{"apiVersion":"0.0","swaggerVersion":"1.2"}

I tried using BeanConfig for the swagger initialization without success. Obviously I am doing something wrong. If anybody worked on similar configuration, please any hint would be appreciated.
Thanks a lot.
Lokuma

I am using the following versions:
jax-rs-jersey v.2.6
swagger v1.3.12
embedded tomcat 7.0.47

These are the main components in configuring the swagger:

public class TomcatEmbeddedRunner {
  private static final AcLogger AC_LOGGER = new AcLogger(TomcatEmbeddedRunner.class.getName());
  
  private static final String ROOT_PATH = "/rest";
  public static final String REST_VERSION = "2";
  private static final String REST_VERSION_PATH = "/v2" + REST_VERSION;
  private static final int DEFAULT_PORT = 4010;

  /**
   * Start the REST server.
   * @throws LifecycleException
   */
  public void startServer() throws LifecycleException {
    Tomcat tomcat = new Tomcat();
    tomcat.setPort(DEFAULT_PORT);
    File base = new File(System.getProperty("java.io.tmpdir"));
    Context rootCtx = tomcat.addContext(ROOT_PATH, base.getAbsolutePath());

    try {
      Tomcat.addServlet(rootCtx, "jersey-container-servlet", resourceConfig());
      rootCtx.addServletMapping(REST_VERSION_PATH + "/*", "jersey-container-servlet");
      
    } catch (Exception e) {
      AC_LOGGER.logN(Level.SEVERE, e, "Unable to add servlet mapping for REST");
    } 
    //specify the swagger configuration class   
    try {
        
    Tomcat.addServlet(rootCtx, "SwaggerJaxrsConfig", aplicationConfig());
        rootCtx.addServletMapping(REST_VERSION_PATH +"/swagger/*", "SwaggerJaxrsConfig");
        
      } catch (Exception e) {
        AC_LOGGER.logN(Level.SEVERE, e, "Unable to add swagger mapping for REST");
      } 
    try {
      tomcat.start();
    } catch (Exception e) {
      AC_LOGGER.logN(Level.SEVERE, e, "Unable to start Tomcat for REST");
    }
    AC_LOGGER.configN("Java REST v2 server is ready on port " + DEFAULT_PORT
        + "\n  REST"
        + " v2 base URL = " + ROOT_PATH + REST_VERSION_PATH);
  }
  private ServletContainer resourceConfig() {
    return new ServletContainer(new ResourceConfig(new ResourceLoader().getClasses()));
  }
   private ServletContainer aplicationConfig() {
   return new ServletContainer(new ResourceConfig(new ApplicationConfig().getClasses()));
 }  
}

The applicationConfig() loads the resources:
@javax.ws.rs.ApplicationPath("api-docs")
public class ApplicationConfig extends Application {
 private static final String RESOURCES_PKG = "com.services.api.rest.resources";
    @Override
    public Set<Class<?>> getClasses() {
    final Set<Class<?>> resources = new HashSet<Class<?>>();
        
        resources.add(com.wordnik.swagger.jaxrs.listing.ApiListingResource.class);
        resources.add(com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider.class);
        resources.add(com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON.class);
        resources.add(com.wordnik.swagger.jaxrs.listing.ResourceListingProvider.class);
        addRestResourceClasses(resources);
               
        return resources;
    }

    /**
     * Do not modify addRestResourceClasses() method.
     * It is automatically populated with
     * all resources defined in the project.
     * If required, comment out calling this method in getClasses().
     */
    private void addRestResourceClasses(Set<Class<?>> resources) {
        resources.add(com.services.api.rest.resources.LoginResource.class);
    }
 
The swagger servlet initialization. When I debugged the application I noticed the SwaggerJaxrsConfig servlet  initialization is never called. Maybe that is why the scanner is not properly initialized.:

@WebServlet(name = "SwaggerJaxrsConfig", loadOnStartup = 2)
public class SwaggerJaxrsConfig extends HttpServlet {

@Override
    public void init(ServletConfig servletConfig) {
        try {
            super.init(servletConfig);
            SwaggerConfig swaggerConfig = new SwaggerConfig();
            ConfigFactory.setConfig(swaggerConfig);
            swaggerConfig.setBasePath("http://localhost:4010/rest/v2/swagger");
            swaggerConfig.setApiVersion("2.0.0");
            ScannerFactory.setScanner(new DefaultJaxrsScanner());
            ClassReaders.setReader(new DefaultJaxrsApiReader());
            
        } catch (ServletException e) {
            System.out.println(e.getMessage());
        }
    }

tony tam

unread,
Feb 26, 2015, 1:24:38 PM2/26/15
to swagger-sw...@googlegroups.com
If you're not working with a web.xml, you have to ensure your scanners are initialized.  So I suggest using the BeanConfig.  Be sure to call "setScan(true)" at the end of configuration.  If that doesn't work, please post how you're using it here.

Lokuma

unread,
Feb 26, 2015, 1:38:03 PM2/26/15
to swagger-sw...@googlegroups.com
Thanks for the quick reply Tony!

I have added the class SwaggerInitializer below, as other posts suggested. I did not add the listener to the servlet.
Is @WebListener enough?
I have put some breakpoints in this code but I never stopped there.
Also I kept the SwaggerJaxrsConfig servlet. Should I switch to JerseyJaxrsConfig default servlet?


@WebListener
public class SwaggerInitializer implements ServletContextListener {

    private static final String RESOURCES_PKG = "com.services.api.rest.resources";

    public void contextInitialized1(ServletContextEvent servletContextEvent) {
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("2.0.0");
        beanConfig.setResourcePackage(RESOURCES_PKG); // replace with your packages
        beanConfig.setBasePath("http://localhost:4010/rest/v2/swagger");
        beanConfig.setDescription("REST API");
        beanConfig.setTitle("REST API");
        beanConfig.setScan(true);
    }

    public void contextDestroyed1(ServletContextEvent servletContextEvent) {
    }

@Override
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}

@Override
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub

Ron Ratovsky

unread,
Feb 26, 2015, 1:47:14 PM2/26/15
to swagger-sw...@googlegroups.com
A @WebListener should be enough.

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
-----------------------------------------
http://swagger.io
https://twitter.com/SwaggerApi
-----------------------------------------

Lokuma

unread,
Feb 26, 2015, 1:54:36 PM2/26/15
to swagger-sw...@googlegroups.com
Ok. I still get the same response:

Ron Ratovsky

unread,
Feb 26, 2015, 1:57:00 PM2/26/15
to swagger-sw...@googlegroups.com
Looks like it's not being picked up by Tomcat. You may need to configure Tomcat explicitly to load it.

On Thu, Feb 26, 2015 at 8:54 PM, Lokuma <iana...@gmail.com> wrote:
Ok. I still get the same response:
{"apiVersion":"0.0","swaggerVersion":"1.2"} 
 

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Lokuma

unread,
Feb 26, 2015, 4:04:03 PM2/26/15
to swagger-sw...@googlegroups.com
I have explicitly added the listener:
Tomcat.addServlet(rootCtx, "JerseyJaxrsConfig", aplicationConfig());
        rootCtx.addServletMapping(REST_VERSION_PATH +"/swagger/*", "JerseyJaxrsConfig");
        rootCtx.addApplicationListener(new ApplicationListener("com.services.api.rest.SwaggerInitializer",false));


Still the same result.
{"apiVersion":"0.0","swaggerVersion":"1.2"} 


On Thursday, February 26, 2015 at 10:57:00 AM UTC-8, Ron wrote:
Looks like it's not being picked up by Tomcat. You may need to configure Tomcat explicitly to load it.
On Thu, Feb 26, 2015 at 8:54 PM, Lokuma <iana...@gmail.com> wrote:
Ok. I still get the same response:
{"apiVersion":"0.0","swaggerVersion":"1.2"} 
 

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Ron Ratovsky

unread,
Feb 27, 2015, 1:45:21 PM2/27/15
to swagger-sw...@googlegroups.com
If the code of the @WebListener you posted is the one you used, it won't work.
Please note that the code you have there is in contextInitialized1(...) instead of contextInitialized(...).

To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Lokuma

unread,
Feb 27, 2015, 2:41:40 PM2/27/15
to swagger-sw...@googlegroups.com

After cleaning the code a little bit I was able to to get the expected JSON from the swagger.

The key was explicitly registering the application listener with Tomcat.
Thanks for your pointers.

Lokuma

unread,
Feb 27, 2015, 2:45:51 PM2/27/15
to swagger-sw...@googlegroups.com
Ron,
I just saw your message. Yes, I got rid of contextInitialized1. Also I was having a dependency to a jersey 1 jar, that i somehow overlooked.

Ron Ratovsky

unread,
Feb 27, 2015, 2:48:23 PM2/27/15
to swagger-sw...@googlegroups.com
Glad it worked out, thanks for keeping us updated.

To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages