Documenting RESTful Webservices in Swagger, AsciiDoc and Plain Text with Maven and the JAX-RS Analyzer

June 16th, 2015 by

A variety of different tools exists to help us analyze RESTful web-services and create documentations for their APIs in different formats.

In the following tutorial I’d like to demonstrate how to document an existing JAX-RS web-service in multiple formats like Swagger, AsciiDoc or Plain Text using Maven, the JAX-RS Analyzer and the JAX-RS Analyzer Maven Plugin.

The JAX-RS Analyzer gathers its information not only by reflection like most other tools but also by bytecode analysis and therefore does not require us to add special annotations for documentation to our code.

Generated Swagger definition imported into the Swagger online editor.

Generated Swagger definition imported into the Swagger Online Editor.

 

Project Setup

We’re reusing the sample RESTful web-service from my tutorial “Testing RESTful Web Services made easy using the REST-assured Framework” (sources) so that we only need to add one dependency for the jaxrs-analyzer-maven-plugin to our pom.xml:

<plugin>
	<groupId>com.sebastian-daschner</groupId>
	<artifactId>jaxrs-analyzer-maven-plugin</artifactId>
	<version>0.5</version>
	<executions>
		<execution>
			<goals>
				<goal>analyze-jaxrs</goal>
			</goals>
			<configuration>
				<backend>plaintext</backend>
				<deployedDomain>localhost</deployedDomain>
			</configuration>
		</execution>
	</executions>
</plugin>

Generating Documentation

The maven plug-in generates the documentation for our JAX-RS based REST services every time our project is built.

In the plug-in’s configuration we may specify the designated output format, currently supported are plain-text, swagger and asciidoc.

Plain Text

To generate our API documentation in plain text, we’re setting plaintext in the backend element in the plug-in configuration and we’re building our project with Maven:

$ mvn clean package

Afterwards our plain-text documentation can be found in the target/jaxrs-analyzer directory:

$ tree target/jaxrs-analyzer
target/jaxrs-analyzer
└── rest-resources.txt

This is our generated plain-text documentation (shortened):

REST resources of jaxrs analyzer tutorial:
1.0.0
 
GET service/persons/xml:
 Request:
  No bod
 
 Response:
  Content-Type: application/xml
  Status Codes: 200
   Response Body: com.hascode.ra_samples.Person (application/json):
[{"firstName":"string","lastName":"string","id":0,"email":"string"}]
 
GET service/secure/person:
 Request:
  No body
 
 Response:
  Content-Type: application/json
  Status Codes: 200
   Response Body: com.hascode.ra_samples.Person (application/json):
{"firstName":"string","lastName":"string","id":0,"email":"string"}
 
GET service/single-user:
 Request:
  No body
 
 Response:
  Content-Type: application/json
  Status Codes: 200
   Response Body: com.hascode.ra_samples.User (application/json):
{"firstName":"string","lastName":"string","id":0,"email":"string"}
 
[..]

I have added the full generated plain-text API documentation to my repository here.

Swagger

Swagger is a formal specification for RESTful web-services and offers rich integrations and tool support (more).

To generate our documentation in the Swagger JSON format, we simply need to change the backend type in the plugin configuration to swagger:

<configuration>
	<backend>swagger</backend>
	[..]
</configuration>

Building the project with Maven again now generates the following (shortened) swagger.json in the directory target/jaxrs-analyzer:

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.0",
    "title": "jaxrs analyzer tutorial"
  },
  "host": "localhost",
  "basePath": "\/",
  "schemas": [
    "http"
  ],
  "paths": {
    "\/service\/persons\/xml": {
      "get": {
        "consumes": [
 
        ],
        "produces": [
          "application\/xml"
        ],
        "parameters": [
 
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
 
            },
            "schema": {
              "type": "array",
              "items": {
                "$ref": "definition#1"
              }
            }
          }
        }
      }
    },
    "\/service\/user\/create": {
      "get": {
        "consumes": [
 
        ],
        "produces": [
          "application\/json"
        ],
        "parameters": [
          {
            "name": "firstName",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "lastName",
            "in": "query",
            "required": true,
            "type": "string"
          },
          {
            "name": "email",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
 
            },
            "schema": {
              "$ref": "definition#5"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "definition#1": {
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "id": {
          "type": "number"
        },
        "email": {
          "type": "string"
        }
      }
    },
    "definition#5": {
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "id": {
          "type": "number"
        },
        "email": {
          "type": "string"
        }
      }
    }
  }
}

