Anotaciones y sintaxis de Cloud Endpoints Frameworks

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

Consulta Escribir código y agregar anotaciones para obtener más información sobre cómo agregar anotaciones mediante el uso de un proyecto de Maven. Los artefactos de Cloud Endpoints de App Engine de Maven se proporcionan a fin de crear y compilar una API de backend y generar una biblioteca cliente a partir de ella.

La anotación que especifica la configuración y el comportamiento de toda la API (que afecta a todas las clases expuestas en la API, así como a todos sus métodos expuestos) es @Api. Todos los métodos públicos, no estáticos ni puentes 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 en particular, puede usar @ApiMethod de forma opcional a fin de establecer la configuración por método. Puedes configurar estas anotaciones mediante la configuración de varios atributos, como se muestra en las tablas siguientes.

@Api: anotaciones con alcance de API

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

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

Importaciones requeridas

Para usar esta característica, necesitas la importación siguiente:

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

Atributos

Atributos de @Api Descripción Ejemplo
audiences Obligatorio si tu API necesita autenticación y si tienes compatibilidad con clientes Android. Consulta ID de cliente y públicos para obtener más información. 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 realiza las autenticaciones con Firebase, Auth0 o cuentas de servicio. Este atributo no es obligatorio si tu API realiza las autenticaciones con tokens de ID de Google. Puedes configurar esto al nivel de la API o de los métodos individuales. Puedes configurarla en {EspAuthenticator.class}, o puedes escribir tu propio autenticador personalizado, como se describe en Autenticador de interfaz. authenticators = {EspAuthenticator.class}
backendRoot Obsoleto Para entregar tu API desde una ruta diferente, en tu archivo web.xml, cambia el url-pattern en la sección EndpointsServlet. <url-pattern>/example-api/*</url-pattern>
canonicalName Se usa con el objetivo de especificar un nombre diferente o más simple para la API en la biblioteca cliente. Este nombre se usa para generar los nombres en la biblioteca cliente; la API de backend sigue usando el valor especificado en la propiedad name.

Por ejemplo, si tu API tiene el name establecido en dfaanalytics , podrías usar esta propiedad para especificar un nombre canónico de DFA Group Analytics; por su lado, las clases cliente generadas contendrán el nombre DfaGroupAnalytics.

Debes incluir los espacios relevantes entre los nombres; estos se reemplazarán por guiones bajos o mayúsculas y minúsculas según corresponda.
canonicalName = "DFA Analytics:"n
clientIds Obligatorio si tu API usa autenticación. Lista de los ID de cliente de aquellos que pueden solicitar tokens. Consulta ID de cliente y públicos para obtener más información. 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. Esto 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 La URL en la que los usuarios pueden buscar documentación sobre esta versión de la API. Esto aparece en el elemento destacado “Más información” del Explorador de API en la parte superior de la página para permitir a los usuarios aprender más sobre tu servicio. documentationLink = "http://link_to/docs"
issuers Las configuraciones personalizadas del emisor de JWT. issuers = { @ApiIssuer(name = "auth0", issuer = "https://test.auth0.com/authorize", jwksUri = "https://test.auth0.com/.well-known/jwks.json") }
issuerAudiences Públicos para los emisores individuales. issuerAudiences = { @ApiIssuerAudience(name = "auth0", audiences = {"aud-1.auth0.com", "aud-2.auth0.com"}) }
limitDefinitions Opcional. Se usa para definir las quotas de tu API. Consulta @ApiLimitMetric. limitDefinitions = { @ApiLimitMetric(name = "read-requests", displayName = "Read requests", limit = 1000)}
name El nombre de la API, que se usa como un prefijo para todos los métodos y rutas de la API. El valor name:
  • Debe comenzar con minúscula.
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]*.
Si no especificas name, se usa el myapi predeterminado.
name = "foosBall"
namespace Configura el espacio de nombres para clientes generados. Consulta @ApiNamespace. namespace=@ApiNamespace(ownerDomain="your-company.com", ownerName="YourCo", packagePath="cloud/platform")
root Obsoleto Para entregar tu API desde una ruta diferente, en tu archivo web.xml, cambia el url-pattern en la sección EndpointsServlet. <url-pattern>/example-api/*</url-pattern>
scopes Si no se proporciona, la opción predeterminada es el alcance de correo electrónico (https://www.googleapis.com/auth/userinfo.email), que es obligatorio para OAuth. Si lo deseas, puedes anular esto para especificar más alcances de OAuth 2.0. Sin embargo, si defines más de un alcance, ten en cuenta que la verificación del alcance se aprueba si el token se emite para cualquier alcance especificado. Para requerir varios alcances, se debe especificar un único String con un espacio entre cada alcance. Especifica alcances diferentes en la anotación @ApiMethod a fin de anular los alcances establecidos aquí para un método de API en particular. scopes = {"ss0", "ss1 and_ss2"}
title El texto que se muestra como título de tu API en el explorador de 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 existe una anotación alternativa (@ApiTransformer) que es preferible. @ApiTransformer anula este atributo. transformers = {BazTransformer.class}
version Especifica tu versión de extremo. Si no lo proporcionas, se usa el valor predeterminado v1. version = "v2"

Anotación @Api de muestra

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

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

ID de cliente y públicos

Para la autenticación OAuth2, se emite un token de OAuth2 a un ID de cliente específico, lo que significa que este ID de cliente puede restringir el acceso a tus API. Cuando registras una aplicación para Android en la consola de Google Cloud, creas un ID de cliente para ella. Este ID de cliente es el que solicita un token de OAuth2 desde Google con fines de autenticación. Cuando la autenticación protege a la API de backend, se envía un token de acceso de OAuth2 y Endpoints lo abre. Luego, se extrae el ID de cliente desde el token y se compara con la lista de ID de cliente declarada como aceptada por el backend (la lista clientIds).

Si quieres que tu API de Endpoints realice autenticaciones a los emisores, debes suministrar una lista de clientIds que tengan permitido solicitar tokens. Esta lista debe incluir todos los IDs de cliente que obtuviste a través de la consola de Google Cloud para tus clientes web o Android. Esto significa que se debe conocer a los clientes al momento de compilar la API. Si especificas una lista vacía, {}, entonces ningún cliente puede acceder a los métodos protegidos por Auth.

Si usas el atributo clientIds y quieres probar las llamadas autenticadas a tu API con el Explorador de API de Google, debes proporcionar tu ID de cliente en la lista clientIds: el valor que se debe usar es com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID.

Acerca de los públicos

La lista clientIds protege a la API de backend de clientes no autorizados. Aun así, se necesita mayor protección para proteger a los clientes, de manera que el token de autenticación solo funcione con la API de backend deseada. Para clientes Android, este mecanismo es el atributo audiences, en el que se especifica el ID de cliente de la API de backend.

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

@ApiMethod: anotaciones con alcance de método

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

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

Importaciones requeridas

Para usar esta característica, necesitas las importaciones siguientes:

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 de @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 Proporciona esto si quieres anular la configuración en @API. Consulta ID de cliente y públicos para obtener más información. audiences = {"1-web-apps.apps.googleusercontent.com", "2-web-apps.apps.googleusercontent.com"}
authenticators Es obligatorio si tu API realiza las autenticaciones con Firebase, Auth0 o cuentas de servicio, y si no configuraste este atributo en el nivel de la API. Este atributo no es obligatorio si tu API realiza las autenticaciones con tokens de ID de Google. Configúralo como {EspAuthenticator.class}, o puedes escribir tu propio autenticador personalizado como se describe en Autenticador de interfaz authenticators = {EspAuthenticator.class}
clientIds Lista de los ID de cliente de aquellos 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 El método HTTP para utilizar. Si no configuras esto, se elige uno predeterminado según el nombre del método. httpMethod = HttpMethod.GET
issuerAudiences Proporciona esto si quieres anular la configuración en @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. Se puede asignar la anotación @ApiMetricCost a metricCosts. También debes especificar el atributo limitDefinitions para definir la cuota en la anotación @Api. La anotación @ApiMetricCost toma los atributos siguientes:
  • nombre: un nombre que especificaste en la anotación ApiLimitMetric.
  • costo: un número entero que especifica el costo de cada solicitud. El costo permite que los métodos realicen un consumo de la misma cuota a velocidades diferentes. Por ejemplo, si una cuota tiene un límite de 1,000 y un costo de 1, la aplicación que realiza la llamada puede hacer 1,000 solicitudes por minuto antes de sobrepasar el límite. Con un costo de 2 por la misma cuota, la aplicación que hace la llamada puede hacer solo 500 solicitudes por minuto antes de sobrepasar el límite.
metricCosts = { @ApiMetricCost(name = read-requests", cost = 1) }
name El nombre para este método en la biblioteca cliente generada. Esto se prefija de forma automática con el nombre de tu API a fin de crear un nombre único para el método. El valor name:
  • Debe comenzar con minúscula.
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]*.
Si no especificas name, se usa el myapi predeterminado.
name = "foosBall.list"
path La ruta URI que se debe usar para acceder a este método. Si no estableces esto, se usa una ruta predeterminada según el nombre del método de Java. Si planeas agregar la administración de la API, no incluyas una barra al final de la ruta. path = "foos"
scopes Especifica uno o más alcances de OAuth 2.0. Uno de ellos es necesario para llamar a este método. Si estableces scopes para un método, se anula la configuración en la anotación @Api. Si defines más de un alcance, ten en cuenta que la verificación del alcance se aprueba si el token se emite para cualquiera de los alcances especificados. Para requerir varios alcances, especifica un único String con un espacio entre cada alcance. scopes = {"ss0", "ss1 and_ss2"}

Anotación @ApiMethod de muestra

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 transferidos a los métodos del lado del servidor. Esta anotación indica el nombre del parámetro en la solicitud que se inserta aquí. Un parámetro que no se anota con @Named se inserta con el objeto de solicitud completo.

Importaciones requeridas

Para usar esta característica, necesitas las importaciones siguientes:

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

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

@ApiLimitMetric

En esta sección, se describen las anotaciones obligatorias a fin de definir las quotas para tu API. Consulta Configura cuotas para ver todos los pasos necesarios a fin de configurar una cuota.

Puedes asignar la anotación @ApiLimitMetric al atributo limitDefinitions de las anotaciones con alcance API. También debes agregar @ApiMetricCost a las anotaciones @ApiMethod de cada método en el que quieres aplicar una cuota.

Importaciones requeridas

Para usar esta característica, necesitas la importación siguiente:

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

Atributos

Atributos de @ApiLimitMetric

Descripción
name El nombre de la cuota Normalmente, este es el tipo de solicitud (por ejemplo, "solicitudes de lectura" o "solicitudes de escritura") que identifica a la cuota de forma única.
displayName El texto que se muestra para identificar la cuota en la pestaña Cuotas en la página Endpoints > Servicios de la consola de Google Cloud. En este texto, también se muestra a los consumidores de la API en la página Cuotas de IAM y administración y API y servicios. El nombre comercial debe contener un máximo de 40 caracteres.
Para facilitar la lectura, el texto "por minuto por proyecto" se anexa de forma automática al nombre visible en las páginas de Cuotas.
Para mantener la coherencia con los nombres comerciales de los servicios de Google que aparecen en las páginas de Cuotas que ven los consumidores de tu API, recomendamos tener en cuenta los elementos siguientes para el nombre comercial:
  • Usa "Solicitudes" cuando solo tengas una métrica.
  • Cuando tengas múltiples métricas, cada una debe describir el tipo de solicitud y debe contener la palabra "solicitudes" (por ejemplo, "Solicitudes de lectura" o "Solicitudes de escritura").
  • Utiliza "unidades de cuota" en lugar de "solicitudes" cuando alguno de los costos de cuotas sea mayor a 1.
limit Un valor entero que representa el máximo de solicitudes por minuto por proyecto del 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 cliente generadas tengan el espacio de nombres que especificaste, en lugar de uno predeterminado que se construya durante la generación de la biblioteca cliente.

De manera predeterminada, si no usas esta anotación, el espacio de nombres que se usa es el inverso a 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 si proporcionas 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 = ""))

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

De forma opcional, puedes usar el atributo packagePath para proporcionar más alcance. Por ejemplo, si estableces packagePath en cloud, la ruta del paquete que se usó en la biblioteca cliente será com.your-company.cloud.yourApi. Puedes agregar más valores a la ruta del paquete si proporcionas 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 búsqueda). @Nullable solo se puede usar con parámetros @Named.

@ApiClass

En una API multiclase, puedes usar @ApiClass a fin de especificar propiedades diferentes para una clase determinada, y así anular propiedades equivalentes en la configuración @Api. Consulta Uso de @ApiClass para propiedades que pueden diferir entre clases si quieres obtener una descripción completa de esta anotación.

@ApiReference

En una API de multiclase, puedes usar @ApiReference para proporcionar un método alternativo de anotación de herencia. Consulta Uso de @ApiReference de herencia para obtener una descripción completa de esta anotación.

@ApiResourceProperty

@ApiResourceProperty proporciona más control sobre el modo en que las propiedades de recursos se exponen en la API Puedes usarla en un captador o definidor de propiedades para omitir la propiedad de un recurso de API. También puedes usarla en el campo en sí mismo, 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 requeridas

Para usar esta característica, necesitas las importaciones siguientes:

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

Atributos

Atributos de @ApiResourceProperty Descripción Ejemplo
ignored Si se configura en AnnotationBoolean.TRUE, se omite la propiedad. Si no se especifica o se configura en AnnotationBoolean.FALSE, no se omite la propiedad. @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
name Si se proporciona, especifica el nombre de la propiedad para que se exponga en la API. @ApiResourceProperty(name = "baz")

Clase de muestra con @ApiResourceProperty

En el fragmento siguiente, se muestra una clase con captadores de propiedad anotada 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 del código anterior, @ApiResourceProperty se aplica al captador getBin para la propiedad bin, con la configuración del atributo ignored que indica a Endpoints Frameworks que omita esta propiedad en el recurso de API.

@ApiResourceProperty también se aplica al campo privado visible, que no posee captador ni definidor. Con esta anotación, se expone este campo como una propiedad en el recurso de API.

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

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

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

@ApiTransformer

Con la anotación @ApiTransformer, se puede personalizar cómo se expone un tipo en Endpoints a través de la transformación desde uno y hacia otro (el transformador especificado debe ser una implementación de com.google.api.server.spi.config.Transformer).

El método de preferencia para especificar un transformador es mediante la anotación @ApiTransformer en una clase. Sin embargo, de forma alternativa, puedes especificar un transformador personalizado en el atributo transformer de la anotación @Api.

Importaciones requeridas

Para usar esta característica, necesitas la importación siguiente:

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

Clase de muestra con @ApiTransformer

En el fragmento siguiente, 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 muestra

En el fragmento siguiente, se muestra una clase de transformador de muestra 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]));
  }
}

Supongamos que tenemos un objeto con una propiedad bar de tipo Bar; sin el transformador anterior, el objeto se representa de la manera siguiente:

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

Con el transformador, el objeto se representaría de la manera siguiente:

{"bar": "1,2"}