java-restify
Search…
Anotações padrão
Para consumir uma API com o java-restify, precisamos especificar os detalhes dos contratos: qual o path, o verbo HTTP utilizado, o formato do corpo da requisição e da resposta, cabeçalhos, etc. Isso é feito com o uso de anotações.

Definição do endpoint

@Path

A anotação @Path é utilizada para construção do path do endpoint. É obrigatória em todos os métodos. Se estiver presente no topo da classe, o conteúdo será concatenado à anotação do método.
1
@Path("/base/api") //aplicado a todos os métodos
2
public interface MyApi {
3
4
@Path("/resource")
5
String getResource(); //o endpoint será "/base/api/resource"
6
}
7
8
public interface MyApi {
9
10
@Path("/resource")
11
String getResource(); //o endpoint será "/resource"
12
}
Copied!

@PathParameter

É possível construir o path dinâmicamente, baseado nos parâmetros do método.
1
public interface MyApi {
2
3
@Path("/resource/{id}/{name}")
4
String getResource(String id, String name);
5
}
Copied!
No exemplo acima, o path tem duas partes variáveis, chamadas id e name, e o endpoint será construído no momento da invocação do método, usando o valor fornecido para cada argumento. O binding será realizado utilizando os nomes dos argumentos do método.
Para permitir que os nomes dos parâmetros dos métodos sejam obtidos através de reflection, seu código deve ser compilado com a flag -parameters
Caso prefira não utilizar o binding pelo nome dos argumentos, ou quiser associar a varíavel a um nome diferente do nome do parâmetro, é possível utilizar a anotação @PathParameter:
1
public interface MyApi {
2
3
@Path("/resource/{id}/{name}")
4
String getResource(@PathParameter("id") String identity, @PathParameter("name") String resourceName);
5
}
Copied!
É permitido incluir essa anotação nos argumentos do método mesmo sem customizar o nome, tornando explícito que esses parâmetros fazem parte do path:
1
public interface MyApi {
2
3
@Path("/resource/{id}/{name}")
4
String getResource(@PathParameter String id, @PathParameter String name);
5
}
Copied!
Se nenhuma anotação for adicionada ao parâmetro, ele será considerado um @PathParameter.

Métodos HTTP

Também é obrigatório informar qual método HTTP deve ser utilizado. As anotações existentes são:
1
public interface MyApi {
2
3
@Get
4
@Path("/resource")
5
String get();
6
7
@Post
8
@Path("/resource")
9
String post();
10
11
@Put
12
@Path("/resource")
13
String put();
14
15
@Delete
16
@Path("/resource")
17
String delete();
18
19
@Patch
20
@Path("/resource")
21
String patch();
22
23
@Head
24
@Path("/resource")
25
String head();
26
27
@Options
28
@Path("/options")
29
String options();
30
31
@Trace
32
@Path("/options")
33
String trace();
34
}
Copied!
Todas as anotações são acima são meta-anotações; elas apenas encapsulam a anotação @Method. Caso deseje utilizar algum outro método HTTP qualquer, também é possível utilizar essa anotação diretamente.
1
public interface MyApi {
2
3
@Method("GET")
4
@Path("/resource")
5
String get();
6
}
Copied!

Cabeçalhos

A anotação @Header pode ser utilizada para definição de headers da requisição.
1
@Header(name = "X-Custom-Header", value = "custom header") //aplicado a todos os métodos
2
public interface MyApi {
3
4
@Path("/customers/{id}") @Get
5
@Header(name = "Accept", value = "application/json")
6
Customer findCustomerById(String id);
7
8
}
Copied!
As anotações @Header do topo da interface e do método são unificadas no momento da construção da requisição. No exemplo acima, ao invocar o método findCustomerBy, a requisição HTTP terá os cabeçalhos X-Custom-Header(que será enviado em todos os métodos da interface) e Accept.
A anotação @Header é repetível, e pode ser utilizada para informar vários cabeçalhos (no topo da interface ou por método):
1
@Header(name = "X-Custom-Header", value = "custom header")
2
@Header(name = "X-Other-Custom-Header", value = "custom header")
3
public interface MyApi {
4
5
@Path("/customers/{id}") @Get
6
@Header(name = "Accept", value = "application/json")
7
@Header(name = "X-Custom-Customer-Header", value = "specific custom method header")
8
Customer findCustomerById(String id);
9
10
}
Copied!

