Anotaciones y sintaxis de Cloud Endpoints Frameworks

Las anotaciones de Endpoints Frameworks describen la configuración, los métodos, los parámetros y otros detalles importantes de la API que definen las propiedades y el comportamiento del endpoint.

Consulta Escribir y anotar código para obtener información sobre cómo añadir anotaciones mediante un proyecto de Maven. Se proporcionan artefactos de Maven App Engine Cloud Endpoints para crear y compilar una API de backend, así como para generar una biblioteca de cliente a partir de ella.

La anotación que especifica la configuración y el comportamiento de toda la API (afecta a todas las clases expuestas en la API y a todos sus métodos expuestos) es @Api. Todos los métodos públicos, no estáticos y no de puente de una clase anotada con @Api se exponen en la API pública.

Si necesitas una configuración de API especial para un método concreto, puedes usar @ApiMethod para definir la configuración de cada método. Para configurar estas anotaciones, debe definir varios atributos, tal como se muestra en las tablas siguientes.

@Api: anotaciones con ámbito de API

La anotación @Api configura toda la API y se aplica a todos los métodos públicos de una clase a menos que se anule con @ApiMethod.

Para anular una anotación @Api determinada de una clase específica de una API, consulta @ApiClass y @ApiReference.

Importaciones necesarias

Para usar esta función, necesitas la siguiente importación:

import com.google.api.server.spi.config.Api;

Atributos

