REST API Documentation Generation
Introduction
The Synapse REST API documentation is composed of a set of auto-generated HTML pages that are published to S3 as a website (see: Hosting a Static Website on Amazon S3 ). All of the auto-generated HTML is extracted from the javadocs of the Controller class that make up the REST service calls and the JSON Entity schemas that make up the model objects. This page covers how to generate the HTML from the javadocs and what each developer is expected provide in the way of API documentation when new REST calls are added or existing calls are modified.
Building the Javadocs
Currently, all of the REST docs are generated from the services-repository project. The following command can be use to build the services-repository project and the javadocs:
cd services/repository mvn clean install -Dmaven.test.skip=true
If the services-repository project has already been compiled, the javadocs can be re-created simply by running:
mvn javadoc:javadoc
The javadocs will be generated in the following directory:
/services/repository/target/javadoc/restdocs
You can view your local copy of the docs in your favorite browser with the following URL:
file:///<your_path>/Synapse-Repository-Services/services/repository/target/javadoc/restdocs/index.html
All of the javadocs are generated with a custom Doclet found in the lib-javadoc project: org.sagebionetworks.javadoc.web.services.SpringMVCDoclet
Documenting Controllers
Including a Controller
The SpringMVCDoclet will scan all Controllers and look for the following special annotation org.sagebionetworks.repo.web.rest.doc.ControllerInfo. The doclet will only create documentation for controllers with this annotation. Here is an example:
@ControllerInfo(displayName="File Services", path="file/v1")
The ControllerInfo annotation provides two key pieces of information need for the documentation:
key | description |
---|---|
displayName | The display name is used as the main header for the Controller HTML. By convention, each display name should have 'Services' as a suffix. |
path | Each REST method has a Resource URL that is composed of three parts host, path, method: http://<host>/<path>/<method>
In the following example 'path' = 'repo/v1': |
Class Javadoc
The class javadocs is the comment for the class itself (between the include section and 'class'). The class javadoc should summarize the entire set of services represented by the controller. This is also where documentation about multiple methods should included. For example, if the caller is expected to call method one, then two, followed by three, such listing should be covered in the class javadocs. Remember the javadocs can contain HTML, and many of the basic HTML tags will work. We will cover supported HTML tags in a later section.
Method javadoc
The javadocs for a method is composed of many parts. We will cover those parts here and how the Doclet interprets the combination of comments and annotations to generate the resulting HTML.
The main method comment should include a description of the method and should include a "@param" comment for each parameter exposed to the caller. We will cover which parameters are exposed to the caller in a later section. Here is an example of a method with a javadoc:
/** * Get a FileHandle using its ID. * <b>Note: Only the creator of a FileHandle can fetch a FileHandle with this method.</b> * * @param handleId The ID of the FileHandle to get. * @param userId The ID of the user making this call. The Auth filter will provide this value. * @param request Not used * @return * @throws FileUploadException * @throws IOException * @throws DatastoreException * @throws NotFoundException * @throws ServiceUnavailableException * @throws JSONObjectAdapterException */ @ResponseStatus(HttpStatus.OK) @RequestMapping(value ="/fileHandle/{handleId}" , method = RequestMethod.GET) public @ResponseBody FileHandle getFileHandle( @PathVariable String handleId, @RequestParam(value = AuthorizationConstants.USER_ID_PARAM) String userId, HttpServletRequest request) throws FileUploadException, IOException, DatastoreException, NotFoundException, ServiceUnavailableException, JSONObjectAdapterException {
Method description
In this example, lines 1 and 2 will become the main method description. Notice the use of the HTLM '<b>' tags in the comment. All HTML tags will preserved in the final HTML document.
Method Parameters
Only parameters with the '@PathVariable' and '@RequestParam' annotations are included in the final HTML of the method. There is one exception to this rule, for the 'userId' parameter, which is covered in the next section.
In the example above, line 5 show the documentation of the path variable declared at line 19. The comment from line 5 will be include in the output HTML. Path variable and request parameters are documented in separatly in the final method HTML page.
Method Authentication
Most REST calls require authentication of the caller. When authentication is required, the 'userId' parameter is included in the method signature (see: line 20 above). The caller does not provide the 'userId' directly, instead the Authentication filter processes the user's sessionToken or method signature and fills in the 'userId' parameter on the caller's behalf. Therefore, we do not document the 'userId' parameter directly. Instead, if the 'userId' parameter is part of the method signature, the method will be marked as 'Authentication Required'. If the 'userId' parameter is not part of the method signature then the method will be marked as 'Authentication False'.
Method Request Mapping
The '@RequestMapping' annotation in the above example (line: 17) provides two key pieces of information; method name (from the value) and the HTTP type (from method).
Method Response & Request
The SpringMVCDoclet only supports model objects that have a JSON schema for both the response and request bodies. In addition the response object must be marked with the '@ResponseBody' annotation. Similarly, the request body must be marked with the '@RequestBody'. If both of these requirement are met, then a link will automatically be provide for the HTML of the model object. If a request or response object does not meet both of these requirements, then the corresponding fields of the method HTML page will be blank.
Documenting Model Objects
All model object are expected to have a JSON schema that defines the model. The model documentation HTML is derived from the full class name of the object and the descriptions in the schema JSON. Here is an example:
{ "description": "Schema defining a Participant object in a Synapse Evaluation.", "name": "Participant", "properties": { "userId": { "type": "string", "description": "The Synapse ID of this Participant.", "transient": true } }
In the above example, the main description for the model object is derived directly from the description from line: 2. Each field should also have a description that will be included such as the 'userId' description at line: 7. Any model object that is a composition of JSON objects will include a link to composite models in the final model HTML.
It is helpful to re-run the build of the lib-auto-generated project continually when editing the schema files to ensure there are no errors:
cd lib/lib-auto-generated mvn clean install
Supported HTML tags
Many of the basic HTML tags can be used without modification in any controller javadoc comment. This includes the following:
- Table <table>
- List <ul> and <ol>
- Paragraph <p>
- Bold <b>
- Paragraph <p>
Links
Linking to auto-generated pages such as JSON Model objects or REST methods requires special syntax.
Model Links
The following is an example of linking to a JSON Model object from a javadoc comment:
/** * Files in Synapse are represented as with a <a href="${org.sagebionetworks.repo.model.file.FileHandle}">FileHandle</a> object. * */
The <a> tag's href in the above example contains special syntax. The href format is "${<fully_qualified_name>}". The doclet will replace this property like syntax with the final path of the FileHandle model HTML file.
Method Links
The following is an example of linking to a REST method call:
/** * See: <a href="${GET.admin.daemon.daemonId}">GET /admin/daemon/{daemonId}</a> */
The <a> tag's href in the above example contains special syntax. The doclet will replace this property like syntax with the final path of the 'GET /admin/daemon/{daemonId}' method HTML file.