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
name
eversion
em 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
@Api
comum. - Use a herança de anotação por meio da anotação
@ApiReference
em todas as classes de uma única API para que façam referência à mesma configuração de API de uma classe com anotação@Api
comum.
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>