Atributos @Api Descripción Ejemplo
audiences Obligatorio si tu API requiere autenticación y si admites clientes Android. Para obtener más información, consulte IDs de cliente y audiencias. audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
apiKeyRequired Opcional. Se usa para restringir el acceso a las solicitudes que proporcionan una clave de API. apiKeyRequired = AnnotationBoolean.TRUE
authenticators Obligatorio si tu API se autentica mediante Firebase, Auth0 o cuentas de servicio. Este atributo no es obligatorio si tu API se autentica mediante tokens de ID de Google. Puede definirlo a nivel de API o de método individual. Defínelo como {EspAuthenticator.class} o escribe tu propio autenticador personalizado, tal como se describe en Interface Authenticator. authenticators = {EspAuthenticator.class}
backendRoot Obsoleto. Para publicar tu API desde otra ruta, en el archivo web.xml, cambia url-pattern en la sección EndpointsServlet. <url-pattern>/example-api/*</url-pattern>
canonicalName Se usa para especificar un nombre diferente o más legible para la API en la biblioteca de cliente. Este nombre se usa para generar los nombres de la biblioteca de cliente. La API backend sigue usando el valor especificado en la propiedad name.

Por ejemplo, si tu API tiene el valor name definido como dfaanalytics, puedes usar esta propiedad para especificar el nombre canónico DFA Group Analytics. Las clases de cliente generadas contendrían el nombre DfaGroupAnalytics.

Debes incluir los espacios correspondientes entre los nombres, que se sustituirán por el formato camel case o por guiones bajos.
canonicalName = "DFA Analytics:"n
clientIds Obligatorio si tu API usa autenticación. Lista de IDs de cliente de los clientes que pueden solicitar tokens. Para obtener más información, consulte IDs de cliente y audiencias. clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
defaultVersion Especifica si se usa una versión predeterminada si no se proporciona ninguna en el atributo version. defaultVersion = AnnotationBoolean.TRUE
description Una breve descripción de la API. Se expone en el servicio de descubrimiento para describir tu API y, opcionalmente, también se puede usar para generar documentación. description = "Sample API for a simple game"
documentationLink URL donde los usuarios pueden encontrar documentación sobre esta versión de la API. Esta información se muestra en la sección "Más información" del explorador de APIs, situada en la parte superior de la página, para que los usuarios puedan obtener información sobre tu servicio. documentationLink = "http://link_to/docs"
issuers Las configuraciones personalizadas de la entidad emisora de JWT. issuers = { @ApiIssuer(name = "auth0", issuer = "https://test.auth0.com/authorize", jwksUri = "https://test.auth0.com/.well-known/jwks.json") }
issuerAudiences Audiencias de emisores concretos. issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
limitDefinitions Opcional. Se usa para definir cuotas para tu API. Consulta @ApiLimitMetric. limitDefinitions = { @ApiLimitMetric(name = "read-requests", displayName = "Read requests", limit = 1000)}
name El nombre de la API, que se usa como prefijo de todos los métodos y rutas de la API. El valor de name:
  • Debe empezar por minúsculas
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]*.
Si no especificas name, se usará el valor predeterminado myapi.
name = "foosBall"
namespace Configura el espacio de nombres de los clientes generados. Consulta @ApiNamespace. namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform")
root Obsoleto. Para publicar tu API desde otra ruta, en el archivo web.xml, cambia url-pattern en la sección EndpointsServlet. <url-pattern>/example-api/*</url-pattern>
scopes Si no se proporciona, el valor predeterminado es el ámbito de correo electrónico (https://www.googleapis.com/auth/userinfo.email), que es obligatorio para OAuth. Puedes anular este valor para especificar más permisos de OAuth 2.0 si quieres. Sin embargo, si define más de un ámbito, tenga en cuenta que la comprobación del ámbito se supera si el token se genera para cualquiera de los ámbitos especificados. Para requerir varios permisos, se debe especificar un solo String con un espacio entre cada permiso. Para anular los ámbitos especificados aquí en un método de API concreto, especifica otros ámbitos en la anotación @ApiMethod. scopes = {"ss0", "ss1 and_ss2"}
title El texto que se muestra en el Explorador de APIs como título de tu API y que se expone en los servicios de descubrimiento y de directorio. title = "My Backend API"
transformers Especifica una lista de transformadores personalizados. Ten en cuenta que hay una anotación alternativa (@ApiTransformer) que es preferible. Este atributo se anula con @ApiTransformer. transformers = {BazTransformer.class}
version Especifica tu versión del endpoint. Si no lo proporcionas, se usará el valor predeterminado v1. version = "v2"

@Api anotación de ejemplo

Esta anotación se coloca antes de la definición de la clase:

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

IDs de cliente y audiencias

En la autenticación de OAuth 2.0, se emite un token de OAuth 2.0 para un ID de cliente específico, lo que significa que puedes usar el ID de cliente para restringir el acceso a tus APIs. Cuando registras una aplicación Android en la Google Cloud consola, se crea un ID de cliente para ella. Este ID de cliente es el que solicita un token de OAuth2 a Google con fines de autenticación. Cuando la API de backend está protegida por autenticación, Endpoints envía y abre un token de acceso de OAuth 2.0, extrae el ID de cliente del token y, a continuación, compara el ID con la lista de IDs de cliente aceptables declarada por el backend (la lista clientIds).

Si quieres que tu API de Endpoints autentique a los llamantes, debes proporcionar una lista de clientIds que tengan permiso para solicitar tokens. Esta lista debe incluir todos los IDs de cliente que hayas obtenido a través de la Google Cloud console para tus clientes web o Android. Esto significa que los clientes deben conocerse en el momento de compilar la API. Si especificas una lista vacía, {}, ningún cliente podrá acceder a los métodos protegidos por Auth.

Si usa el atributo clientIds y quiere probar las llamadas autenticadas a su API con Explorador de APIs de Google, debe proporcionar su ID de cliente en la lista de clientIds. El valor que debe usar es com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID.

Acerca de las audiencias

La lista clientIds protege la API de backend frente a clientes no autorizados. Sin embargo, se necesita más protección para proteger a los clientes, de modo que su token de autenticación solo funcione con la API backend prevista. En el caso de los clientes Android, este mecanismo es el atributo audiences, en el que se especifica el ID de cliente de la API backend.

Ten en cuenta que, cuando creas un Google Cloud proyecto de consola, se crea automáticamente un ID de cliente predeterminado y se le asigna un nombre para que lo use el proyecto. Cuando subes tu API backend a App Engine, esta usa ese ID de cliente. Este es el ID de cliente web que se menciona en Autenticación de APIs.

@ApiMethod: anotaciones con ámbito de método

La anotación @ApiMethod se usa para proporcionar una configuración de API diferente a la predeterminada que ofrecen las anotaciones @Api o @ApiClass. Ten en cuenta que esto es opcional: todos los métodos públicos, no estáticos y no de puente de una clase con una anotación @Api se exponen en la API, tengan o no una anotación @ApiMethod.

Los atributos de esta anotación te permiten configurar los detalles de un solo método de API. Si se especifica el mismo atributo en @Api y @ApiMethod, @ApiMethod tiene prioridad.

.

Importaciones necesarias

Para usar esta función, necesitas las siguientes importaciones:

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;

Atributos

Atributos @ApiMethod Descripción Ejemplo
apiKeyRequired Opcional. Se usa para restringir el acceso a las solicitudes que proporcionan una clave de API. apiKeyRequired = AnnotationBoolean.TRUE
audiences Proporcione este valor si quiere anular la configuración de @API. Para obtener más información, consulte IDs de cliente y audiencias. audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
authenticators Obligatorio si tu API se autentica mediante Firebase, Auth0 o cuentas de servicio, y no has definido este atributo a nivel de API. Este atributo no es obligatorio si tu API se autentica mediante tokens de ID de Google. Configúralo como {EspAuthenticator.class} o escribe tu propio autenticador personalizado, tal como se describe en Interface Authenticator. authenticators = {EspAuthenticator.class}
clientIds Lista de IDs de cliente de los clientes que pueden solicitar tokens. Obligatorio si tu API usa autenticación. clientIds = {"1-web-apps.apps.googleusercontent.com", "2-android-apps.apps.googleusercontent.com"}
httpMethod Método HTTP que se va a usar. Si no lo define, se elegirá un valor predeterminado en función del nombre del método. httpMethod = HttpMethod.GET
issuerAudiences Proporcione este valor si quiere anular la configuración de @Api. issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
metricCosts Opcional. Indica que el método tiene un límite de cuota. Asigna la anotación @ApiMetricCost a metricCosts. También debe especificar el atributo limitDefinitions para definir la cuota en la anotación @Api. La anotación @ApiMetricCost tiene los siguientes atributos:
  • name: nombre que ha especificado en la anotación ApiLimitMetric.
  • Coste: un número entero que especifica el coste de cada solicitud. El coste permite que los métodos consuman a ritmos diferentes de la misma cuota. Por ejemplo, si una cuota tiene un límite de 1000 y un coste de 1, la aplicación que llama puede hacer 1000 solicitudes por minuto antes de superar el límite. Con un coste de 2 para la misma cuota, una aplicación de llamadas solo puede hacer 500 solicitudes por minuto antes de superar el límite.
metricCosts = { @ApiMetricCost(name = read-requests", cost = 1) }
name El nombre de este método en la biblioteca de cliente generada. Se le añade automáticamente el prefijo del nombre de la API para crear un nombre único para el método. El valor de name:
  • Debe empezar por minúsculas
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]*.
Si no especificas name, se usará el valor predeterminado myapi.
name = "foosBall.list"
path Ruta de URI que se usará para acceder a este método. Si no lo haces, se usará una ruta predeterminada basada en el nombre del método de Java. Si tienes previsto añadir gestión de APIs, no incluyas una barra al final en la ruta. path = "foos"
scopes Especifica uno o varios ámbitos de OAuth 2.0. Uno de ellos es obligatorio para llamar a este método. Si asignas el valor scopes a un método, se anula el ajuste de la anotación @Api. Si defines más de un ámbito, ten en cuenta que la comprobación del ámbito se supera si el token se genera para cualquiera de los ámbitos especificados. Para requerir varios permisos, especifica un solo String con un espacio entre cada permiso. scopes = {"ss0", "ss1 and_ss2"}

Ejemplo de anotación @ApiMethod

Esta anotación se coloca antes de la definición del método dentro de una clase:

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(
    name = "sayHiUser",
    httpMethod = ApiMethod.HttpMethod.GET)
public MyBean sayHiUser(@Named("name") String name, User user)
    throws OAuthRequestException, IOException {
  MyBean response = new MyBean();
  response.setData("Hi, " + name + "(" + user.getEmail() + ")");

  return response;
}

Los métodos que toman una entidad como parámetro deben usar HttpMethod.POST (para operaciones de inserción) o HttpMethod.PUT (para operaciones de actualización):

@ApiMethod(
    name = "mybean.insert",
    path = "mybean",
    httpMethod = ApiMethod.HttpMethod.POST
)
public void insertFoo(MyBean foo) {
}

@Named

La anotación @Named es obligatoria para todos los parámetros de tipo no entidad que se transfieran a métodos del lado del servidor. Esta anotación indica el nombre del parámetro de la solicitud que se inserta aquí. Un parámetro que no esté anotado con @Named se inserta con todo el objeto de solicitud.

Importaciones necesarias

Para usar esta función, necesitas las siguientes importaciones:

import javax.inject.Named;

En este ejemplo se muestra el uso de @Named:

/** A simple endpoint method that takes a name and says Hi back. */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
  MyBean response = new MyBean();
  response.setData("Hi, " + name);

  return response;
}

