Attention: Open API Support will be available with the release of Version 3.0. It is currently (February 2022) available in the 3.0-SNAPSHOT.

Introduction

JavaLite supports the Open API Initiative. The main advantage of the JavaLite support is the ability to keep the OpenAPI documentation very close to the code, so that it is easier to maintain.

Writing Open API Specifications

The API specifications for JavaLite apps can be written in two places:

  • Directly in controllers inside the GET/POST/PUT/DeLETE (etc) annotations
  • In project files

Example APP

A full example for the Open API support can be found in a Pet Store API example. Ensure to read its README file.

Template file

A template file is a starting point in the documentation. It can be located anywhere in code, but the suggested location and name is:

src/main/open-api/base.json

The most bare-bones example of this file is:

{
  "openapi": "3.0.0",
  "info": {
    "title": "Simple API overview",
    "version": "3.0.0"
  },
  "paths":{

   }
}

As you can see, the file has an object paths that is blank. This is where the generated documentation will be injected. This file can be adorned with more information above and below the paths object, and none of that will change.

OpenAPI versions

The JavaLite Open API implementation is agnostic to Open API versioning. A developer can specify the version in the base template file and provide additional information before and after the paths element as he/she sees fit.

JavaLite does not validate the correctness of the specification according to OpenAPI standards. It merely merges all documentation from controllers and external files into a base template.

As long as a developer or documentation writer provides all the pieces of documentation that conforms to the Open API standard, teh resulting file will comply too.

Open API formats

Current (3.0-SNAPSHOT and future 3.0) support for Open API JSON. The YAML support may come at a later time.

Annotations - Based Approach

ActiveWeb provides Java annotations that can be added to an action method in controllers. See Controllers and HTTP methods for more information.

The ActiveWeb annotations signify what HTTP method to use with a corresponding action. However, they also accept a string that is a snippet of Open API documentation.

A bare minimum example will look like this:

public class PeopleController extends AppCOntroller {
    
    @PUT("""
            {
                "description" : "Adding a new Person, etc.",
                "responses": {
                    "200": {
                    "description": "200 OK"
                    }
                }
            }
            """)
    public void save() {
    }

}

As you can see, the snippet of OpenAPI documentation related to a specific endpoint and the HTTP method is attached directly to the HTTP method annotation and is close to the implementation.

Having Open API documentation close to the implementation, makes it easier to maintain loggic and the publicly facing documentation at the same time.

File - Based Approach

In some cases when the amount of documentation inside teh Java files gets out of hand, you can move it into a file. Such files are located in the project and are queried when the Open API documentation needs to be generated by a Maven plugin (see below).

A file name must follow a specific format. Here is an example from teh Pet Store example:

app.controllers.PetController#deletePet-delete.json

Where:

  • app.controllers.PetController - fully qualified controller class name
  • deletePet - action method name
  • delete - the HTTP method name
  • json - format

The advantages of the file approach:

  • Use the power of the IDE to validate the JSON format
  • Remove clutter from controller code

Disadvantage:

  • The API documentation, while structured is not a bit farther away from the Java code.

Mixed Approach

In a mixed approach, you can have some documentation specified in annotation, and some in files. The AW-Mate plugin will take care of that.

Injecting HTML tables into JSON Open API

When writing API documentation, it is often useful to use tables, for instance to list parameters and related conditions.

You can embed tables into JSON with ease by using a @table tag. See the file app.controllers.PetController#deletePet-delete.json. This file has the following:

<@table file='src/main/open-api/delete-pet.html'/>

which is a pointer to the HTML table in a separate file. In case you want to include HTML tables into your API specification, you can do that with this tag. It allows you to take advantage of the HTML and JSON editors.

The screenshot below shows how the HTML table is transformed into a UI by the Swagger Editor:

The AW-Mate plugin will transform the double-quotes from your HTML file into single quotes and also will remove newlines and carriage returns to comply with JSON, but will not do any other processing.

AW-Mate Plugin

JavaLite provides a maven plugin to generate Open API output file from the project artifacts (controller annotations and endpoint files).

The aw-mate Maven plugin (stands for ActiveWeb Mate) is provided by JavaLite.

Configuration of the plugin:

See the pom.xml file:

