Multiclass APIs
Using @ApiClass for Properties that Can Differ Between Classes
Annotation Inheritance
Using Java Inheritance
Using @ApiReference Inheritance
Overriding Inherited Configuration
Inheriting @ApiMethod Annotations
Inheritance and Precedence Rules
Common Use Cases for Annotation Inheritance
If a single API is particularly complex, you may wish to implement it from multiple Java classes. To make different classes part of the same API, simply give each class the same name and version strings in their @Api annotation. For example, the following two classes will both be part of the tictactoe API:
The API configuration is specified through the @Api annotation properties. However, for multiple classes in the same API, the @Api requirements extend beyond simply having the same name and version strings in the @Api annotation for each class. In fact, your backend API will not work if there are any differences in the API configurations specified in the classes' @Api properties. Any difference in the @Api properties for classes in a multiclass API result in an "ambiguous" API configuration, which will not work in Endpoints.
Note: for a way to specify different properties for classes without using @Api properties, see Using @ApiClass for Properties that Can Differ Between Classes.
There are several ways to create a unambiguous multiclass API:
Manually ensure that all classes in a single API have the exact same
@Apiannotation properties. We won't describe this further, since it is self-evident.Use annotation inheritance through Java inheritance. In this inheritance, all classes in a single API inherit the same API configuration from a common
@Api-annotated base class.Use annotation inheritance through the
@ApiReferenceannotation on all classes in a single API to have them reference the same API configuration from a common @Api-annotated class.
Using @ApiClass for Properties that Can Differ Between Classes
While all properties in the @Api annotation must match for all classes in an API, you can additionally use the @ApiClass annotation to provides properties that do not need to be exactly the same between classes. For example:
where TicTacToeA limits access using a whitelist of client IDs containing the allowed client ID, and TicTacToeB does not limit acccess.
All properties provided by the @ApiClass annotation have an equivalent property in the @Api annotation. Note that the @Api equivalent property acts as the API-wide default. If there is an API-wide default for that same property, specified in @Api, the class-specific @ApiClass property will override the API-wide default.
The following examples illustrate the overriding of @Api properties by the class specific @ApiClass equivalents:
Annotation Inheritance
The @Api and @ApiClass annotation properties can be inherited from from other classes, and individual properties can be overridden either through Java Inheritance or @ApiReference inheritance
Using Java Inheritance
A class that extends another class with @Api or @ApiClass annotations will behave as if annotated with the same properties. For example:
Annotations are only inherited through Java subclassing, not through interface implementation. For example:
As a result, there is no support for any sort of multiple inheritance of Endpoints annotations.
Inheritance works for @ApiClass too:
where TicTacToeBoards inherits the resource property value boards from BoardsBase, thus overriding the resource property setting (scores) in its @Api annotation. Remember that if any class has specified the resource property in the @Api annotation, all of the classes need to specify that same setting in the @Api annotation; this inheritance technique lets you override that @Api property.
Using @ApiReference Inheritance
The @ApiReference annotation provides an alternate way to specify annotation inheritance. A class that uses @ApiReference to specify another class with @Api or @ApiClass annotations will behave as if annotated with the same properties. For example:
If both Java inheritance and the @ApiReference are used, the annotations will inherit through the @ApiReference annotation only. @Api and @ApiClass annotations on the class inherited through Java inheritance will be ignored. For example:
Overriding Inherited Configuration
Whether inheriting configuration using Java inheritance or @ApiReference, the inherited configuration can be overridden using a new @Api or @ApiClass annotation. Only configuration properties specified in the new annotation are overridden. Properties that are unspecified are still inherited. For example:
Overriding inheritance works for @ApiClass too:
Overriding also works when inheriting through @ApiReference:
Inheriting @ApiMethod Annotations
The @ApiMethod annotation can be inherited from overridden methods. For example:
Similarly to @Api and @ApiClass annotation inheritance, if multiple methods overriding each other have @ApiMethod annotations, individual properties can be overridden. For example:
There is no @ApiReference annotation or equivalent for methods, so @ApiMethod is always inherited through Java inheritance, not through @ApiReference.
Inheritance and Precedence Rules
To synopsize the preceding discussion, the follow table shows the inheritance rules and order of precedence.
Annotation/inheritance | Rule |
|---|---|
| Must be identical for all classes. |
| Specified for a class to override |
Java inheritance | Class inherits |
| Class inherits |
Using | Class inherits the |
Common Use Cases for Annotation Inheritance
The following are examples of the typical use cases for inheritance:
For API versioning:
For multiclass APIs:
For testing different versions of the same API:
where someMethod might return pre-determined responses, avoid calls with side-effects, skip a network or datastore request, and so forth.