Swagger has become the de facto standard for REST API documentation. It is also a pretty generic framework and developers need to know how to configure their specific environment. In this post, I will review the steps required to document a JAX-RS API developed with IBM WebSphere Application Server Liberty Profile. The complete example is available on my GitHub repository.
I will assume that you have created a Maven Dynamic Web project in Eclipse (project name and web context root are set to 'swagger-liberty'), and that you have defined a WAS Liberty server environment. Setting up your environment is outside the scope of this post, but you can find more information here.
In order to develop and document your JAX-RS API, you will need to follow these steps:
- Declare the required maven dependencies.
- Declare the JAX-RS and Swagger servlets.
- Declare the Swagger JAX-RS providers and your JAX-RS resources.
- Implement and document your APIs using Java annotations.
- Copy the Swagger UI web resource files.
- Activate the JAX-RS feature of Liberty.
- Test your server locally.
The first step is to add the maven dependencies to your maven project. You need to add the Swagger JAX-RS bridge, logging bridge and JEE 6 apis:
<dependency> <groupId>com.wordnik</groupId> <artifactId>swagger-jaxrs_2.10</artifactId> <version>1.3.10</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>6.0</version> <scope>provided</scope> </dependency>
Then you need to declare the servlets in your web.xml file. The first servlet is used to indicate the JAX-RS runtime where to find your JAX-RS application.
<servlet> <description>JAX-RS Tools Generated - Do not modify</description> <servlet-name>JAX-RS Servlet</servlet-name> <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.mycloudtips.swagger.MctApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> <enabled>true</enabled> <async-supported>false</async-supported> </servlet> <servlet-mapping> <servlet-name>JAX-RS Servlet</servlet-name> <url-pattern>/jaxrs/*</url-pattern> </servlet-mapping>The second servlet is used to configure the Swagger runtime and indicate where to find the API meta-data (the base path, which is made of the web root context and the JAX-RS servlet mapping).
<servlet> <servlet-name>DefaultJaxrsConfig</servlet-name> <servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class> <init-param> <param-name>api.version</param-name> <param-value>1.0.0</param-value> </init-param> <init-param> <param-name>swagger.api.basepath</param-name> <param-value>/swagger-liberty/jaxrs</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet>
The application class (MctApplication class) is the place where you need to declare the JAX-RS Swagger providers and your JAX-RS resource (MctResource class). Note that I usually declare the resources as singletons so that they are not created at each request.
@Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<Class<?>>(); classes.add(ApiDeclarationProvider.class); classes.add(ResourceListingProvider.class); classes.add(ApiListingResourceJSON.class); return classes; } @Override public Set<Object> getSingletons() { Set<Object> singletons = new HashSet<Object>(); singletons.add(new MctResource()); return singletons; }
The resource class is the place where you can develop and document your APIs. You need to use the JAX-RS and Swagger annotations. Here is an example to declare a method returning a list of books:
@GET @ApiOperation(value = "Returns the list of books from the library.", response = MctBook.class, responseContainer = "List") @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal error") }) public Collection<MctBook> getBooks() { return library.values(); }
The server will include the Swagger UI and you need to copy the web resources (index.html, o2c.html, sagger-ui.js, sawgger-ui.min.js, lib, images and css files and directories). You can find these files in the Swagger UI JAX-RS sample or in my GitHub repository. You also need to adjust a path in the index.html file to point to your API:
$(function () { window.swaggerUi = new SwaggerUi({ url: "/swagger-liberty/jaxrs/api-docs", ... });
At this point, your project should compile fine and you should get ready to test. Before doing so, you need to activate the JAX-RS support in Liberty. Remember that Liberty is very flexible and let you decide what features will be loaded. To do so, you need to add the jaxrs-1.1 feature in the server.xml file.
<featureManager> <feature>jaxrs-1.1</feature> <feature>localConnector-1.0</feature> </featureManager>
Finally, you can add your application to your server runtime and start it. You should then be able to access the Swagger UI:
http://localhost:9080/swagger-liberty/As an optional step, not covered in this post, you can easily deploy this server to IBM Bluemix.
Works like a charm - thank you!
ReplyDeleteHi. There's now native support in Liberty to auto-generate Swagger documents from jaxrs / swagger annotations and expose them in a native UI. You can do this via the latest beta https://developer.ibm.com/wasdev/blog/2015/11/20/beta-was-liberty-beta-with-tools-december-2015/
ReplyDeleteDocumentation is here: http://www-01.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_api_discovery.html
Hi. There's now native support in Liberty to auto-generate Swagger documents from jaxrs / swagger annotations and expose them in a native UI. You can do this via the latest beta https://developer.ibm.com/wasdev/blog/2015/11/20/beta-was-liberty-beta-with-tools-december-2015/
ReplyDeleteDocumentation is here: http://www-01.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_api_discovery.html