<plugin>
    <groupId>org.javalite</groupId>
    <artifactId>aw-mate</artifactId>

    <version>3.0-SNAPSHOT</version> <!--  will change, see releases page  -->
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <format>JSON</format>
        <templateFile>src/main/open-api/base.json</templateFile>
        <targetFile>target/classes/openapi.json</targetFile>
        <apiLocation>src/main/open-api</apiLocation>
    </configuration>
</plugin>

where: * templateFile - a file that will be used to inject OpenAPI paths found in code. * targetFile - a file to generate. In this implementation, the file is generated and packaged into the app on the classpath. * apiLocation - an alternative location of the OpenAPI docs. The Open API specs can be placed into GET/POST/PUT.. annotations directly in controllers. If that pollutes to the code, they can be placed into this directory, as long as a name of a file follows the provided pattern.

Plugin goals

The org.javalite:aw-mate plugin has the following goals:

  • routes - prints all existing routes in the given ActiveWeb project.
  • generate - will generate OpenAPI documentation from those routes that include an OpenAPI documentaion.
  • help - prints this message.

The routes goal is the one that is a by product of this plugin, but nonetheless, very useful. Here is the example of running this goal for the Pet Store example:


$mvn aw-mate:routes

...

**
**  STANDARD END POINTS
**
+--------+---------------------+--------------+-----------------------------------+----------------+
| Number | Path                | HTTP Methods | Controller                        | Method         |
+--------+---------------------+--------------+-----------------------------------+----------------+
| 1      | /home/index         | GET          | app.controllers.HomeController    | index()        |
| 2      | /openapi/index      | GET          | app.controllers.OpenapiController | index()        |
| 3      | /pet/add            | POST         | app.controllers.PetController     | add()          |
| 4      | /pet/update         | PUT          | app.controllers.PetController     | update()       |
| 5      | /pet/find_by_status | GET          | app.controllers.PetController     | findByStatus() |
| 6      | /pet/get_pet        | GET          | app.controllers.PetController     | getPet()       |
| 7      | /pet/update_pet     | POST         | app.controllers.PetController     | updatePet()    |
| 8      | /pet/delete_pet     | DELETE       | app.controllers.PetController     | deletePet()    |
+--------+---------------------+--------------+-----------------------------------+----------------+

**
**  CUSTOM END POINTS
**
+--------+-------------------+--------------+-----------------------------------+----------------+
| Number | Path              | HTTP Methods | Controller                        | Method         |
+--------+-------------------+--------------+-----------------------------------+----------------+
| 1      | /openapi          | GET          | app.controllers.OpenapiController | index()        |
| 2      | /pet              | POST         | app.controllers.PetController     | add()          |
| 3      | /pet              | PUT          | app.controllers.PetController     | update()       |
| 4      | /pet/findByStatus | GET          | app.controllers.PetController     | findByStatus() |
| 5      | /pet/{petId}      | GET          | app.controllers.PetController     | getPet()       |
| 6      | /pet/{petId}      | POST         | app.controllers.PetController     | updatePet()    |
| 7      | /pet/{petId}      | DELETE       | app.controllers.PetController     | deletePet()    |
+--------+-------------------+--------------+-----------------------------------+----------------+

This will list all accessible routes that are available for HTTP requests to the app. It makes sense to review all routes here to ensure your app is not exposing anything it should not.

Running the aw-mate plugin:

  1. Ensure you run Java 16 (pre-requisite for )
  2. Generate the OpenAPI documentation:
    mvn aw-mate:generate

Observe this in the output:

Output saved to: target/classes/openapi.json

Note: The plugin is wired into a COMPILE Maven lifecycle, as such, it will be invoked during a normal build cycle.

Viewing OpenAPI live

Since the output of the plugin will be saved to target/classes/openapi.json, it will automatically appear on the classpath of the Webapp.

If you add a controller to your app that looks like this:

public class OpenapiController extends AppController {
    public void index(){
            respond(readResource("/openapi.json")).contentType("application/json");
    }
}

Then you should be able to pull the Open API docs from a live app: http://localhost:8080/openapi.

As you can see, this primitive controller just serves a file on a classpath. Such a resource can be published to the outside so that external tools consume and process it as they see fit.

A further improvement on this controller would be caching the file on the heap if necessary.


How to comment

The comment section below is to discuss documentation on this page.

If you have an issue, or discover bug, please follow instructions on the Support page