I have added the complete generated Swagger API definition to my repository here.

Online tools as the Swagger Online Editor allows viewing, editing and validating Swagger definitions – this is what our uploaded swagger.json looks like:

Generated Swagger definition imported into the Swagger online editor.

Generated Swagger definition imported into the Swagger Online Editor.

In addition, the online editor allows us to generate REST-clients in several languages from the uploaded Swagger file:

Generating REST clients using the Swagger Online Editor.

Generating REST clients using the Swagger Online Editor.

AsciiDoc

AsciiDoc is a plain-text writing format for authoring notes, articles, documentation, books, ebooks, web pages, slide decks, blog posts, man pages and more. (source)

To set our documentation format to AsciiDoc we simply need to set asciidoc in our plug-in configuration:

<configuration>
	<backend>asciidoc</backend>
	[..]
</configuration>

When we’re building our project again, we’re able to see the following (shortened) AsciiDoc API documentation in a file named rest-resources.adoc in target/jaxrs-analyzer:

= REST resources of jaxrs analyzer tutorial
1.0.0
 
== `GET service/persons/xml`
 
=== Request
_No body_ + 
 
=== Response
*Content-Type*: `application/xml`
 
==== `200 OK`
*Response Body*: (`com.hascode.ra_samples.Person`) +
`application/json`: `[{"firstName":"string","lastName":"string","id":0,"email":"string"}]` + 
 
== `GET service/secure/person`
 
=== Request
_No body_ + 
 
=== Response
*Content-Type*: `application/json`
 
==== `200 OK`
*Response Body*: (`com.hascode.ra_samples.Person`) +
`application/json`: `{"firstName":"string","lastName":"string","id":0,"email":"string"}` +

I have added the full generated AsciiDoc API documentation to my repository here.

This is what our generated documentation looks like in the asciidocLive editor:

Generated AsciiDoc rendered in the AsciiDoc Online Editor

Generated AsciiDoc rendered in the AsciiDoc Online Editor

Appendix A: JAX-RS Service

Here is the JAX-RS web-service that we have used as reference in the examples above – the complete sources are available in my repository here.

package com.hascode.ra_samples;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
@Path("/service")
public class RestAssuredSampleService {
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/single-user")
	public User getSingleUser() {
		User user = new User();
		user.setEmail("test@hascode.com");
		user.setFirstName("Tim");
		user.setLastName("Testerman");
		user.setId(1L);
		return user;
	}
 
	@GET
	@Produces(MediaType.APPLICATION_XML)
	@Path("/single-user/xml")
	public User getSingleUserAsXml() {
		User user = new User();
		user.setEmail("test@hascode.com");
		user.setFirstName("Tim");
		user.setLastName("Testerman");
		user.setId(1L);
		return user;
	}
 
	@GET
	@Produces(MediaType.APPLICATION_XML)
	@Path("/persons/xml")
	public List<Person> allUsers() {
		List<Person> users = new ArrayList<Person>();
		Person person1 = new Person();
		person1.setEmail("test@hascode.com");
		person1.setFirstName("Tim");
		person1.setLastName("Testerman");
		person1.setId(1L);
		users.add(person1);
 
		Person person2 = new Person();
		person2.setEmail("dev@hascode.com");
		person2.setFirstName("Sara");
		person2.setLastName("Stevens");
		person2.setId(20L);
		users.add(person2);
 
		Person person3 = new Person();
		person3.setEmail("devnull@hascode.com");
		person3.setFirstName("Mark");
		person3.setLastName("Mustache");
		person3.setId(11L);
		users.add(person3);
		return users;
	}
 
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/user/create")
	public User createUser(@QueryParam("email") final String email,
			@QueryParam("firstName") final String firstName,
			@QueryParam("lastName") final String lastName) {
		User user = new User();
		user.setEmail(email);
		user.setFirstName(firstName);
		user.setLastName(lastName);
		user.setId(1L);
 
		return user;
	}
 
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	@Path("/status/notfound")
	public Response statusNotFound() {
		return Response.status(404).build();
	}
 
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/secure/person")
	public Person secureGetPerson() {
		Person person = new Person();
		person.setEmail("test@hascode.com");
		person.setFirstName("Tim");
		person.setLastName("Testerman");
		person.setId(1L);
		return person;
	}
 
}

Tutorial Sources

Please feel free to download the tutorial sources from my Bitbucket repository, fork it there or clone it using Git:

git clone https://bitbucket.org/hascode/jaxrs-analyzer-tutorial.git

Resources

Search
Categories