RSS .92| RSS 2.0| ATOM 0.3
  • Home
  • Artigos
  • Publicações
  • Apresentações
  • Interviews
  • Livros
  • Contact
  • About
  • Manipulação de diferentes formatos

    Uma das capacidades mais interessantes que temos na JSR-311 é a de tratar facilmente diferentes formatos nos nossos serviços. Somos capazes de receber e gerar dados em diferentes tipos de conteúdo, sem ônus para os desenvolvedores.

    Os formatos XML e JSON já estão disponíveis no Jersey (implementação de referência da JSR). Além disso, a JSR permite que seja oferecido o suporte a qualquer formato, através de classes Provider.

    Classes Provider são desenvolvidas para permitir a leitura e/ou escrita de determinados tipos de conteúdo (Content-Types). Uma classe Provider implementa as interfaces MessageBodyReader e MessageBodyWriter para oferecer suporte ao tipo de conteúdo que se propõe. Poderíamos ter, por exemplo, um Provider que soubesse manipular recursos com formato mp3 em uma aplicação multimídia.

    Classes Recurso podem usar as anotações @ConsumeMime e @ProduceMime para declarar quais são os tipos de conteúdo que elas geram e os tipos de conteúdo que elas aceitam receber, respectivamente. Caso nenhum tipo de conteúdo seja declarado, assume-se que qualquer tipo de conteúdo (”*/*”) é aceito.

    O trecho a seguir apresenta um exemplo de uso destas anotações na classe UsuarioResource. Neste exemplo, declaramos que a classe aceita e gera conteúdo nos formatos text/xml e application/json.

    @ConsumeMime( { "text/xml", "application/json" })
    @ProduceMime( { "text/xml", "application/json" })
    public class UsuarioResource {}

    Neste exemplo, colocamos as anotações sobre a classe. Estas anotações também podem ser colocadas sobre métodos. Caso as anotações sejam colocadas sobre a classe e também sobre um método, a anotação sobre o método é a que vale.

    O trecho abaixo mostra um exemplo de anotações sobre a classe e sobre um método. Neste exemplo, declaramos que a classe aceita os tipos de conteúdo text/xml e application/json em todos os seus métodos, com exceção do método buscarUsuario(). Neste método declaramos que produzimos apenas conteúdo em formato text/xml. O método atualizarUsuario() herda as declarações feitas na classe, portanto aceita conteúdo em text/xml e application/json.

    @Path("usuario")
    @ConsumeMime( { "text/xml", "application/json" })
    @ProduceMime( { "text/xml", "application/json" })
    public class UsuarioResource {
    @GET
    @Path("{usuarioId}")
    @ProduceMime("text/xml")
    public Response buscarUsuario(@PathParam("usuarioId") String usuarioId) {
    Usuario usuario = usuarioService.buscar(usuarioId);
    Response resposta = Response.ok(usuario).build();
    return resposta;
    }
     
    @PUT
    @Path("{usuarioId}")
    public Response atualizarUsuario(Usuario usuario) {
    usuarioService.atualizar(usuario);
    return Response.ok().build();
    }
    }

    É importante mencionar como funciona este tratamento dos tipos de conteúdo. Quando um cliente faz uma requisição HTTP, ele pode especificar o cabeçalho Accept. Este cabeçalho informa ao servidor quais são os tipos de conteúdo que o cliente aceita receber. Se o cliente não especificar este cabeçalho, o valor assumido do mesmo é “*/*”, o que indica que o cliente aceita qualquer tipo de conteúdo.

    Ao receber uma requisição HTTP, o runtime JAX-RS irá comparar a lista de tipos enviados no cabeçalho Accept com a lista de tipos de conteúdo registrados para o método invocado. Nesta comparação, as seguintes regras serão aplicadas:

    • Caso exista apenas um tipo de conteúdo em comum entre as duas listas, este será o tipo de conteúdo enviado;
    • Caso exista mais de um tipo de conteúdo em comum entre as listas, o conteúdo será enviado no formato que aparecer primeiro na lista registrada no servidor. Se o método declarou geração de text/xml e application/json (nesta ordem) e o cliente aceita ambos os tipos, o cliente receberá text/xml;
    • Se a lista de tipos de conteúdo oferecida pelo servidor não contiver nenhum dos tipos que o cliente afirmou aceitar, o runtime JAX-RS envia uma resposta de falha com status HTTP 415 (Unsupported Media Type).

    Com estes exemplos, mostramos a capacidade de gerar diferentes formatos em nossos serviços, sem que seja necessário tratar isso explicitamente pela nossa aplicação. A declaração dos tipos de conteúdo através das anotações @ConsumeMime e @ProduceMime é suficiente para que o runtime JAX-RS faça o tratamento correto.

    Uma última questão que precisamos abordar neste contexto é como indicar para a JAX-RS como deve ser feito o mapeamento de nossas classes em XMLs. As implementações da JSR são obrigadas a suportar o uso de JAXB (Java Architecture for XML Binding) na conversão de Java para XML e de XML para Java. O JAXB é um dos componentes do Java EE 5 e foi incluído também na versão 6 do Java SE. Ele é a forma padrão de mapeamento entre classes Java e documentos XML na JSR-311.

    Para utilizar o JAXB no mapeamento de nossas classes, a opção mais simples é utilizar a anotação @XmlRootElement sobre as mesmas. Ao fazer isso, o JAXB fará a conversão da classe e dos seus atributos em um documento XML cujo elemento root será o nome da classe (começando por minúscula). Os elementos filhos serão os atributos da classe, seguindo a nomenclatura da mesma.

    Caso seja desejado, é possível especificar na anotação @XmlRootElement um nome de elemento XML diferente do nome da classe. Podemos também modificar os elementos XML dos atributos da classe usando a anotação @XmlElement. O JAXB nos permite customizar bastante os mapeamentos realizados, se assim quisermos. O trecho abaixo apresenta um exemplo no qual mapeamos a classe Avaliacao para um XML com elementos em inglês. Não entraremos em mais detalhes sobre o JAXB neste momento, pois isto fugiria do foco do artigo.

    @XmlRootElement(name = "feedback")
    public class Avaliacao {XmlElement(name = "feedbackCode")
     
    private String codAvaliacao;
    @XmlElement(name = "rater")
     
    private Usuario avaliador;
    @XmlElement(name = "positive")
     
    private boolean positiva;
    @XmlElement(name = "comment")
     
    private String comentario;
    }

    AnteriorÍndicePróxima

    Leave a Reply

    Bruno Pereira is Digg proof thanks to caching by WP Super Cache!