@HeaderParameter

Para cabeçalhos dinâmicos, existe a anotação @HeaderParameter:
1
public interface MyApi {
2
3
@Path("/customers/{id}") @Get
4
Customer findCustomerById(String id, @HeaderParameter("X-Custom-Customer-Header") String customHeader);
5
6
}
Copied!

Shortcuts

Outras anotações úteis para inclusão de cabeçalhos são:
1
public interface MyApi {
2
3
@Path("/customers/{id}") @Get
4
@AcceptAll
5
Customer findCustomerById(String id);
6
7
/* @AcceptJson adiciona o cabeçalho "Accept=application/json" */
8
@Path("/customers/{id}") @Get
9
@AcceptJson
10
Customer findCustomerByIdAsJson(String id);
11
12
/* @AcceptXml adiciona o cabeçalho "Accept=application/xml" */
13
@Path("/customers/{id}") @Get
14
@AcceptXml
15
Customer findCustomerByIdAsXml(String id);
16
17
/* @FormURLEncoded adiciona o cabeçalho "Content-Type=application/x-www-form-urlencoded" */
18
@Path("/customers") @Post
19
@FormURLEncoded
20
Customer createCustomerAsForm();
21
22
/* @MultipartFormData adiciona o cabeçalho "Content-Type=multipart/form-data" */
23
@Path("/customers") @Post
24
@FormURLEncoded
25
Customer createCustomerAsMulipart();
26
27
/* @JsonContent adiciona o cabeçalho "Content-Type=application/json" */
28
@Path("/customers") @Post
29
@JsonContent
30
Customer createCustomerAsJson();
31
32
/* @XmlContent adiciona o cabeçalho "Content-Type=application/xml" */
33
@Path("/customers") @Post
34
@XmlContent
35
Customer createCustomerAsXml();
36
37
/* @SerializableContent adiciona o cabeçalho "Content-Type=application/octet-stream" */
38
@Path("/customers") @Post
39
@SerializableContent
40
Customer createCustomerAsSerializable();
41
}
Copied!

Cookies

A anotação @Cookie é utilizada para definição de cookies da requisição, que são enviados através do cabeçalho Cookie.
De maneira análoga à anotação @Header, cookies podem ser definidos no topo da interface ou ao nível do método; cookies dinâmicos também podem ser enviados através de argumentos do método anotados com @CookieParameter.
1
@Cookie(name = "my-cookie", value = "cookie-value") //aplicado a todos os métodos
2
public interface MyApi {
3
4
@Path("/customers/{id}") @Get
5
@Cookie(name = "other-cookie", value = "other-cookie-value")
6
Customer findCustomerById(String id);
7
8
@Path("/customers/{id}") @Get
9
Customer findCustomerById(String id, @CookieParameter("other-cookie") String cookie);
10
}
Copied!

Query parameters

@QueryParameter

Para o envio de query parameters, utilize a anotação @QueryParameter:
1
public interface MyApi {
2
3
// "/customers?name=..."
4
@Path("/customers") @Get
5
Customer findCustomerByName(@QueryParameter String name);
6
7
// "/customers?customer_name=..."
8
@Path("/customers") @Get
9
Customer findCustomerByName(@QueryParameter("customer_name") String name);
10
11
}
Copied!

@QueryParameters

Para enviar múltiplos parâmetros, naturalmente, pode-se criar um método com vários argumentos anotados com @QueryParameter, mas existem outras alternativas, utilizando a anotação @QueryParameters.
É possível utilizar um único parâmetro do tipo Map<String, ?>:
1
public interface MyApi {
2
3
@Path("/customers") @Get
4
Customer findCustomerByParameters(@QueryParameters Map<String, String> mapParameters);
5
}
6
7
public static void main(String[] args) {
8
9
MyApi myApi = new RestifyProxyBuilder()
10
.target(MyApi.class)
11
.build();
12
13
// adiciona dois query parameters
14
Map<String, String> mapParameters = new LinkedHashMap<>;
15
mapParameters.put("name", "Tiago de Freitas Lima");
16
mapParameters.put("age", "33");
17
18
// /customers?name=Tiago+de+Freitas+Lima&age=33
19
Customer customer = myApi.findCustomerByParameters(mapParameters);
20
}
Copied!
A chave do mapa deve ser do tipo String, e os valores podem ser de qualquer tipo.
Outra opção é utilizar um parâmetro do tipo Parameters, um objeto Map-like que permite adicionar múltiplos valores por parâmetro:
1
public interface MyApi {
2
3
@Path("/customers") @Get
4
Customer findCustomerByParameters(@QueryParameters Parameters parameters);
5
6
}
7
8
public static void main(String[] args) {
9
10
MyApi myApi = new RestifyProxyBuilder()
11
.target(MyApi.class)
12
.build();
13
14
// Parameters é um objeto imutável
15
Parameters parameters = new Parameters()
16
.put("name", "Tiago de Freitas Lima")
17
.put("age", "31")
18
.put("socialPreferences", "facebook")
19
.put("socialPreferences", "twitter");
20
21
// /customers?name=Tiago+de+Freitas+Lima&age=31&socialPreferences=facebook&socialPreferences=twitter
22
Customer customer = myApi.findCustomerByParameters(parameters);
23
}
Copied!

