O Java™ API para Serviços da Web RESTful (JAX-RS) permite que os desenvolvedores incluam um provedor de entidade customizado no aplicativo. Use os provedores de entidade customizados quando desejar usar os tipos Java para representar corpos de mensagens
de pedido recebido e também representar corpos de mensagem de resposta de saída. Ao incluir um provedor de entidade customizado, poderá desserializar tipos Java
customizados a partir de corpos de mensagem e serializar qualquer tipo de mídia como
corpos de mensagens.
Sobre Esta Tarefa
Um provedor de entidade customizado é criado ao anotar uma classe
com a anotação javax.ws.rs.ext.Provider. A classe deve implementar a interface
javax.ws.rs.ext.MessageBodyReader, a interface javax.ws.rs.ext.MessageBodyWriter,
ou ambas. Você deve incluir a classe do provedor na lista de classes retornada no método getClasses() da subclasse javax.ws.rs.core.Application.
Procedimento
- Crie uma nova classe Java como seu
provedor de entidade customizado. Nesse procedimento,
o código de exemplo cria um leitor e um gravador para os tipos com.ibm.json.java.JSONObject,
para que o tipo com.ibm.json.java.JSONObject possa ser usado como o parâmetro
de entidade de pedido recebido e como um tipo de retorno para conter a entidade de resposta.
public class MyEntityProvider {
}
- Inclua a Anotação @javax.ws.rs.ext.Provider. Incluir essa anotação indica para o ambiente de tempo de execução JAX-RS
que essa classe é um provedor JAX-RS. Se essa anotação Provedor não for especificada, o ambiente de tempo
de execução não detecta que essa classe é um provedor customizado.
@javax.ws.rs.ext.Provider
public class MyEntityProvider {
}
- (opcional) Inclua uma anotação @javax.ws.rs.Consumes ou @javax.ws.rs.Produces
se desejar limitar os tipos de mídia que o provedor de entidade suporta. No seguinte fragmento de código, o provedor é chamado apenas quando o
Tipo de Conteúdo recebido ou o Tipo de Conteúdo de saída for
application/json.
@javax.ws.rs.ext.Provider
@javax.ws.rs.Consumes("application/json")
@javax.ws.rs.Produces("application/json")
public class MyEntityProvider {
}
- Implemente javax.ws.rs.ext.MessageBodyReader<T> se o provedor
de entidade precisar desserializar um corpo da mensagem.
É possível usar o tipo genérico
<T> para limitar os tipos suportados
pelo provedor da entidade.
Ao definir o leitor de corpo da mensagem como
javax.ws.rs.ext.MessageBodyReader<com.ibm.json.java.JSONObject>,
o ambiente de tempo de execução JAX-RS sabe que apenas os objetos com.ibm.json.java.JSONObject podem ser produzidos.
Se um provedor de entidade precisar suportar um conjunto
de tipos complexo, considere implementar javax.ws.rs.ext.MessageBodyReader<Object>.
@javax.ws.rs.ext.Provider
@javax.ws.rs.Consumes("application/json")
@javax.ws.rs.Produces("application/json")
public class MyEntityProvider implements
javax.ws.rs.ext.MessageBodyReader<com.ibm.json.java.JSONObject> {
public boolean isReadable(Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType) {
return com.ibm.json.java.JSONObject.class == type;
}
public com.ibm.json.java.JSONObject readFrom(Class<com.ibm.json.java.JSONObject> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
/* Este InputStream lê a partir do entityStream e constrói o objeto. */
com.ibm.json.java.JSONObject retObj = com.ibm.json.java.JSONObject.parse(entityStream);
return retObj;
}
}
- Implemente javax.ws.rs.ext.MessageBodyWriter<T> se o provedor
de entidade precisar serializar um corpo da mensagem. É possível implementar as interfaces MessageBodyReader<T> e MessageBodyWriter<T>
interfaces na mesma classe Java.
No seguinte fragmento de código, apenas a implementação MessageBodyWriter é mostrada.
@Provider
public class MyEntityProvider implements
MessageBodyWriter<Object> {
public long getSize(Object t,
Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType) {
/* retornar -1 se o comprimento do conteúdo não puder ser determinado */
retornar -1;
}
public boolean isWriteable(Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType) {
return MyType.class == type;
}
public void writeTo(Object t,
Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
entityStream.write(MyType.getBytes());
}
}
- Inclua o provedor de entidade customizado na subclasse javax.ws.rs.core.Application e inclua o provedor no conjunto de classes retornado a partir do método getClasses(). É possível incluir vários provedores de entidade customizados no conjunto
de classes retornadas.
public class MyApplication extends javax.ws.rs.core.Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(MyEntityProvider.class);
return classes;
}
}
Resultados
Você definiu um provedor de entidade customizado e incluiu esse provedor no seu aplicativo da Web JAX-RS.
Evitar Problemas: Use as seguintes dicas para resolver erros comuns ao implementar formatos
de entidade customizados:
- Provedores customizados não são localizados.
Para resolver esse problema, conclua as seguintes ações:
- Verifique se o provedor está anotado com um @javax.ws.rs.ext.Provider.
Uma classe que não possui a anotação não é registrada como um provedor.
- Verifique se o provedor foi incluído no conjunto de classes retornado a partir do
método getClasses() para as subclasses da classe javax.ws.rs.core.Application.
- Verifique se o valor @javax.ws.rs.Produces ou @javax.ws.rs.Consumes
na classe do provedor está correto.
- Verifique se o método javax.ws.rs.ext.MessageBodyReader#isReadable ou o método
javax.ws.rs.ext.MessageBodyWriter#isWritable está implementado corretamente
e se retornam corretamente um valor true quando esses métodos
forem usados.
- Os cabeçalhos ou a saída do provedor de entidade customizado MessageBodyWriter não está correto.
Para resolver esse problema, conclua as seguintes ações:
- Verifique se o tamanho da resposta em javax.ws.rs.ext.MessageBodyWriter#getSize
está configurado para -1 se o tamanho for desconhecido ou se o valor
está configurado para o tamanho correto quando o tamanho for conhecido. Os clientes podem
truncar a resposta se o valor do tamanho estiver incorreto.
- Se os cabeçalhos HTTP forem configurados no método javax.ws.rs.ext.MessageBodyWriter#writeTo,
eles deverão ser configurados antes que o restante da resposta HTTP seja enviado. Os cabeçalhos HTTP são enviados no início de uma resposta. Portanto, se você configurar os cabeçalhos
depois que o corpo da mensagem de resposta principal começou a ser enviado para o cliente,
será tarde demais para enviar os cabeçalhos de resposta.
gotcha