Custom Annotations

One Network builds on the JAX-RS specification annotations by providing a set of additional custom annotations for documenting RESTful web services.

Table 6.2. Custom Annotations

Annotation

RetentionPolicy

Target

ModulePublic

SOURCE

METHOD

RestParam

SOURCE

PARAMETER

RestObjectProperty

SOURCE

METHOD

RestRequest

SOURCE

METHOD

RestResponse

SOURCE

METHOD

RestEnumeration

SOURCE

PACKAGE

RestException

RUNTIME

TYPE

RestFooter

SOURCE

PACKAGE

We will explore each custom annotation in detail in the sections below.

ModulePublic

ModulePublic is a marker annotation. To make your API public, annotate your webservice with@ModulePublic.

Usage:

@ModulePublic
@GET
public JSONObject getBook(@QueryParam("SysId") Long sysId) {
}

Documentation is generated only for Public APIs. Any webservice which is not annotated with @ModulePublic is treated as a private API and will not be documented.

RestParam

RestParam is an annotation that works in conjunction with the @QueryParam or @PathParam or @FormParam annotations of the JAX-RS specification. This annotation provides attributes, shown below, to include additional details about the parameters for documenting.

  • description: Provides a description of the parameter.

  • required: Boolean value representing if this parameter is required or optional. (This is not enforced at runtime, it is purely documentational.)

  • sampleValue: A sample value of the parameter.

Usage:

@ModulePublic
@GET
public JSONObject getBook(@QueryParam("SysId") @RestParam(description="Unique identifier for a book", required=true, sampleValue="10000") Long sysId) {
}
@ModulePublic
@GET
@Path("{SysId}")
public JSONObject getBook(@PathParam("SysId") @RestParam(description="Unique identifier for a book", required=true, sampleValue="10000") Long sysId) {
}
@ModulePublic
@POST
public JSONObject getBook(@FormParam("SysId") @RestParam(description="Unique identifier for a book", required=true, sampleValue="10000") Long sysId) {
}


@RestParam cannot be used alone. It has to be used in conjunction with @QueryParam or @PathParam or @FormParam annotations.


RestObjectProperty

RestObjectProperty is used to document a property within a JSON sent in a request body or returned in a response body. It has the following attributes:

  • name: Name of the property.

  • description: Provides a description about the parameter.

  • required: Boolean value. When used with @RestRequest, it specifies whether this property is required or optional in the request body. When used with @RestResponse, it specifies wheth er this property is always included or not in the response body. (This is not enforced at runtime, it is purely documentational.)

  • sampleValue: A sample value of the parameter.

Usage:

@ModulePublic
@GET
@Path("{SysId}")
@RestResponse(description="Returns a book",
properties= {
@RestObjectProperty(name="SysId", description="Unique identifier for a book", required=true, sampleValue="10000"),
@RestObjectProperty(name="Title", description="Title of the book", required=true, sampleValue="Learning Platform")}
)
public JSONObject getBook(@PathParam("SysId") @RestParam(description="Unique identifier for a book", required=true, sampleValue="10000") Long sysId) {
}
@ModulePublic
@POST
@RestRequest(description="Create a book",
properties= {
@RestObjectProperty(name="Title", description="Title of the book", required=true, sampleValue="Learning Platform")}
)
public JSONObject createBook(JSONObject book) {
}


@RestObjectProperty cannot be used alone. It has to be used in inside @RestRequest or @RestResponse annotations.

RestRequest

RestRequest is used to document request body. A collection of @RestObjectProperty annotations can be used inside a @RestRequest. It has the following attributes:

  • description: Provides a description about the parameter.

  • sampleValue: A sample value of the parameter.

  • RestObjectProperty[]: A collection of RestObjectProperty annotations to document request body properties.

Usage:

@ModulePublic
@POST
@RestRequest(description="Create a book",
properties= {
@RestObjectProperty(name="Title", description="Title of the book", required=true, sampleValue="Learning Platform"),
@RestObjectProperty(name="Author", description="Author of the book", required=false, sampleValue="Greg Merrill")}
)
public JSONObject createBook(JSONObject book) {
}

RestResponse

RestResponse is used to document response body. A collection of @RestObjectProperty annotations can be used inside a @RestResponse. It has the following attributes:

  • description: Provides a description about the parameter.

  • sampleValue: A sample value of the parameter.

  • RestObjectProperty[]: A collection of RestObjectProperty annotations to document response body properties.