Request body

@BodyParameter

Para enviar um objeto no corpo da requisição, utilize a anotação @BodyParameter:
1
public interface MyApi {
2
3
@Path("/customers") @Post
4
@JsonContent
5
Customer createCustomer(@BodyParameter Customer customer);
6
7
}
Copied!
Para que o objeto seja adequadamente serializado, o cabeçalho Content-Type deve, obrigatoriamente, estar definido. No exemplo acima, usando a anotação @JsonContent, o Content-Type da requisição será application/json, e o objeto será serializado nesse formato se houver um converter registrado (consulte a documentação detalhada do mecanismo de serialização/deserialização e dos tipos de conteúdo suportados).
Apenas um argumento do método deve ser anotado com @BodyParameter.

Versionamento

@Version

A anotação @Version pode ser utilizada para indicar explicitamente a versão do endpoint que está sendo consumido. A versão será incluída sempre antes do path especificado para o método.
1
public interface MyApi {
2
3
// /v1/customers
4
@Version("v1")
5
@Path("/customers") @Post
6
Customer createCustomer(@BodyParameter Customer customer);
7
8
}
9
10
@Path("http://my.api.com")
11
public interface MyApi {
12
13
// http://my.api.com/v1/customers
14
@Version("v1")
15
@Path("/customers") @Post
16
Customer createCustomer(@BodyParameter Customer customer);
17
18
}
Copied!
A anotação também pode ser utilizada no topo da interface, sendo aplicada para todos os métodos:
1
@Version("v1")
2
public interface MyApi {
3
4
// /v1/customers
5
@Path("/customers") @Post
6
Customer createCustomer(@BodyParameter Customer customer);
7
8
}
Copied!
Eventualmente, a estratégia de versionamento da API não será explícita no path, e sim através de algum cabeçalho da requisição. Nesse caso, é possível utiizar a anotação apenas para informar explicitamente a versão, sem incluí-la no path:
1
public interface MyApi {
2
3
// o path construído será "/customers"
4
@Version(value = "v1", uri = false)
5
@Path("/customers") @Post
6
Customer createCustomer(@BodyParameter Customer customer);
7
8
}
Copied!
A informação da versão ainda estará disponível, e poderá ser acessada em um interceptor para inclusão de algum cabeçalho customizado, ou qualquer outra maneira de enviar essa informação na requisição (consulte a documentação detalhada da API de interceptors).

Serialização de argumentos

Para obter o valor do argumento que deve ser concatenado ao path, ao header ou ao query string, é utilizado o método toString() (argumentos com valores nulos são desconsiderados). Mas esse comportamento pode ser customizado através do atributo serializer, presente nas anotações @PathParameter, @HeaderParameter, @CookieParameter, @QueryParameter e @QueryParameters. Esse atributo recebe uma referência para uma implementação da interface ParameterSerializer.
Por exemplo, suponhamos que o argumento do método é do tipo Date, mas queremos concatenar ao path o timestamp. A estratégia padrão, usando o método toString(), não atenderia esse caso de uso.
1
public interface MyApi {
2
3
@Path("/resource/{timestamp}")
4
String getResourceByTimestamp(@PathParameter(serializer = TimestampParameterSerializer.class) Date timestamp);
5
6
}
7
8
public class TimestampParameterSerializer implements ParameterSerializer {
9
10
@Override
11
public String serialize(String name, Type type, Object source) {
12
Date date = (Date) source;
13
14
return Long.toString(date.getTime());
15
}
16
}
Copied!
Last modified 2yr ago