Se uma única API for particularmente complexa, implemente-a a partir de múltiplas classes Java. Para que diferentes classes façam parte da mesma API, siga estas etapas:
- Adicione a cada classe as mesmas strings
nameeversionem suas anotações@Api. - Adicione APIs de classe como uma lista separada por vírgulas em
web.xml.
Por exemplo, as duas classes a seguir fazem parte da API tictactoe:
@Api(name = "tictactoe", version = "v1")
class TicTacToeA { … }
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
A configuração da API é especificada por meio das propriedades da anotação @Api.
No entanto, para várias classes na mesma API, os requisitos de @Api vão além de ter as mesmas strings name e version na anotação @Api de cada classe. Na verdade, a API de back-end não funcionará se houver qualquer diferença nas configurações de API especificadas nas propriedades @Api das classes. Se houver diferenças nas propriedades @Api em uma API multiclasse, será gerada uma configuração "ambígua" que não funciona no Cloud Endpoints Frameworks para App Engine.
Há várias maneiras de criar uma API multiclasse não ambígua:
- Verifique manualmente se todas as classes de uma única API têm as mesmas propriedades de anotação
@Api. - Use a herança de anotação por meio da Herança de Java.
Nessa herança, todas as classes de uma única API herdam a mesma configuração de API de uma classe base com anotação
@Apicomum. - Use a herança de anotação por meio da anotação
@ApiReferenceem todas as classes de uma única API para que façam referência à mesma configuração de API de uma classe com anotação@Apicomum.
Como usar @ApiClass em propriedades que diferem entre as classes
Para usar esse recurso, é necessária a seguinte importação:
import com.google.api.server.spi.config.ApiClass;
Todas as propriedades na anotação @Api precisam corresponder a todas as classes em uma API. No entanto, também é possível usar a anotação @ApiClass para fornecer propriedades que não precisam ser exatamente as mesmas entre classes. Por exemplo:
// API methods implemented in this class allow only "clientIdA".
@Api(name = "tictactoe", version = "v1")
@ApiClass(clientIds = { "clientIdA" })
class TicTacToeA { … }
// API methods implemented in this class provide unauthenticated access.
@Api(name = "tictactoe", version = "v1")
class TicTacToeB { … }
em que TicTacToeA limita o acesso usando uma lista de permissões de IDs de clientes contendo o ID do cliente permitido e TicTacToeB não limita o acesso.
Todas as propriedades fornecidas pela anotação @ApiClass têm uma propriedade equivalente na anotação @Api. Observe que a propriedade equivalente de @Api atua como o padrão da API. Se houver um padrão para toda a API para essa mesma propriedade, especificada em @Api, a propriedade @ApiClass específica para classes substituirá o padrão da API.
Nos exemplos a seguir, veja a substituição de propriedades @Api pelos equivalentes @ApiClass específicos da classe:
// For this class "boards" overrides "games".
@Api(name = "tictactoe", version = "v1", resource = "games")
@ApiClass(resource = "boards")
class TicTacToeBoards { … }
// For this class "scores" overrides "games".
@Api(name = "tictactoe", version = "v1", resource = "games")
@ApiClass(resource = "scores")
class TicTacToeScores { … }
// For this class, the API-wide default "games" is used as the resource.
@Api(name = "tictactoe", version = "v1", resource = "games")
class TicTacToeGames { … }
Herança de anotação
As propriedades de anotação @Api e @ApiClass podem ser herdadas de outras classes, e propriedades individuais podem ser modificadas por meio da herança de Java ou da herança de @ApiReference.
Como usar a herança de Java
Uma classe que estende outra classe com anotações @Api ou @ApiClass comporta-se como se fosse anotada com as mesmas propriedades. Por exemplo:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA and TicTacToeB both behave as if they have the same @Api annotation as
// TicTacToeBase
class TicTacToeA extends TicTacToeBase { … }
class TicTacToeB extends TicTacToeBase { … }
As anotações são herdadas somente por meio das subclasses Java, não por meio de implementação de interface. Por exemplo:
@Api(name = "tictactoe", version = "v1")
interface TicTacToeBase { … }
// Does *not* behave as if annotated.
class TicTacToeA implements TicTacToeBase { … }
Como resultado, não há suporte para qualquer tipo de herança múltipla de anotações de frameworks.
A herança funciona para @ApiClass também:
@ApiClass(resource = "boards")
class BoardsBase { … }
// TicTacToeBoards behaves as if annotated with the @ApiClass from BoardsBase.
// Thus, the "resource" property will be "boards".
@Api(name = "tictactoe", version = "v1", resource = "scores")
class TicTacToeBoards extends BoardsBase { … }
em que TicTacToeBoards herda boards do valor da propriedaderesource de BoardsBase, modificando a configuração de propriedade resource (scores) na anotação @Api. Lembre-se de que será preciso especificar a propriedade de recurso na anotação @Api em todas as classes se alguma classe tiver essa definição na anotação @Api. Com essa técnica de herança, é possível modificar essa propriedade de @Api.
Como usar a herança @ApiReference
Para usar esse recurso, é necessária a seguinte importação:
import com.google.api.server.spi.config.ApiReference;
A anotação @ApiReference fornece um meio alternativo de especificar a herança de anotação. Uma classe que usa @ApiReference para especificar outra classe com anotações @Api ou @ApiClass comporta-se como se estivesse anotada com as mesmas propriedades. Por exemplo:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase { … }
// TicTacToeA behaves as if it has the same @Api annotation as TicTacToeBase
@ApiReference(TicTacToeBase.class)
class TicTacToeA { … }
Se a herança de Java e a @ApiReference forem usadas simultaneamente, as anotações serão herdadas somente pela anotação @ApiReference. As anotações @Api e @ApiClass na classe herdada por meio da herança de Java serão ignoradas. Por exemplo:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBaseA { … }
@Api(name = "tictactoe", version = "v2")
class TicTacToeBaseB { … }
// TicTacToe will behave as if annotated the same as TicTacToeBaseA, not TicTacToeBaseB.
// The value of the "version" property will be "v1".
@ApiReference(TicTacToeBaseA.class)
class TicTacToe extends TicTacToeBaseB { … }
Como modificar a configuração herdada
Se sua configuração foi herdada por meio da herança de Java ou @ApiReference, é possível mudá-la usando uma nova anotação @Api ou @ApiClass. Somente as propriedades da configuração especificadas na nova anotação serão modificadas. As propriedades não especificadas ainda serão herdadas.
Por exemplo:
@Api(name = "tictactoe", version = "v2")
class TicTacToe { … }
// Checkers will behave as if annotated with name = "checkers" and version = "v2"
@Api(name = "checkers")
class Checkers extends TicTacToe { … }
A modificação da herança funciona também para @ApiClass:
@Api(name = "tictactoe", version = "v1")
@ApiClass(resource = "boards", clientIds = { "c1" })
class Boards { … }
// Scores will behave as if annotated with resource = "scores" and clientIds = { "c1" }
@ApiClass(resource = "scores")
class Scores { … }
A modificação funciona também na herança por meio de @ApiReference:
@Api(name = "tictactoe", version = "v2")
class TicTacToe { … }
// Checkers will behave as if annotated with name = "checkers" and version = "v2"
@ApiReference(TicTacToe.class)
@Api(name = "checkers")
class Checkers { … }
Como herdar anotações @ApiMethod
A anotação @ApiMethod pode ser herdada de métodos modificados. Por exemplo:
class TicTacToeBase {
@ApiMethod(httpMethod = "POST")
public Game setGame(Game game) { … }
}
@Api(name = "tictactoe", version = "v1")
class TicTacToe extends TicTacToeBase {
// setGame behaves as if annotated with the @ApiMethod from TicTacToeBase.setGame.
// Thus the "httpMethod" property will be "POST".
@Override
public Game setGame(Game game) { … }
}
Assim como acontece com a herança das anotações @Api e @ApiClass, as propriedades individuais poderão ser modificadas se vários métodos que modificam um ao outro tiverem anotações @ApiMethod. Por exemplo:
class TicTacToeBase {
@ApiMethod(httpMethod = "POST", clientIds = { "c1" })
public Game setGame(Game game) { … }
}
@Api(name = "tictactoe", version = "v1")
class TicTacToe extends TicTacToeBase {
// setGame behaves as if annotated with httpMethod = "GET" and clientIds = { "c1"}.
@ApiMethod(httpMethod = "GET")
@Override
public Game setGame(Game game) { … }
}
Não há qualquer anotação @ApiReference ou equivalente para os métodos, por isso, @ApiMethod é sempre herdado da herança de Java e não de @ApiReference.
Regras de herança e precedência
Para resumir a discussão sobre precedência, a tabela a seguir apresenta as regras de herança e a ordem de precedência:
| Anotação/herança | Regra |
|---|---|
@Api |
Precisa ser idêntica para todas as classes. |
@ApiClass |
Especificada para uma classe para modificar propriedades de @Api. |
| Herança de Java | A classe herda @Api e @ApiClass da classe base. |
@ApiReference |
A classe herda @Api e @ApiClass da classe especificada. |
Usar @ApiReference em uma classe (Java) que herda de uma classe base. |
A classe herda a @Api e @ApiClass da classe especificada, não da classe base. |
Casos de uso comuns da herança de anotação
Exemplos de casos de uso típicos de herança:
Para controle de versão de API:
@Api(name = "tictactoe", version = "v1")
class TicTacToeV1 { … }
@Api(version = "v2")
class TicTacToeV2 extends TicTacToeV1 { … }
Para APIs multiclasse:
@Api(name = "tictactoe", version = "v1")
class TicTacToeBase {}
@ApiClass(resource = "boards")
class TicTacToeBoards extends TicTacToeBase { … }
@ApiClass(resource = "scores")
class TicTacToeScores extends TicTacToeBase { … }
Para testar diferentes versões da mesma API:
@Api(name = "tictactoe", version = "v1")
class TicTacToe {
protected Foo someMethod() {
// Do something real;
}
public Foo getFoo() { … }
}
@Api(version="v1test")
class TicTacToeTest extends TicTacToe {
protected Foo someMethod() {
// Stub out real action;
}
}
em que someMethod retorna respostas predeterminadas, evita chamadas com efeitos colaterais, ignora uma solicitação de rede ou de armazenamento de dados e assim por diante.
Como adicionar as classes a web.xml
Depois de anotar suas classes, adicione-as ao seu arquivo web.xml. O exemplo a seguir mostra uma única classe:
Para adicionar várias classes:
Substitua
<param-value>com.example.skeleton.MyApi</param-value>pelo nome de classe da API.Adicione cada classe no mesmo campo
<param-value>separado por uma vírgula, por exemplo:<param-value>com.example-company.example-api.Hello,com.example-company.example-api.Goodbye</param-value>