Skip to content

Swagger 2.X Integration and Configuration

Francesco Tumanischvili edited this page Sep 26, 2023 · 15 revisions

NOTE: Swagger Core 2.X produces OpenApi 3.0 definition files. If you're looking for swagger 1.5.X and OpenApi 2.0, please refer to 1.5.X JAX-RS Setup

This page details integration and configuration of Swagger, please also check out Quick start and annotations


NOTE: Since version 2.2.0 Swagger Core supports OpenAPI 3.1; see this page for details


NOTE: Jakarta namespace support (since version 2.1.7)

Since version 2.1.7 Swagger Core supports also Jakarta namespace, with a parallel set of artifacts with -jakarta suffix, providing the same functionality as the "standard" javax namespace ones.

While behaviour described in this documentation is the same for both namespaces, artifact IDs, JEE / Jakarta EE versions and Jackson versions mentioned refer to javax namespace.

If you are using jakarta namespace:

  • when you read artifact IDs in the form: swagger-* (e.g. swagger-core), replace them with swagger-*-jakarta (e.g. swagger-core-jakarta)
  • when you read javax.* in package names, replace that with jakarta (e.g jakarta.ws.rs.GET)
  • when JEE / Jakarta EE dependencies are provided in examples, replace their version with Jakarta EE 9 versions.
  • When Jackson dependencies are provided in examples, add the jakarta classifier for artifacts supporting it. See Jackson release notes Jakarta namespace Swagger Core artifacts need Jackson 2.12+

Dependencies

Swagger uses maven for build and deployment and its artifacts are available at Maven Central. You can use the maven dependencies with any dependency management system that supports maven dependencies such as Maven, Ivy and Gradle. If you're not using Maven, please refer to Not using Maven

In most scenarios, a single dependency to swagger-jaxrs2 added to the project POM (optionally together with the provided configuration) is all that is needed to integrate swagger-core into a JAX-RS application.

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-jaxrs2</artifactId>
      <version>2.0.0</version>
    </dependency>
  </dependencies>

As detailed in Quick start a zero config integration can be obtained by adding one more dependency to swagger-jaxrs2-servlet-initializer (or swagger-jaxrs2-servlet-initializer-v2, see below) (a ServletContainerInitializer implementation which resolves JAX-RS resources from servlet classes):

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-jaxrs2</artifactId>
      <version>2.1.1</version>
    </dependency>
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
      <version>2.1.1</version>
    </dependency>
  </dependencies>

or since version 2.1.2 better (see #3412):

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-jaxrs2</artifactId>
      <version>2.1.2</version>
    </dependency>
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-jaxrs2-servlet-initializer-v2</artifactId>
      <version>2.1.2</version>
    </dependency>
  </dependencies>

There are however scenarios in which the dependency to swagger-jaxrs2-servlet-initializer (or swagger-jaxrs2-servlet-initializer-v2, see above) is not necessary, as Swagger integration mechanism is capable of identifying resources from the ones configured by the JAX-RS environment, even without swagger specific settings; these include:

  • Resources defined via JAX-RS Application.getClasses() - see Jersey and RESTEasy samples.
  • Resources defined e.g. in resourcePackages or resourceClasses init parameters of JAX-RS framework servlet - see Jersey sample

For example, adding io.swagger.v3.jaxrs2.integration.resources to Jersey 2 container servlet/filter jersey.config.server.provider.packages init param is by itself sufficient to integrate Swagger and have it scan and expose resolved spec. (in servlet-context-path/openapi.json or servlet-context-path/openapi.yaml).

Refer to the samples for examples of dependencies usage in different environment and configuration scenarios.


In scenarios where e.g. you only care about the annotations, or the OpenAPI specification Java implementation (models) or one of the other module, you can just add the specific dependency you need, like

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-annotations</artifactId>
      <version>2.0.0</version>
    </dependency>
  </dependencies>

or

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-models</artifactId>
      <version>2.0.0</version>
    </dependency>
  </dependencies>

or

  <dependencies>
    ...
    <dependency>
      <groupId>io.swagger.core.v3</groupId>
      <artifactId>swagger-core</artifactId>
      <version>2.0.0</version>
    </dependency>
  </dependencies>

Exposing OpenAPI definition

Swagger provides two out-of-the-box mechanisms to have the resolved OpenAPI definition exposed as an API:

OpenApiResource

OpenApiResource and AcceptHeaderOpenApiResource are JAX-RS resources exposing the definition via :

  • /openapi.json (OpenApiResource)
  • /openapi.yaml (OpenApiResource)
  • /openapi with Accept header application/json or application/yaml (AcceptHeaderOpenApiResource)

Depending on the JAX-RS environment in use and its setup, in some cases just adding the swagger-jaxrs2 dependency is sufficient to have the above resources registered by the JAX-RS environment, and the enpoints activated, e.g. this would be true in a Jersey environment with no resource packages or classes configured. Check out Jersey and RESTEasy samples for this scenario.

In other cases you might need to register OpenApiResource, AcceptHeaderOpenApiResource or both in your JAX-RS environment, for example:

@ApplicationPath("/sample")
public class MyApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        return Stream.of(PetResource.class, OpenApiResource.class, AcceptHeaderOpenApiResource.class).collect(Collectors.toSet());
    }
}