donde @Named especifica que solo se inserta el parámetro id en la solicitud.

@ApiLimitMetric

En esta sección se describen las anotaciones necesarias para definir cuotas para tu API. Consulta los pasos necesarios para configurar una cuota.

Asigna la anotación @ApiLimitMetric al atributo limitDefinitions de las anotaciones con ámbito de API. También debes añadir @ApiMetricCost a las anotaciones @ApiMethod de cada método al que quieras aplicar una cuota.

Importaciones necesarias

Para usar esta función, necesitas la siguiente importación:

import com.google.api.server.spi.config.ApiLimitMetric;

Atributos

Atributos de @ApiLimitMetric

Descripción
name Nombre de la cuota. Normalmente, se trata del tipo de solicitud (por ejemplo, "read-requests" o "write-requests") que identifica de forma única la cuota.
displayName El texto que se muestra para identificar la cuota en la pestaña Cuotas de la página Endpoints > Services de la consola Google Cloud . Este texto también se muestra a los consumidores de tu API en la página Cuotas de IAM y administración, y de APIs y servicios. El nombre visible debe tener un máximo de 40 caracteres.
Para que sea más fácil de leer, el texto "por minuto y por proyecto" se añade automáticamente al nombre visible en las páginas Cuotas.
Para mantener la coherencia con los nombres visibles de los servicios de Google que se muestran en las páginas Cuotas que ven los consumidores de tu API, te recomendamos que uses los siguientes nombres visibles:
  • Usa "Solicitudes" cuando solo tengas una métrica.
  • Si tienes varias métricas, cada una de ellas debe describir el tipo de solicitud y contener la palabra "solicitudes" (por ejemplo, "Solicitudes de lectura" o "Solicitudes de escritura").
  • Usa "unidades de cuota" en lugar de "solicitudes" cuando alguno de los costes de esta cuota sea superior a 1.
