See the backend API tutorial for a recommended way of adding annotations using a Maven project. Maven App Engine Endpoints artifacts are provided to make it easy to create and build a backend API, and generate a client library from it. Alternatively, you could use the Google Plugin for Eclipse(GPE).
Endpoint annotations describe API configuration, methods, parameters, and
other vital details that define the properties and behavior of the Endpoint.
The annotation that specifies configuration and behavior across the entire API
(affecting all the classes exposed in the API and all their exposed methods) is
@Api. All public, non-static, non-bridge methods of a class annotated with
@Api will be exposed in the public API.
If you need special API configuration for a particular method, you can optionally use @ApiMethod to set configuration on a per method basis. You configure these annotations by setting various attributes, as shown in the tables below.
@Api: API-Scoped Annotations
The annotation @Api
is used to configure the whole API, and apply to all public methods of a class
unless overridden by @ApiMethod.
(To override a given @Api annotation for a specific class within
an API, see @ApiClass and @ApiReference.)
Required Imports
To use this feature, you need the following import:
import com.google.api.server.spi.config.Api;
Attributes
| @Api Attributes | Description | Example |
|---|---|---|
audiences |
Required if your API requires authentication and if you are supporting Android clients. For more information, see Client IDs and Audiences. | audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"} |
backendRoot |
The root URL used for method calls to backend instances. If not supplied, the default https://your_app_id.appspot.com/_ah/spi is used. |
backendRoot = "https://example.appspot.com/_ah/spi" |
canonicalName |
Optional. Used to specify a different or more readable name for the API in the client library. This name is used to generate the names in the client library; the backend API continues to use the value specified in the name property.For example, if your API has the name set to dfaanalytics, you could use this property to specify a canonical name of DFA Group Analytics; the generated client classes would then contain the name DfaGroupAnalytics.You should include the relevant spaces between the names as shown above; these will be replaced by the appropriate camel casing or underscores. |
canonical_name='DFA Analytics' |
clientIds |
Required if your API uses authentication. List of client IDs for clients allowed to request tokens. For more information, see Client IDs and Audiences. | clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"} |
defaultVersion |
Specifies whether a default version is used if none is supplied in the version attribute. |
defaultVersion = AnnotationBoolean.TRUE |
description |
A short description of the API. This is exposed in the discovery service to describe your API, and may optionally also be used to generate documentation. | description = "Sample API for a simple game" |
documentationLink |
Optional. The URL where users can find documentation about this version of the API. This will be surfaced in the API Explorer "Learn More" highlight at the top of the API Explorer page and also in the GPE plugin to allow users to learn about your service. | http://link_to/docs |
name |
The name of the API, which is used as the prefix for all of the API's methods and paths. The name value:
name, the default myapi is used. |
name = "foosBall" |
namespace |
Configures namespacing for generated clients. See @ApiNamespace. | namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform") |
root |
The frontend root URL under which your API methods are exposed for. If not supplied, the default https://your_app_id.appspot.com/_ah/api is used. |
root = "https://example.appspot.com/_ah/api" |
scopes |
If not supplied, the default is the email scope (https://www.googleapis.com/auth/userinfo.email), which is required for OAuth. You can override this to specify more OAuth 2.0 scopes if you wish. However, if you do define more than one scope, note that the scope check will pass if the token is minted for any of the specified scopes. To override the scopes specified here for a particular API method, specify different scopes in the @ApiMethod annotation. |
scopes = {"ss0", "ss1"} |
title |
Optional. The text displayed in API Explorer as the title of your API, and exposed in the discovery and the directory services. | title=My Backend API |
transformers |
Specifies a list of custom transformers. Note that there is an alternative annotation (@ApiTransformer) that is preferable. This attribute is overridden by @ApiTransformer. |
@Api(name = "test", transformers = {BazTransformer.class}) |
version |
Specifies your Endpoint’s version. If you don't supply this, the default v1 is used. |
version = "v2" |
Sample @Api Annotation
This annotation is placed above the class definition:
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiAuth;
@Api(
version = "v1",
description = "Sample API",
scopes = {"ss0", "ss1"},
audiences = {"aa0", "aa1"},
clientIds = {"cc0", "cc1"},
defaultVersion = AnnotationBoolean.TRUE
)
Client IDs and Audiences
In an OAuth2 authentication, an OAuth2 token is issued to a specific client ID,
which means that this client ID can be used for restricting access to your APIs.
When you register an iOS or Android application in the Google Developers Console,
you create a client ID for it. This client ID is the one requesting an OAuth2
token from Google for authentication purposes. When the backend API is protected
by auth, an OAuth2 access token is sent and opened by Google Cloud Endpoints,
the client ID is extracted from the token, and then the ID is compared to the
backend's declared acceptable Client ID list (the clientIds list).
So, if you want your Endpoints API to authenticate callers, you need to supply
a list of clientIds that are allowed to request tokens
that can be used with your application. This list should consist of the all
client IDs you have obtained through the Developers Console for your
web, Android, or iOS clients. (This means that the clients must
be known at API build-time.) If you specify an empty list, [], then no clients
can access the methods protected by Auth.
If you use the clientIds attribute and you want to test authenticated calls to
your API using the Google API Explorer, you must supply its client ID in the
list of clientIds: the value to use is
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID.
About Audiences
The clientIds list protects the backend API from unauthorized clients. But
further protection is needed to protect the clients, so that their auth token
will work only for the intended backend API. For Android clients, this mechanism
is the audiences attribute, in which you specify the client ID of the
backend API.
Note that when you create a Google Developers Console Project, a default client ID is automatically created and named for use by the project. When you upload your backend API into App Engine, it uses that client ID. This is the web client ID mentioned in the backend API auth docs and the backend tutorial docs.
@ApiMethod: Method-Scoped Annotations
The annotation @ApiMethod
is used to supply a different API configuration than the defaults provided by the
@Api or @ApiClass annotations. Note that this is optional: all public, non
static, non bridge methods in a class with an @Api annotation are exposed in the API, whether they have an
@ApiMethod annotation or not.
Attributes within this annotation allow you to configure details
of a single API method. If the same attribute is specified in @Api and
@ApiMethod, @ApiMethod overrides.
Required Imports
To use this feature, you need the following imports:
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;
Attributes
| @ApiMethod Attributes | Description | Example |
|---|---|---|
name |
The name for this method in the generated client library. This is automatically prefixed with your API name to create a unique name for the method. The name value:
name, the default myapi is used. |
name = "foosBall.list" |
path |
The URI path to use to access this method. If you don't set this, a default path is used based on the Java method name. | path = "foos" |
httpMethod |
The HTTP method to use. If you don't set this, a default is chosen based on the name of the method. | httpMethod = HttpMethod.GET |
scopes |
Specify one or more OAuth 2.0 scopes, one of which is required for calling this method. If you set scopes for a method, it overrides the setting in the @Api annotation. |
scopes = {"ss0", "ss1"} |
audiences |
Required if your API requires authentication and if you are supporting Android clients. For more information, see Client IDs and Audiences. | audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"} |
clientIds |
List of client IDs for clients allowed to request tokens. Required if your API uses authentication. | clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"} |
Sample @ApiMethod Annotation
This annotation is placed above the method definition inside a class:
import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;
@ApiMethod(
name = "foos.list",
path = "foos",
httpMethod = HttpMethod.GET,
scopes = {"s0", "s1"},
audiences = {"a0", "a1"},
clientIds = {"c0", "c1"}
)
public List<Foo> listFoos() {
return null;
}
Methods that take an entity as a parameter should use HttpMethod.POST
(for insert operations) or HttpMethod.PUT (for update operations):
@ApiMethod(
name = "foos.insert",
path = "foos",
httpMethod = HttpMethod.POST
)
public void insertFoo(Foo foo) {
}
@Named
The @Named annotation is required for all non-entity type parameters passed to
server-side methods. This annotation indicates the name of the parameter in the
request that gets injected here. A parameter that is not annotated with @Named
is injected with the whole request object.
Required Imports
To use this feature, you need the following imports:
import javax.inject.Named;
This sample shows the use of @Named:
@ApiMethod(
name = "foos.remove",
path = "foos/{id}",
httpMethod = HttpMethod.DELETE
)
public void removeFoo(@Named("id") String id) {
}
where @Named specifies that only the id parameter is injected
in the request.
@ApiNamespace
The @ApiNamespace annotation causes the generated client libraries to have the namespace you specify, rather than a default constructed during client library generation.
By default, if you don't use this annotation, the namespace that is used is the
reverse of your-project-id.appspot.com. That is, the package path will be
com.appspot.your-project-id.yourApi.
You can change the default namespace by supplying the @ApiNamespace annotation
within the @Api annotation:
@Api(
name = "tictactoe",
version = "v1",
namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform")
)
with the ownerDomain attribute set to your own company domain and ownerName
set to your company name, for example, your-company.com. The reverse of the
ownerDomain will then be used for the package path: com.your-company.yourApi.
You can optionally use the packagePath attribute to provide further scoping. For
example, by setting packagePath to cloud, the package path used in the
client library will be com.your-company.cloud.yourApi. You can add more values
to the package path by supplying the delimiter /: packagePath="cloud/platform".
@Nullable
This annotation indicates that a parameter of a method is optional (and
therefore a query parameter). @Nullable may only be used with @Named
parameters.
@ApiClass
In a multiclass API, used to
specify different properties for a given class, overriding equivalent properties
in the @Api configuration. See
Using @ApiClass for Properties that Can Differ Between Classes for a complete description of this annotation.
@ApiReference
In a multiclass API, used to supply an alternate method of annotation inheritance. See Using @ApiReference Inheritance for a complete description of this annotation.
@ApiResourceProperty
@ApiResourceProperty provides more control over how resource properties are exposed in the API. You can use it on a property getter or setter to omit the property from an API resource. You can also use it on the field itself, if the field is private, to expose it in the API. You can also use this annotation to change the name of a property in an API resource.
Required Imports
To use this feature, you need the following imports:
import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.AnnotationBoolean;
Attributes
| @ApiResourceProperty Attributes | Description | Example |
|---|---|---|
ignored |
If set to AnnotationBoolean.TRUE, omits the property. If not specified or set to AnnotationBoolean.FALSE, the property is not omitted. |
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE) |
name |
If supplied, it specifies the property name to be exposed in the API. | @ApiResourceProperty(name = "baz") |
Sample Class with @ApiResourceProperty
The following snippet shows a class with property getters annotated with
@ApiResourceProperty:
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.AnnotationBoolean;
@Api(name = "myendpoint")
public class MyEndpoint {
class Resp {
private String foobar = "foobar";
private String bin = "bin";
@ApiResourceProperty
private String visible = "nothidden";
@ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
public String getBin() {
return bin;
}
public void setBin(String bin) {
this.bin = bin;
}
@ApiResourceProperty(name = "baz")
public String getFoobar() {
return foobar;
}
public void setFoobar(String foobar) {
this.foobar = foobar;
}
}
public Resp getResp() {
return new Resp();
}
}
In the code snippet above, @ApiResourceProperty is applied
to the getBin getter for the bin property, with the ignored attribute
setting telling the Endpoints framework to omit this property in the API
resource.
@ApiResourceProperty is also applied to the private field visible, which
has no getter or setter. Using this annotation will expose this field as a
property in the API resource.
In the same snippet, @ApiResourceProperty is also applied
to a different getter, getFoobar, which returns a property value
for the foobar property. The name attribute in this
annotation tells the Endpoints framework to change the property name in the API
resource. The property value itself is unchanged.
In the above example snippet, the JSON representation of a Resp object would
look something like this:
{"baz": "foobar", "visible": "nothidden"}
@ApiTransformer
The @ApiTransformer
annotation customizes how a type is exposed in Endpoints through transformation
to and from another type. (The transformer specified
must be an implementation of com.google.api.server.spi.config.Transformer.)
Using the @ApiTransformer annotation on a class is the preferred way to specify
a transformer. However, you could alternatively specify your custom
transformer in the transformer attribute of the
@Api annotation.
Required imports
To use this feature, you need this import:
import com.google.api.server.spi.config.ApiTransformer;
Sample class with @ApiTransformer
The following snippet shows a class annotated with @ApiTransformer:
import com.google.api.server.spi.config.ApiTransformer;
@ApiTransformer(BarTransformer.class)
public class Bar {
private final int x;
private final int y;
public Bar(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
This class will be transformed by the BarTransformer class.
Sample Endpoints transformer class
The following snippet shows a sample transformer class named BarTransformer.
This is the transformer referenced by @ApiTransformer in the preceding snippet:
import com.google.api.server.spi.config.Transformer;
public class BarTransformer implements Transformer<Bar, String> {
public String transformTo(Bar in) {
return in.getX() + "," + in.getY();
}
public Bar transformFrom(String in) {
String[] xy = in.split(",");
return new Bar(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
}
}
Assuming we have an object with a property bar of type Bar, without the
above transformer, the object would be represented as:
{"bar": {"x": 1, "y": 2}}
With the transformer, the object is represented as:
{"bar": "1,2"}