Try it out by cloning/downloading the Jersey or RESTEasy sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/sample/openapi.yaml (and .json).

or

@ApplicationPath("/sample")
public class MyApplication extends ResourceConfig {

    public MyApplication() {
        OpenApiResource openApiResource = new OpenApiResource();
        register(openApiResource);
    }
}

Try it out by cloning/downloading the Jersey sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/sample/openapi.yaml (and .json).

or

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
        io.swagger.v3.jaxrs2.integration.resources,io.swagger.sample.resource
      </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>jersey</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>

</web-app>

Try it out by cloning/downloading the Jersey sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/sample/openapi.yaml (and .json).

OpenApiServlet

If you want to have the definition exposed independently of your APIs, you can use provided OpenApiServlet configuring e.g. in web descriptor:

<servlet>
    <servlet-name>OpenApi</servlet-name>
    <servlet-class>io.swagger.v3.jaxrs2.integration.OpenApiServlet</servlet-class>

    <init-param>
      <param-name>openApi.configuration.resourcePackages</param-name>
      <param-value>io.swagger.sample.resource</param-value>
    </init-param>

  <!-- alternatively include a file openapi.json or openapi.yaml / openapi-configuration.json or openapi-configuration.yaml in classpath -->

  <!-- alternatively include a configuration file in the location specified below -->
  <!--
    <init-param>
      <param-name>openApi.configuration.location</param-name>
      <param-value>/openapi-configuration.json</param-value>
    </init-param>
  -->
  </servlet>

  <servlet-mapping>
    <servlet-name>OpenApi</servlet-name>
    <url-pattern>/openapi/*</url-pattern>
  </servlet-mapping>

Try it out by cloning/downloading the Jersey sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/openapi/openapi.yaml (and .json).

Alternatively you can "custom expose" it either extending BaseOpenApiResource or resolving the definition spec and then exposing it via whatever mechanism suiting your needs.

Extend BaseOpenApiResource

You can define your own endpoints and/or execute additional logic, by extending BaseOpenApiResource which provides the logic to load/init swagger context and resolve the OpenAPI definition, e.g. like:

@Path("/mycustompath")
public class CustomOpenApiResource extends BaseOpenApiResource {
    @Context
    ServletConfig config;

    @Context
    Application app;

    @GET
    @Produces({MediaType.APPLICATION_JSON})
    @Operation(hidden = true)
    public Response getOpenApi(@Context HttpHeaders headers,
                               @Context UriInfo uriInfo) throws Exception {

        return super.getOpenApi(headers, config, app, uriInfo, "json");
    }
}

Notice the @Operation(hidden = true) annotation, keeping the resource from being included in the resulting definition.


Configuration

In swagger-core context, Configuration is a set of properties which affects the OpenAPI definition outcome by declaring e.g. the packages to be considered while resolving the definition (resourcePackages), if want a pretty printed output (prettyPrint), the definition cache TTL (cacheTTL), an OpenAPI definition directly in OpenAPI format, which will be merged with the resolved definition (openAPI).

Please check out below for the complete set of available properties.

Note that the configuration can also be absent, see Quick start for such a scenario.

There are several ways to provide a configuration, detailed below. probably the easiest and least intrusive way is via a configuration file in YAML or JSON format, however also servlet init parameters, programmatic configuration, service loader options are available.

Configuration file

Probably the simplest and more powerful mechanism to hook and configure Swagger with your application is using a configuration file in YAML or JSON format.

You can either rely on swagger scanning known locations, or provide the location of such file as an init param or programmatically.

A typical example of a configuration file is:

resourcePackages:
- io.swagger.sample.resource
prettyPrint: true
cacheTTL: 0
openAPI:
  info:
    version: '1.0'
    title: Swagger Pet Sample App Config File
    description: 'This is a sample server Petstore server.  You can find out more
      about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
      #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
      `special-key` to test the authorization filters.'
    termsOfService: http://swagger.io/terms/
    contact:
      email: [email protected]
    license:
      name: Apache 2.0
      url: http://www.apache.org/licenses/LICENSE-2.0.html

In the example above, we are providing the packages to be considered while resolving the definition (resourcePackages), we declare we want a pretty printed output (prettyPrint), we disable the cache to resolve the definition each time the endpoint is hit (cacheTTL), and we provide an info section directly in OpenAPI format, which will be merged with the resolved definition (openAPI).

Please check out below for the complete set of available properties.

Known locations

Dropping a file named openapi.yaml or openapi.json or openapi-configuration.yaml or openapi-configuration.json to a classpath or filesystem location from a specific set is probably the easiest way to provide a configuration. Depending on the environment, known locations include:

Path Type Environment
openapi.yaml classpath All
openapi.json classpath All
openapi.yaml file All
openapi.json file All
openapi.yaml servletpath Web app (root of webapp)
openapi.json servletpath Web app (root of webapp)
WEB-INF/openapi.yaml servletpath Web app
WEB-INF/openapi.json servletpath Web app
openapi-configuration.yaml classpath All
openapi-configuration.json classpath All
openapi-configuration.yaml file All
openapi-configuration.json file All
openapi-configuration.yaml servletpath Web app (root of webapp)
openapi-configuration.json servletpath Web app (root of webapp)
WEB-INF/openapi-configuration.yaml servletpath Web app
WEB-INF/openapi-configuration.json servletpath Web app

Try it out by cloning/downloading the Jersey or RESTEasy sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/sample/openapi.yaml (and .json).

Custom locations

While known locations are handy, you might want to specify the path of your configuration file yourself.

In a servlet based environment, such path can be defined as a servlet init parameter, e.g. in a Jersey environment with deployment descriptor:

  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
        io.swagger.v3.jaxrs2.integration.resources,io.swagger.sample.resource
      </param-value>
    </init-param>
    <init-param>
      <param-name>openApi.configuration.location</param-name>
      <param-value>openapi-customname-configuration.json</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

Alternatively, it can also be defined in code, e.g. in JAX-RS Application instance constructor (or in a custom bootstrap servlet, a ServletContainerInitializer implementation, etc..):

@ApplicationPath("/test")
public class MyApplication extends Application {
    public MyApplication() {
        try {
            new JaxrsOpenApiContextBuilder()
                .configLocation("/myconfigfile.json")
                .buildContext(true);
        } catch (OpenApiConfigurationException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}

See also Programmatic configuration below.

Servlet init parameters

In such a scenario you can directly define configuration properties as init parameters of the servlet serving your APIs (or any other "Bootstrap" servlet); For example within a RESTEasy HttpServletDispatcher servlet:

<servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>
      org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>io.swagger.sample.MyApplication</param-value>
    </init-param>
    <!-- specify resource classes to scan -->
    <init-param>
      <param-name>openApi.configuration.resourceClasses</param-name>
      <param-value>io.swagger.sample.resource.UserResource</param-value>
    </init-param>
    <!-- specify scanner implementation -->
    <init-param>
      <param-name>openApi.configuration.scannerClass</param-name>
      <param-value>io.swagger.v3.jaxrs2.integration.JaxrsAnnotationScanner</param-value>
    </init-param>
    <!-- pretty print -->
    <init-param>
      <param-name>openApi.configuration.prettyPrint</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>

Please check out below for the complete set of available properties and related parameters keys.

Try it out by cloning/downloading the Jersey or RESTEasy sample, and running it with mvn package jetty:run OpenAPI definition will be available at http://localhost:8002/sample/openapi.yaml (and .json).

Programmatic configuration

If for any reason it is preferable to provide a configuration (and initialization) programmatically, you can do it in any "bootstrap" code available, e.g.:

The mechanism applied is the same used to expose the OpenAPI definition, and makes use of contexts.

JAX-RS Application

@ApplicationPath("/sample")
public class MyApplication extends Application {

    public MyApplication(@Context ServletConfig servletConfig) {
        super();
        OpenAPI oas = new OpenAPI();
        Info info = new Info()
                .title("Swagger Sample App bootstrap code")
                .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                        "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                        "you can use the api key `special-key` to test the authorization filters.")
                .termsOfService("http://swagger.io/terms/")
                .contact(new Contact()
                        .email("[email protected]"))
                .license(new License()
                        .name("Apache 2.0")
                        .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

        oas.info(info);
        SwaggerConfiguration oasConfig = new SwaggerConfiguration()
                .openAPI(oas)
                .prettyPrint(true)
                .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));

        try {
            new JaxrsOpenApiContextBuilder()
                    .servletConfig(servletConfig)
                    .application(this)
                    .openApiConfiguration(oasConfig)
                    .buildContext(true);
        } catch (OpenApiConfigurationException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

    }
}

Own servlet

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

    OpenAPI oas = new OpenAPI();
    Info info = new Info()
      .title("Swagger Sample App - independent config exposed by dedicated servlet")
      .description("This is a sample server Petstore server.  You can find out more about Swagger " +
        "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
        "you can use the api key `special-key` to test the authorization filters.")
      .termsOfService("http://swagger.io/terms/")
      .contact(new Contact()
        .email("[email protected]"))
      .license(new License()
        .name("Apache 2.0")
        .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

    oas.info(info);
    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));

    try {
      new JaxrsOpenApiContextBuilder()
              .servletConfig(config)
              .openApiConfiguration(oasConfig)
              .buildContext(true);
    } catch (OpenApiConfigurationException e) {
      throw new ServletException(e.getMessage(), e);
    }

  }
}

Whatever bootstrap-initializer class

public class MyBootstrap {
    ...
    OpenAPI oas = new OpenAPI();
    Info info = new Info()
            .title("Swagger Sample App bootstrap code")
            .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                    "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                    "you can use the api key `special-key` to test the authorization filters.")
            .termsOfService("http://swagger.io/terms/")
            .contact(new Contact()
                    .email("[email protected]"))
            .license(new License()
                    .name("Apache 2.0")
                    .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

    oas.info(info);
    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .prettyPrint(true)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));

    try {
        new JaxrsOpenApiContextBuilder()
                //.servletConfig(servletConfig)
                //.application(this)
                .openApiConfiguration(oasConfig)
                .buildContext(true);
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

    }
}

Service loader

Alternatively you can provide an implementation of io.swagger.v3.oas.integration.api.OpenAPIConfigBuilder returning a configuration instance which will be applied to your integration, adding the following file to your META-INF/services directory, using standard Java service loader mechanism.

File: META-INF/services/io.swagger.v3.oas.integration.api.OpenAPIConfigBuilder:

foo.bar.YourBuilderImplementationClass

Resolve the OpenAPI Definition

Swagger integration layer makes use of a Configuration and so called contexts to allow for easy integration in different environments, however use of such contexts is not necessary to be able to resolve an OpenAPI definition out of a set of JAX-RS resources and related types.

Reader

The simplest way to obtain an OpenAPI instance (Java POJO implementing the OpenAPI definition) is using the Default JAX-RS Reader:

Reader reader = new Reader(new SwaggerConfiguration());
OpenAPI openAPI = reader.read(MyResourceClass.class);
// or reader.read(Stream.of(MyFirstResourceClass.class, MySecondResourceClass.class).collect(Collectors.toSet()));

You can then further process the OpenAPI POJO e.g serializing it to JSON (Json.prettyPrint(openAPI)), or to YAML (Yaml.prettyPrint(openAPI)), or pass it as entity of the response of your APIs, filtering, modifying, etc.

You can also pass an OpenAPI instance to the constructor, which will be merged with the resolved one:

Reader reader = new Reader(new OpenAPI().info(new Info().version("2.0")));
OpenAPI openAPI = reader.read(MyResourceClass.class);

Please note that such mechanism to resolve a definition out of a set of resources, can be applied both at design and run time, as long resources are available in classpath.

Converter

If you only care about definitions, even not in a JAX-RS environment, you can also directly use swagger-core converter logic to obtain corresponding OpenAPI schemas:

final Map<String, Schema> schemas = ModelConverters.getInstance().readAll(cls);

Context

To take full advantage of the configuration options and app environment, context usage comes handy, allowing to define a Configuration and/or to pass environment related objects (e.g. servletConfig, JAX-RS Application, etc). An example passing a full configuration (see related Jersey and RESTEasy samples):

    OpenAPI oas = new OpenAPI();
    Info info = new Info()
            .title("Swagger Sample App bootstrap code")
            .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                    "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                    "you can use the api key `special-key` to test the authorization filters.")
            .termsOfService("http://swagger.io/terms/")
            .contact(new Contact()
                    .email("[email protected]"))
            .license(new License()
                    .name("Apache 2.0")
                    .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

    oas.info(info);
    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .prettyPrint(true)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));


    try {
        OpenAPI openAPI = new JaxrsOpenApiContextBuilder()
                .openApiConfiguration(oasConfig)
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

or (allowing e.g. to get resource classes from JAX-RS Application or from servlet init parameters)

    try {
        OpenAPI openAPI = new JaxrsOpenApiContextBuilder()
                .servletConfig(servletConfig)
                .application(this)
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

or (passing the path to a file based configuration)

    try {
        OpenAPI openAPI = new JaxrsOpenApiContextBuilder()
                .configLocation("custom-openapi-configuration.yaml")
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

or (if a configuration file is present in a known location)

    try {
        OpenAPI openAPI = new JaxrsOpenApiContextBuilder()
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

or (if in a Servlet non JAX-RS environment)

    try {
        OpenAPI openAPI = new ServletOpenApiContextBuilder()
                .servletConfig(servletConfig)
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

or (if not in a Web application environment)

    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .prettyPrint(true)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));


    try {
        OpenAPI openAPI = new GenericOpenApiContextBuilder()
                .openApiConfiguration(oasConfig)
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

examples above make use of context builders as a convenient helper to build a context and registering it, handle multiple or root contexts, etc; you can anyway also use contexts directly:

    OpenApiContext ctx = new XmlWebOpenApiContext()
            .servletConfig(servletConfig)
            .app(application)
            .openApiConfiguration(openApiConfiguration)
            .parent(rootCtx)
            .init();
    ctx.read()

Contexts also allow to register separate instances handling different subsets of the APIs, or different configuration, endpoints etc. This is achieved by assigning a context id to a context:

    try {
        new JaxrsOpenApiContextBuilder()
                .ctxId("apiA")
                .configLocation("apiA-configuration.yaml")
                .buildContext(true);

        new JaxrsOpenApiContextBuilder()
                .ctxId("apiB")
                .configLocation("apiB-configuration.yaml")
                .buildContext(true);
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

and use it wherever needed:

    try {
        OpenAPI openAPI_A = new JaxrsOpenApiContextBuilder()
                .ctxId("apiA")
                .buildContext(true)
                .read();

        OpenAPI openAPI_B = new JaxrsOpenApiContextBuilder()
                .ctxId("apiB")
                .buildContext(true)
                .read();
    } catch (OpenApiConfigurationException e) {
        throw new RuntimeException(e.getMessage(), e);
    }

Resource scanning

By default, in a JAX-RS environment, Swagger identifies the set of resources to be "scanned" using io.swagger.v3.jaxrs2.integration.JaxrsApplicationAndAnnotationScanner, an OpenApiScanner implementation which includes:

  • Resources defined by JAX-RS application instance in classes() and getSingleton() (if existing)
  • Resources defined in configuration resourceClasses or resourcePackages
  • Types in classpath annotated with Path

You can customize resource scanning by providing the class name of the scanner to use in the configuration, e.g.:

    <init-param>
      <param-name>openApi.configuration.scannerClass</param-name>
      <param-value>io.swagger.v3.jaxrs2.integration.JaxrsAnnotationScanner</param-value>
    </init-param>

or (in a file configuration)

{
    "scannerClass": "my.custom.Scanner",
    "prettyPrint" : true,
    "openAPI": {
        "info": {
            "version": "1.0",
            "title": "Swagger Pet Sample App",
            "description": "This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.",
            "termsOfService": "http://swagger.io/terms/",
            "contact": {
                "email": "[email protected]"
            },
            "license": {
                "name": "Apache 2.0",
                "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
            }
        }
    }
}

depending on the environment/context, specifically:

Out of the box, in addition to JaxrsApplicationAndAnnotationScanner, Swagger provides:

  • Since 2.0.10 io.swagger.v3.jaxrs2.integration.JaxrsApplicationAndResourcePackagesAnnotationScanner: as JaxrsApplicationAndAnnotationScanner but not considering resources in classpath if resourcePackages is not defined. This behaves as JaxrsApplicationAndAnnotationScanner in versions up to 2.0.6 (see also #3284 and #3283)
  • io.swagger.v3.jaxrs2.integration.JaxrsAnnotationScanner: as JaxrsApplicationAndAnnotationScanner but not considering resources defined in JAX-RS application instance.
  • io.swagger.v3.jaxrs2.integration.JaxrsApplicationScanner: only considering resources defined in JAX-RS application instance.
  • io.swagger.v3.oas.integration.GenericOpenApiScanner: only considering resources defined in configuration resourceClasses or resourcePackages.

If none of these fits your need, you can provide a custom implementation of OpenApiScanner and declare it with one of the mechanisms detailed above.


Configuration properties

The following Configuration properties are supported, and can be represented/provided in different ways, as detailed below.

Property Data type Equivalent init param
resourcePackages Set / Comma separated string openApi.configuration.resourcePackages

set of resources packages to be scanned for resources; alternatively in a jersey environment, init param jersey.config.server.provider.packages is also recognized


Property Data type Equivalent init param
resourceClasses Set / Comma separated string openApi.configuration.resourceClasses

set of resources classes to be resolved; alternatively in a jersey environment, init param jersey.config.server.provider.classnames is also recognized


Property Data type Equivalent init param
openAPI Open API

Open API instance (e.g in json, yaml or java format) that will be merged with the resolved spec. Typically used to add Info section, or any other meta data.


Property Data type Equivalent init param
prettyPrint true/false openApi.configuration.prettyPrint

turns pretty printed spec on / off


Property Data type Equivalent init param
ignoredRoutes Set / Comma separated string

set of routes which will be ignored while resolving


Property Data type Equivalent init param
cacheTTL Long openApi.configuration.cacheTTL

resolved spec cache Time to live in milliseconds, default to -1 which means forever, set to 0 to disable cache


Property Data type Equivalent init param
filterClass String openApi.configuration.filterClass

custom implementation of io.swagger.v3.core.filter.OpenAPISpecFilter, invoked after resolving the spec to filter out or modify parts of the spec.


Property Data type Equivalent init param
readerClass String openApi.configuration.readerClass

custom implementation of io.swagger.v3.oas.integration.api.OpenApiReader


Property Data type Equivalent init param
scannerClass String openApi.configuration.scannerClass

custom implementation of io.swagger.v3.oas.integration.api.OpenApiScanner


Property Data type Equivalent init param
readAllResources true/false openApi.configuration.readAllResources

Default to true. By setting this flag to false only Operation annotated methods are considered.


Since Property Data type Equivalent init param
Since 2.0.6 modelConverterClasses Set / Comma separated string openApi.configuration.modelConverterClasses

set of custom ModelConverters to be applied.


Since Property Data type Equivalent init param
Since 2.0.6 objectMapperProcessorClass String openApi.configuration.objectMapperProcessorClass

implementation of io.swagger.v3.oas.integration.api.ObjectMapperProcessor interface, allowing to customize Jackson object mapper in use.

Since 2.1.6 ObjectMapperProcessor is now defining 2 more methods processOutputJsonObjectMapper and processOutputYamlObjectMapper to customize the "output mapper" used for serialization of resolved output.


Since Property Data type Equivalent init param
Since 2.1.6 sortOutput true/false openApi.configuration.sortOutput

see https://github.com/swagger-api/swagger-core/pull/3740#issue-532125507


Since Property Data type Equivalent init param
Since 2.1.9 alwaysResolveAppPath true/false openApi.configuration.alwaysResolveAppPath

Since version 2.1.9 #3936 a new boolean configuration parameter alwaysResolveAppPath is available: if set to true @ApplicationPath annotation applied to a JAX-RS Application class will be considered also at build time (e.g. via maven/gradle plugin or programmatic execution) and when exposing via a separate app (e.g. via OpenAPIServlet).


Since Property Data type Equivalent init param
Since 2.2.0 openAPI31 true/false openApi.configuration.openAPI31

Since version 2.2.0 a new boolean configuration parameter openAPI31 is available: if set to true the resolved spec will be processed to convert it into a 3.1.0 specification by updating the version and converting any incompatible construct into the one supoorted in 3.1


Since Property Data type Equivalent init param
Since 2.2.17 defaultResponseCode String openApi.configuration.defaultResponseCode

Allows to set the code used when resolving responses with no http status code annotation

Configuration file example

{
    "resourcePackages": [
        "io.swagger.sample.resource"
    ],
    "prettyPrint" : true,
    "openAPI": {
        "info": {
            "version": "1.0",
            "title": "Swagger Pet Sample App",
            "description": "This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.",
            "termsOfService": "http://swagger.io/terms/",
            "contact": {
                "email": "[email protected]"
            },
            "license": {
                "name": "Apache 2.0",
                "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
            }
        }
    }
}

Init params example

  <servlet>
    ...
    <init-param>
      <param-name>openApi.configuration.resourceClasses</param-name>
      <param-value>io.swagger.sample.resource.PetResource,io.swagger.sample.resource.UserResource</param-value>
    </init-param>
    <init-param>
      <param-name>openApi.configuration.prettyPrint</param-name>
      <param-value>true</param-value>
    </init-param>
    ...
  </servlet>

Custom code initializer, e.g. in custom servlet, listener, context initializer, etc

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

    OpenAPI oas = new OpenAPI();
    Info info = new Info()
      .title("Swagger Sample App")
      .description("This is a sample server Petstore server.  You can find out more about Swagger " +
        "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
        "you can use the api key `special-key` to test the authorization filters.")
      .termsOfService("http://swagger.io/terms/")
      .contact(new Contact()
        .email("[email protected]"))
      .license(new License()
        .name("Apache 2.0")
        .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

    oas.info(info);
    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));

    try {
      new JaxrsOpenApiContextBuilder()
              .servletConfig(config)
              .openApiConfiguration(oasConfig)
              .buildContext(true);
    } catch (OpenApiConfigurationException e) {
      throw new ServletException(e.getMessage(), e);
    }

        // or
    /*
        try {
          new XmlWebOpenApiContext().servletConfig(config).openApiConfiguration(oasConfig).init();
        } catch (OpenApiConfigurationException e) {
          e.printStackTrace();
        }
    */
  }
}