límite Valor entero que representa el número máximo de solicitudes por minuto por proyecto de consumidor para la cuota.

Ejemplo

limitDefinitions = {
      @ApiLimitMetric(
        name = "read-requests",
        displayName = "Read requests",
        limit = 1000),
      @ApiLimitMetric(
        name = "write-requests",
        displayName = "Write requests",
        limit = 50),
    }

@ApiNamespace

La anotación @ApiNamespace hace que las bibliotecas de cliente generadas tengan el espacio de nombres que especifiques, en lugar de un espacio de nombres predeterminado que se crea durante la generación de la biblioteca de cliente.

De forma predeterminada, si no usas esta anotación, el espacio de nombres que se utiliza es el inverso de your-project-id.appspot.com. Es decir, la ruta del paquete es com.appspot.your-project-id.yourApi.

Puedes cambiar el espacio de nombres predeterminado proporcionando la anotación @ApiNamespace dentro de la anotación @Api:

/** An endpoint class we are exposing. */
@Api(name = "myApi",
    version = "v1",
    namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",
        ownerName = "helloworld.example.com",
        packagePath = ""))

Asigna el atributo ownerDomain al dominio de tu empresa y ownerName al nombre de tu empresa (por ejemplo, your-company.com). La inversa de ownerDomain se usa para la ruta del paquete: com.your-company.yourApi.

