Search code examples
javaweb-servicesjax-rsswaggerswagger-2.0

Using Multiple JAX-RS Application Classes with Swagger


I'm trying to implement Swagger on a Java application that has two Application classes due to the fact that one deals with "public" web services and the other deals with "admin" web services. I'm trying to generate two separate swagger.json files, one for each Application class. However, only one of them is being generated for both urls. Here's some code:

Public Application class:

@WebServlet
@ApplicationPath("/public") 
public class PublicApplication extends Application {

    public PublicApplication() {

        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setTitle("A Fine Title");
        beanConfig.setDescription("A Fine Description.");
        beanConfig.setSchemes(new String[]{"http"});
        beanConfig.setBasePath("/api"); 
        beanConfig.setResourcePackage("com.test.rest.resource.external");
        beanConfig.setPrettyPrint(true);
        beanConfig.setScan(true);
    }
}

Private Application class:

@WebServlet
@ApplicationPath("/admin") 
public class AdminApplication extends Application {

    public AdminApplication() {

        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setTitle("Another Fine Title");
        beanConfig.setDescription("Another Fine Description.");
        beanConfig.setSchemes(new String[]{"http"});
        beanConfig.setBasePath("/apiTwo"); 
        beanConfig.setResourcePackage("com.test.rest.resource.internal");
        beanConfig.setPrettyPrint(true);
        beanConfig.setScan(true);
    }
}

Now if I hit either of these urls I get the same "public" swagger json file:

What am I doing wrong?

Thanks to all who read!


Solution

  • By default, Swagger does initialization of scanner and configuration once. If you have multiple applications or configs, you need to set a configId, scannerId & contextId to each of your application via BeanConfig and this should match with the values in your servlet config. And this settings work only with latest versions of swagger I think. I tried with swagger-1.5.13. An example is shown below.

    public class PublicApplication extends Application {
    
    public PublicApplication() {
    
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setTitle("A Fine Title");
        beanConfig.setDescription("A Fine Description.");
        beanConfig.setSchemes(new String[]{"http"});
        beanConfig.setBasePath("/api"); 
        beanConfig.setResourcePackage("com.test.rest.resource.external");
        beanConfig.setPrettyPrint(true);
    
        // Set configId,contextId & scannerId
        beanConfig.setConfigId("public");  
        beanConfig.setContextId("public");
        beanConfig.setScannerId("public");
        beanConfig.setScan(true);
    
    }
    

    Your AdminApplication class

    public AdminApplication() {
    
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setTitle("Another Fine Title");
        beanConfig.setDescription("Another Fine Description.");
        beanConfig.setSchemes(new String[]{"http"});
        beanConfig.setBasePath("/apiTwo"); 
        beanConfig.setResourcePackage("com.test.rest.resource.internal");
        beanConfig.setPrettyPrint(true);
    
        // Set configId,contextId & scannerId
        beanConfig.setConfigId("admin");  
        beanConfig.setContextId("admin");
        beanConfig.setScannerId("admin");
        beanConfig.setScan(true);
        beanConfig.setScan(true);
    }
    

    You should also specify the configId, contextId & scannerId in your servlet config as init parameter as shown below.

    <servlet>
        <servlet-name>jersey-rest-public</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.test.rest.resource.PublicApplication</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.scanner.id</param-name>
            <param-value>public</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.context.id</param-name>
            <param-value>public</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.config.id</param-name>
            <param-value>public</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>jersey-rest-admin</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.test.rest.resource.AdminApplication</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.context.id</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.scanner.id</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>swagger.config.id</param-name>
            <param-value>admin</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>