Scenarios examples

Please also check out swagger samples.

Jersey JAX-RS container servlet

with configuration file in known location

    <servlet>
      <servlet-name>jersey</servlet-name>
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
      <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            io.swagger.v3.jaxrs2.integration.resources,
            {your.application.packages}
        </param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

see related sample.

Jersey JAX-RS container filter

with configuration file in known location

    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                io.swagger.v3.jaxrs2.integration.resources,
                {your.application.packages}
            </param-value>
        </init-param>
        <!-- param below necessary in Servlet 2.x envs, see https://jersey.github.io/documentation/latest/deployment.html#d0e3419 -->
        <init-param>
          <param-name>jersey.config.servlet.filter.contextPath</param-name>
          <param-value>/api</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>jersey</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

RESTEasy JAX-RS container servlet

  <servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>
      org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>io.swagger.sample.MyApplication</param-value>
    </init-param>
    <!-- specify resource classes to scan -->
    <init-param>
      <param-name>openApi.configuration.resourceClasses</param-name>
      <param-value>io.swagger.sample.resource.UserResource</param-value>
    </init-param>
    <init-param>
      <param-name>openApi.configuration.prettyPrint</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/sample/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/sample</param-value>
  </context-param>

see related sample.

JAX-RS Application

@ApplicationPath("/sample")
public class MyApplication extends Application {