También puede usar el atributo packagePath para acotar aún más la búsqueda. Por ejemplo, si asignas el valor cloud a packagePath, la ruta del paquete que se usa en la biblioteca de cliente es com.your-company.cloud.yourApi. Puedes añadir más valores a la ruta del paquete proporcionando el delimitador /: packagePath="cloud/platform".

@Nullable

Esta anotación indica que un parámetro de un método es opcional (y, por lo tanto, un parámetro de consulta). @Nullable solo se puede usar con parámetros @Named.

@ApiClass

En una API de varias clases, puedes usar @ApiClass para especificar diferentes propiedades de una clase determinada y anular las propiedades equivalentes de la configuración @Api. Consulta la sección Usar @ApiClass en propiedades que pueden variar entre clases para ver una descripción completa de esta anotación.

@ApiReference

En una API de varias clases, puedes usar @ApiReference para proporcionar un método alternativo de herencia de anotaciones. Consulta la sección Usar la herencia de @ApiReference para ver una descripción completa de esta anotación.

@ApiResourceProperty

@ApiResourceProperty proporciona control sobre cómo se exponen las propiedades de los recursos en la API. Puedes usarlo en un método getter o setter de una propiedad para omitir la propiedad de un recurso de API. También puedes usarlo en el propio campo, si es privado, para exponerlo en la API. También puedes usar esta anotación para cambiar el nombre de una propiedad en un recurso de API.

Importaciones necesarias

Para usar esta función, necesitas las siguientes importaciones:

import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.AnnotationBoolean;

Atributos

Atributos @ApiResourceProperty Descripción Ejemplo
ignored Si se asigna el valor AnnotationBoolean.TRUE, se omite la propiedad. Si no se especifica o se le asigna el valor AnnotationBoolean.FALSE, la propiedad no se omite. @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
name Si se proporciona, especifica el nombre de la propiedad que se va a exponer en la API. @ApiResourceProperty(name = "baz")

Clase de ejemplo con @ApiResourceProperty

En el siguiente fragmento se muestra una clase con getters de propiedades anotados con @ApiResourceProperty:


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();
}

En el fragmento de código anterior, se aplica @ApiResourceProperty al getter getBin de la propiedad bin. El atributo ignored indica a Endpoints Frameworks que omita esta propiedad en el recurso de la API.

@ApiResourceProperty también se aplica al campo privado visible, que no tiene ningún método getter ni setter. Si usas esta anotación, el campo se expondrá como una propiedad en el recurso de la API.

En el mismo fragmento, @ApiResourceProperty también se aplica a otro getter, getFoobar, que devuelve un valor de propiedad para la propiedad foobar. El atributo name de esta anotación indica a Endpoints Frameworks que cambie el nombre de la propiedad en el recurso de la API. El valor de la propiedad no cambia.

En el fragmento de ejemplo anterior, la representación JSON de un objeto Resp tiene un aspecto similar al siguiente:

{"baz": "foobar", "visible": "nothidden"}

@ApiTransformer

La anotación @ApiTransformer personaliza la forma en que se expone un tipo en Endpoints mediante la transformación a otro tipo y desde otro tipo. (El transformador especificado debe ser una implementación de com.google.api.server.spi.config.Transformer).

Usar la anotación @ApiTransformer en una clase es la forma recomendada de especificar un transformador. Sin embargo, también puede especificar su transformador personalizado en el atributo transformer de la anotación @Api.

Importaciones necesarias

Para usar esta función, necesitas la siguiente importación:

import com.google.api.server.spi.config.ApiTransformer;

Clase de ejemplo con @ApiTransformer

En el siguiente fragmento se muestra una clase anotada con @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;
  }
}

Esta clase se transforma con la clase BarTransformer.

Clase de transformador de Endpoints de ejemplo

El siguiente fragmento muestra una clase de transformador de ejemplo llamada BarTransformer. Este es el transformador al que hace referencia @ApiTransformer en el fragmento anterior:

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]));
  }
}

Si hay un objeto con una propiedad bar de tipo Bar, sin el transformador anterior, el objeto se representa de la siguiente manera:

{"bar": {"x": 1, "y": 2}}

Con el transformador, el objeto se representa de la siguiente manera:

{"bar": "1,2"}