Usage:

@ModulePublic
@GET
@RestResponse(description="Get a book", sampleValue="{SysId:10000, Title:Learning Platform, Author:Greg Merrill}"
properties= {
@RestObjectProperty(name="SysId", description="Unique identifier of the book", required=true, sampleValue="10000"),
@RestObjectProperty(name="Title", description="Title of the book", required=true, sampleValue="Learning Platform"),
@RestObjectProperty(name="Author", description="Author of the book", required=true, sampleValue="Greg Merrill")}
)
public JSONObject getBook(@QueryParam("SysId") @RestParam(description="Unique identifier for a book", required=true, sampleValue="10000") Long sysId) {
}

RestEnumeration

RestEnumeration is used to document all enumerations used in the module. This annotation should be used only on the package-info.java file in the root folder of rest webservices (/rest). It takes a collection of fully qualified names of the enumerations.

Usage:

/**
* Web services for creating and retrieving books
*/
@com.onenetwork.platform.integ.rest.annotation.RestEnumeration(enums={"com.mybooks.model.enums.GenreEnum"})
package com.mybooks.rest;
RestException

RestException

RestException is used to document all exceptions that can be thrown by each web service. This annotation works differently when compared with the above discussed annotations.

@RestException should be used only on Exception classes, not on a REST resource. A resource that throws an exception which is annotated with @RestException will inherit the documentation from the Exception class.

It has the following properties:

  • errorCode: Provides an error code for the exception.

  • message: Provides an detailed message of the exception.

We will illustrate with an example.

We create an exception, called BookNotFoundException, which is thrown when the requested book is not found. We annotate this exception with @RestException annotation.

package com.mybooks.rest;
import com.onenetwork.platform.integ.rest.annotation.RestException;
@RestException(errorCode="BookNotFound", message="Failed to retrieve the Book which corresponds to the provided id")
public class BookNotFoundException extends RuntimeException{
}


Now, we create a REST resource, shown below, which throws the BookNotFoundException. The documentation processor generates the error response documentation of this web service using errorCode and message defined in the BookNotFoundException's @RestException annotation.

@ModulePublic
@GET
public JSONObject getBook(@QueryParam("SysId") @RestParam(description="Book Identifier", required=true, sampleValue="10000") Long sysId)
throws BookNotFoundException{
// do something
}


Also, since @RestException annotation has a RetentionPolicy of RUNTIME, we will provide a response to the client during run time with errorCode and message defined on the BookNotFoundException if the web service throws BookNotFoundException.

@ModulePublic
@GET
public JSONObject getBook(@QueryParam("SysId") @RestParam(description="Book Identifier", required=true, sampleValue="10000") Long sysId)
throws BookNotFoundException{
try {
// do something
} catch(RuntimeException ex) {
throw new BookNotFoundException();
}
}


You can also use inheritance for retrieving errorCode and message. Let's say a REST resource throws an exception, FictionBookNotFoundException, which is a sub class of BookNotFoundException. In this case, FictionBookNotFoundException is not annotated with @RestException annotation, but BookNotFoundException has the @RestException annotation. As a result, then errorCode and message of the error response is retrieved from the BookNotFoundException.

package com.mybooks.rest;
import com.onenetwork.platform.integ.rest.annotation.RestException;
public class FictionBookNotFoundException extends BookNotFoundException{
}


RestFooter

RestFooter is used to append additional text (including html markup) at the end of the generated documentation below the Enumerations section. (If there are no enumerations, then the text will be appended at the end of the web services section.) This annotation should be used only on the package-info.java file in the root folder of rest webservices (/rest). It takes a collection of file names that contain the text to be appended. The file name should provide the location of a file relative to the module's root directory. The order of appending file content depends on the order in which file names are declared on the annotation.

Usage:

/**
* Web services for creating and retrieving books
*/
@com.onenetwork.platform.integ.rest.annotation.RestEnumeration(enums={"com.mybooks.model.enums.GenreEnum"})
@com.onenetwork.platform.integ.rest.annotation.RestFooter(filenames={"docs/RestFooter.txt", "docs/Book.html"})
package com.mybooks.rest;


Note that if the file name provided in the RestFooter annotation is not found, a warning is displayed, as shown in the image below, in the ant console and the documentation is still generated.