    public MyApplication(@Context ServletConfig servletConfig) {
        super();
        OpenAPI oas = new OpenAPI();
        Info info = new Info()
                .title("Swagger Sample App bootstrap code")
                .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                        "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                        "you can use the api key `special-key` to test the authorization filters.")
                .termsOfService("http://swagger.io/terms/")
                .contact(new Contact()
                        .email("[email protected]"))
                .license(new License()
                        .name("Apache 2.0")
                        .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

        oas.info(info);
        SwaggerConfiguration oasConfig = new SwaggerConfiguration()
                .openAPI(oas)
                .prettyPrint(true)
                .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));


        try {
            new JaxrsOpenApiContextBuilder()
                    .servletConfig(servletConfig)
                    .application(this)
                    .openApiConfiguration(oasConfig)
                    .buildContext(true);
        } catch (OpenApiConfigurationException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

    }
}

see related sample.

Dropwizard

public class SwaggerSampleApplication extends Application <SwaggerSampleConfiguration> {
  public static void main(String[] args) throws Exception {
    new SwaggerSampleApplication().run(args);
  }

  @Override
  public void initialize(Bootstrap<SwaggerSampleConfiguration> bootstrap) { }

  @Override
  public String getName() {
      return "swagger-sample";
  }

  @Override
  public void run(SwaggerSampleConfiguration configuration, Environment environment) {

    OpenAPI oas = new OpenAPI();
    Info info = new Info()
            .title("Swagger Sample App")
            .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                    "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                    "you can use the api key `special-key` to test the authorization filters.")
            .termsOfService("http://swagger.io/terms/")
            .contact(new Contact()
                    .email("[email protected]"))
            .license(new License()
                    .name("Apache 2.0")
                    .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

    oas.info(info);
    SwaggerConfiguration oasConfig = new SwaggerConfiguration()
            .openAPI(oas)
            .prettyPrint(true)
            .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));

