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.
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:
In addition, the online editor allows us to generate REST-clients in several languages from the uploaded Swagger file:
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:
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 GitHub repository, fork it there or clone it using Git:
git clone https://bitbucket.org/hascode/jaxrs-analyzer-tutorial.git
Additional REST articles of mine
Please feel free to have a look at these tutorials of mine covering different aspects of handling or creating RESTful webservices.
Resources
Article Updates
-
2015-08-06: Links to other REST articles of mine added.
-
2015-10-22: Link list updated