    environment.jersey().register(new PetResource());
    environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);

    // eg.
    environment.jersey().register(new OpenApiResource().openApiConfiguration(oasConfig));

    // or
/*
    try {
      new GenericOpenApiContext().openApiConfiguration(oasConfig).init();
    } catch (OpenApiConfigurationException e) {
      e.printStackTrace();
    }
    environment.jersey().register(new OpenApiResource());
*/

    // or
    //environment.jersey().register(new OpenApiResource().configLocation("/integration/openapi-configuration.json"));

    // or provide an openapi.json or yaml / openapi-configuration.json or yaml in classpath

    // or
    //environment.jersey().register(new OpenApiResource().resourcePackage("io.swagger.sample.resource"));

    // or
    //environment.jersey().register(new OpenApiResource().resourceClasses("io.swagger.sample.resource.PetResource"));


  }
}

see related sample.

Guice

public class SwaggerExampleGuiceContextListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
            @Override
            protected void configureServlets() {
                bind(ServletContainer.class).in(Singleton.class);
                bind(ApiOriginFilter.class).in(Singleton.class);

                Map<String, String> props = new HashMap<String, String>();
                props.put("javax.ws.rs.Application", MyApplication.class.getName());
                props.put("jersey.config.server.wadl.disableWadl", "true");
                serve("/api/*").with(ServletContainer.class, props);

                OpenAPI oas = new OpenAPI();
                Info info = new Info()
                        .title("Swagger Sample App bootstrap code")
                        .description("This is a sample server Petstore server.  You can find out more about Swagger " +
                                "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
                                "you can use the api key `special-key` to test the authorization filters.")
                        .termsOfService("http://swagger.io/terms/")
                        .contact(new Contact()
                                .email("[email protected]"))
                        .license(new License()
                                .name("Apache 2.0")
                                .url("http://www.apache.org/licenses/LICENSE-2.0.html"));

                oas.info(info);
                SwaggerConfiguration oasConfig = new SwaggerConfiguration()
                        .openAPI(oas)
                        .prettyPrint(true)
                        .resourcePackages(Stream.of("io.swagger.sample.resource").collect(Collectors.toSet()));


                try {
                    new JaxrsOpenApiContextBuilder()
                            .openApiConfiguration(oasConfig)
                            .buildContext(true);
                } catch (OpenApiConfigurationException e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
            }
        });
    }
}

see related sample.

A bunch of Jersey examples

config file location as init param

You can also provide the file location and name as an init param.

If you're defining it as a servlet:

    <servlet>
      <servlet-name>jersey</servlet-name>
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
      <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            io.swagger.v3.jaxrs2.integration.resources,
            {your.application.packages}
        </param-value>
      </init-param>
       <init-param>
         <param-name>openApi.configuration.location</param-name>
         <param-value>/foo/bar/your-openapi-configuration.json</param-value>
       </init-param>       
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

And if as a filter:

    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                io.swagger.v3.jaxrs2.integration.resources,
                {your.application.packages}
            </param-value>
        </init-param>
       <init-param>
         <param-name>openApi.configuration.location</param-name>
         <param-value>/foo/bar/your-openapi-configuration.json</param-value>
       </init-param>                
        <!-- param below necessary in Servlet 2.x envs, see https://jersey.github.io/documentation/latest/deployment.html#d0e3419 -->
        <init-param>
          <param-name>jersey.config.servlet.filter.contextPath</param-name>
          <param-value>/api</param-value>
        </init-param>        
    </filter>


    <filter-mapping>
        <filter-name>jersey</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

Package scanning / Concrete class selection

In both cases, you can use <init-param/> to set which packages or classes Jersey should scan/load when it starts. This is where you'd define your own packages and/or classes.

To hook Swagger into your application, you need to add the some of Swagger's packages and classes.

Package scanning

If you're defining it as a servlet:

    <servlet>
      <servlet-name>jersey</servlet-name>
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
      <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            io.swagger.v3.jaxrs2.integration.resources,
            {your.application.packages}
        </param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

And if as a filter:

    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                io.swagger.v3.jaxrs2.integration.resources,
                {your.application.packages}
            </param-value>
        </init-param>
        <!-- param below necessary in Servlet 2.x envs, see https://jersey.github.io/documentation/latest/deployment.html#d0e3419 -->
        <init-param>
          <param-name>jersey.config.servlet.filter.contextPath</param-name>
          <param-value>/api</param-value>
        </init-param>        
    </filter>


    <filter-mapping>
        <filter-name>jersey</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

You can also use swagger specific init param in a similar way, e.g to scan a subset of the APIs:

    <servlet>
      <servlet-name>jersey</servlet-name>
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
      <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            io.swagger.v3.jaxrs2.integration.resources,
            {your.application.packages}
        </param-value>
      </init-param>
      <init-param>
        <param-name>openApi.configuration.resourcePackages</param-name>
        <param-value>            
            {your.application.packages.subset}
        </param-value>
      </init-param>      
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
Concrete class selection

If you're defining it as a servlet:

    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>
                io.swagger.v3.jaxrs2.integration.resources.OpenApiResource,
                {your.application.classes}
            </param-value>
        </init-param>
    </servlet>


    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

And if as a filter:

    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>
                io.swagger.v3.jaxrs2.integration.resources.OpenApiResource,
                {your.application.classes}
            </param-value>
        </init-param>
        <!-- param below necessary in Servlet 2.x envs, see https://jersey.github.io/documentation/latest/deployment.html#d0e3419 -->
        <init-param>
          <param-name>jersey.config.servlet.filter.contextPath</param-name>
          <param-value>/api</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>jersey</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

A few things to note:

  1. {your.application.packages}, {your.application.classes} should be replaced by the package(s) or classes of your application, respectively.
  2. The mapping of either servlet or filter depends on your own needs. The above is just an example.

Using a custom Application subclass

When using a custom Application subclass, you would need to add swagger-core's providers to the set up process. For example:

public class SampleApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet();

        //resources.add(FirstResource.class);
        //resources.add(SecondResource.class);
        //...

        resources.add(io.swagger.v3.jaxrs2.integration.resources.OpenApiResource.class);
        
        return resources;
    }
}

The commented part is where you'd add your own application's resources and providers.


What's Next?

Now that you have everything hooked up, don't forget to add some Annotations to your resources, so that those are added to your API definition.

Note: swagger-jaxrs2 reader engine includes by default also methods of scanned resources which are not annotated with @Operation, as long as a jax-rs @Path is defined at class and/or method level, together with the http method annotation (@GET, @POST, etc).

This behaviour is controlled by configuration property readAllResources which defaults to true. By setting this flag to false only Operation annotated methods are considered.

Clone this wiki locally