Mostrando postagens com marcador Web Services. Mostrar todas as postagens
Mostrando postagens com marcador Web Services. Mostrar todas as postagens

Introdução a JAX–RS – Java API for RESTful Web Services

sábado, 16 de outubro de 2010

JAX-RS é a solução do JCP para o estilo de programação REST. A proposta final da especificação foi liberada para o público no inicio de Agosto de 2008,. A especificação define um conjunto de APIs Java para
auxiliar no desenvolvimento de web services baseados em REST.
O objetivo da API é fornecer um conjunto de anotações, classes e interfaces para expor uma classe POJO
como um web service RESTful, de modo que possamos fazer uma programação fácil e de alto nível.


Trabalhando com os recursos

Para uma classe ser determinada como um recurso, ela tem que ser uma classe POJO com pelo menos um método anotado com a anotação @Path.
A anotação @Path pode ser colocada na declaração de classe ou de um método e possui o elemento value
obrigatório. Por este elemento definimos o prefixo da URI que a classe ou o método irá atender. Na Listagem 01, a classe Repositorio é identificada pela URI relativa “/repositorio/{id}”, onde {id} é o valor do parâmetro id, fornecido junto a URI.
Mais adiante, demonstraremos como extrair valores como esse de uma URI utilizando anotações especificas.

@Path("/repositorio/{id}")
public class Repositorio { ... }
Listagem 01 - Mapeando uma URI para uma classe com @Path.

A especificação define que no ciclo de vida de um recurso, por padrão, sempre que for feito uma requisição a um recurso, será criada uma nova instância de uma classe REST. Primeiro o construtor é chamado pelo contêiner, por conta disto, o construtor da classe deve ser público. Após este primeiro passo, o contêiner efetua as injeções de dependência nos devidos métodos e o método designado para aquele recurso é invocado. E finalmente após a chamada ao método o objeto fica disponível para o garbage collector.
Geralmente a anotação @Path é incluída na declaração de um método quando queremos atribuir um caminho mais específico para um recurso, de forma a especializar nosso método, como na Listagem 02. Note no exemplo como a URI é mapeada com a classe e o método.
@Path("/vendas/")
public class Repositorio {
  @GET
  @Produces("application/xml")
  @Path("/pedidos/{numPedido}/")
  public PedidoAsXML getPedido(@PathParam("numPedido") Integer id){
    // retorna Pedido em formato XML.
  }
}
Listagem 02 - Mapeando uma URI para uma classe com @Path.

Acessando os Recursos

Para acesso aos recursos, a especificação JAX-RS define um conjunto de anotações correspondentes aos métodos HTTP, como @GET, @POST, @PUT, @DELETE, @HEAD.. Elas devem ser atribuídas a métodos públicos. O método anotado com @GET, por exemplo, irá processar requisições HTTP GET na URI atribuída. O comportamento do recurso é determinado pelo método HTTP ao qual o recurso está respondendo.
É bom entender o papel e o uso de cada um destes métodos HTTP no momento de projetar nossos serviços.
Além dos métodos definidos pelo JAX-RS, podemos criar uma anotação customizada como @MKCOL, com uso da anotação HttpMethod, conforme ilustra a Listagem 03.
Com esta anotação podemos criar métodos customizados e extender a gama dos métodos pré-existentes e utilizar os métodos definidos pelo WebDAV, como fazemos na Listagem 3, ou podemos alternar um método padrão para a anotação customizada, onde para isso poderíamos simplesmente informar como valor para anotação HttpMethod o valor do método que queremos sobrepor, por exemplo, para sobrepor o método PUT a declaração da anotação ficaria
@HttpMethod("PUT").

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("MKCOL")
public @interface MKCOL {
}
Listagem 03: Utilizando a anotação HttpMethod para criar uma anotação customizada.

Representações: Quais são os sabores?

As classes de uma aplicação RESTful podem ser declaradas para suportar diversos tipos de formatos durante um ciclo requisição-resposta. Para isso a especificação define as anotações @Consumes e @Produces para o tratamento da request e response respectivamente.
Com estas anotações o servidor declara o tipo de conteúdo que será trafegado, através do cabeçalho (header) do protocolo HTTP, estas anotações podem ser aplicadas na declaração de uma classe, ou podemos utilizar estas anotações na declaração do método para sobrescrever a declaração da classe, na ausência destas anotações, será assumido como default qualquer tipo de retorno ("*/*").
No caso da anotação @Produces, ela é utilizada para mapear uma requisição de um cliente com o cabeçalho do cliente (parâmetro Accept). Desta maneira, podemos definir mais de um tipo de retorno da URI solicitada, como JSON e XML, como no exemplo da Listagem 04:
@GET
@Produces({"application/xml", "application/json"})
public PessoaConverter getPessoa(@QueryParam("CPF") String numCPF) {
  // Retorna representação em XML ou JSON
}
Listagem 04 - Declarando o tipo de retorno com a anotação @Produces.

Pegando o exemplo da Listagem 04, podemos testar o retorno da chamada utilizando uma das ferramentas
citadas no tópico "Como consumir serviços REST", como a ferramenta RESTClient, por exemplo, e incluir na aba "Headers" o parâmetro "Accept" e no campo Value especificar o tipo de retorno primeiro com XML e depois com JSON, conforme Figura 01:

Figura 01 - Testando tipos de retorno para a mesma URI com RESTClient.

Com a anotação @Consumes por outro lado, podemos definir os tipos de mídia que um recurso em particular consome. Como o exemplo da Listagem 05, onde estamos declarando que o método consome apenas formatos do tipo XML e JSON:
@PUT
@Consumes("application/xml","application/json")
@Path("/autores/")
public Response putPessoa(PessoaBinding pessoa) {}
Listagem 05: Uso da anotação @Consumes.

Extraindo parâmetros e valores da URI na requisição.

JAX-RS fornece algumas anotações para extrair informações de uma requisição. Existem seis tipos de parâmetros (ver Tabela 01) que podemos extrair para utilizar em nossa classe recurso. Para os parâmetros de query utilizamos a anotação @QueryParam. Para os parâmetros de URI(path) existe a anotação @PathParam.
Para os parâmetros de formulário existe @FormParam. Já para parâmetros de cookie existe @CookieParam.
Para os parâmetros de header existe @HeaderParam e, finalmente, para os parâmetros de matriz existe a anotação @MatrixParam.
Estas anotações podem ser aplicadas diretamente a parâmetros de um método. Desta forma vinculamos o valor do parâmetro de uma URI a algum parâmetro de entrada de um método. Para contextualizar, veja um exemplo na Listagem 06:
@Path("/editora/")
public class EditoraResource {
  @GET
  @Produces("application/xml")
  @Path("/autores/{nomeAutor}/")
  public PessoaBinding getPessoa(@PathParam("nomeAutor") String name,
                       @QueryParam("idade") int idade,
                       @HeaderParam("CPF") String numCPF,
                       @MatrixParam("statusCivil") String statusCivil) {
     return new PessoaBinding(name, idade, numCPF, statusCivil);
  }
}
Listagem 06 – Mapeando os parâmetros de uma URI para os parâmetros de um método.

Na Listagem 06, vemos a aplicação de várias anotações de parâmetro de URI em um único método. Para entender melhor como será feito o DE-PARA da URI para os parâmetros de entrada, vamos fazer uma chamada a este recurso com a biblioteca curl, apresentado na Figura 02.

Figura 02 - Fragmentando a URI para demonstrar anotações de mapeamento.



Tabela 01 - Anotações JAX-RS para extração de informações da URI.

No exemplo da Listagem 06 não demonstramos o uso das anotações CookieParam e FormParam, mas o seu uso é bem similar. No caso de FormParam, esta anotação pode capturar todos os valores submetidos de um formulário HTML e injetá-los nos parâmetros desejados. Veja um exemplo simples na listagem 07. Trata-se de um formulário HTML e de um método que irá receber estas informações.

Nome: Idade:
@Path("/editora/")
public class EditoraResource {
  @GET
  @Path("/autores/")
  public PessoaBinding getPessoa(@FormParam("nomeAutor") String name,
                       @FormParam("idade") int idade) {
    return new PessoaBinding(name, idade);
  }
}
Listagem 07 - Uso da anotação FormParam.

No caso da anotação CookieParam, conseguimos injetar o valor de cookie ou a classe Cookie do javax.ws.rs.core, que representa o valor de um cookie HTTP na invocação de um método.

Dados de Contexto

A especificação JAX-RS dispõe de um recurso para a obtenção de informações do contexto da aplicação e de requisições individuais. Estas informações são disponíveis tanto para as classes recursos quanto para os providers. Para a recuperação destas informações existe a anotação @Context, que ao ser aplicada sobre um campo, método ou parâmetro, identifica um alvo a ser injetado pelo contêiner.
O contêiner fornece instâncias dos recursos listados na tabela 02, mediante a aplicação da anotação @Context.


Tabela 02: Lista de recursos injetados pelo contêiner pela anotação @Context.

Tratando o retorno dos métodos ao Cliente.

Os tipos de retorno de uma chamada a um método recurso podem ser do tipo void, Resource, GenericType ou outro tipo Java. Esses tipos de retorno são mapeados ao entity body da Response cada um de uma maneira, de acordo o provider padrão, conforme veremos a seguir.
Para os retornos do tipo void, o retorno será um corpo vazio com status 204 do HTTP. Para tratar o retorno ao cliente foi disponibilizada a classe abstrata Response. Com essa classe definimos um contrato entre a instância de retorno e o ambiente de execução, quando uma classe precisa fornecer metadados para ambiente de execução.
Podemos estender esta classe diretamente ou, ainda melhor, podemos criar uma instância utilizando sua classe interna ResponserBuilder. Por essa classe podemos construir objetos do tipo Response, adicionar metadados, adicionar cookies, adicionar dados no Header, informar a linguagem, entre outras informações.
Na Listagem 08, no método putPessoa, fazemos uso do método Response. Note que não a instanciamos diretamente, pois ela é uma classe abstrata que implementa o padrão de projeto Builder.
Dentro do método, primeiramente efetuamos uma chamada ao método estático created, passando como parâmetro a URI que obtemos através da classe injetada UriInfo. Esta classe retorna o objeto ResponseBuilder, que é uma subclasse de Response, esta subclasse é utilizada exclusivamente para criar instâncias de Response.
Por ResponseBuilder ser uma classe de construção (Builder), podemos efetuar chamadas recursivas aos métodos de parametrização. Após a chamada ao método created, chamamos o método status, no qual atribuímos o código de status HTTP 202 (Accepted) e logo após atribuímos uma entidade à requisição, no nosso exemplo um código HTML simples, pelo método entity. Na chamada ao método type seguinte, especificamos o tipo de mídia trafegado, neste caso TEXT_HTML. No final fazemos uma chamada ao método build, que constrói o objeto Response.
E por fim o objeto GenericEntity representa uma entidade de um tipo genérico, muito útil quando precisamos retornar uma Response personalizada e reter informações genéricas. Pois informações de tipos genéricos são apagadas ao utilizar uma instância.

@Context protected UriInfo uriInfo;
@PUT
@Consumes("application/xml")
@Path("/MundoJava/update/")
public Response putPessoa(PessoaBinding pessoa) {
     String retorno = "Bem vindo "+pessoa.getNome();
     Response response = Response.created(uriInfo.getAbsolutePath()).
                                       status(Response.Status.ACCEPTED).
                                       entity(retorno).
                                       type(MediaType.TEXT_HTML).
                                       build();
     return response;
}
Listagem 08 – Tratando a Response do cliente.

Entity Providers

Entity providers fornecem serviços de mapeamento entre representações e seus tipos associados Java. Existem dois tipos de entity providers, MessageBodyReader e MessageBodyWriter.
A especificação JAX-RS define que para alguns tipos, o contêiner pode automaticamente serializar (marshal) e deserealizar (unmarshal) o corpo de diferentes tipos de mensagens, listados na tabela 03.
Tabela 03: Tipos de Mídia e seus tipos Java correspondentes.

Para requisições HTTP, podemos mapear o corpo da entidade para um parâmetro de método com uso da interface MessageBodyReader, para o tratamento das responses, o valor de retorno é mapeado para o corpo da entidade de um método HTTP com uso da interface MessageBodyWriter.
Pode ser que no desenvolvimento de nossas aplicações, estes tipos padrões não atendam a necessidade de negócio e tenhamos que lidar com tipos que não sejam suportados pelos tipos default, para contornar esta limitação, a API JAX-RS permite que a criação de Providers para Message Body customizáveis, com métodos para conversão de InputStream/OutputStream para objetos Java do tipo T.
Para criar nosso próprio provider customizado, a especificação disponibiliza a anotação @Provider, que ao ser aplicado sobre uma classe, estamos automaticamente registrando este classe junto ao contêiner. 
Porém, é importante ressaltar, que esta funcionalidade apesar de muito útil, pode ser tornar um problema em grandes projetos, que podem utilizar providers com o mesmo nome em diferentes bibliotecas, podendo ocasionar conflitos.
Caso a aplicação necessite de informações adicionais, como HTTP Headers ou um código de status diferente, o método pode retornar o objeto Response que encapsule a entidade. 
Veja um exemplo extraído de um sample da implementação de referência da Sun, o Jersey, na listagem 09, esta classe implementa um MessageBodyWriter para uma classe Properties.

@Produces("text/plain")
@Provider
public class PropertiesProvider implements MessageBodyWriter {
    public void writeTo(Properties p, 
            Class type, Type genericType, Annotation annotations[],
            MediaType mediaType, MultivaluedMap headers, 
            OutputStream out) throws IOException {
        p.store(out, null);
    }
    public boolean isWriteable(Class type, Type genericType, Annotation annotations[], MediaType mediaType) {
        return Properties.class.isAssignableFrom(type);
    }
    public long getSize(Properties p, Class type, Type genericType, Annotation annotations[], MediaType mediaType) {
        return -1;
    }
}
Listagem 09: Uso da tag @Provider.
Tratando Exceções

Para tratamento de exceções, a especificação JAX-RS define a exceção WebApplicationException que estende RuntimeExcetion, que pode ser lançada por um método de recurso, por um provider ou por uma implementação de StreamingOutput. Esta exceção permite que abortemos a execução de um serviço JAX-RS. 
Como parâmetro de construtor, podemos utilizar um código de status HTTP ou até um objeto Response. Veja um exemplo na listagem 10:

@GET
@Produces("application/xml")
@Path("/autores/{personName}/{idade: [0-9]+}/")
public PessoaBinding getPessoa(@PathParam("personName") String name, @PathParam("idade")
    int idade, @HeaderParam("CPF") String numCPF) {
    if (idade <= 0 || idade > 120){
        throw new WebApplicationException(Response.
                                          status(412).
                                          entity("Idade inválida!").
                                          build());
    }
  return new PessoaBinding(name, idade, numCPF);
}
Listagem 10: Uso de exceção com WebApplicationException.

Por padrão, quando uma classe JAX-RS ou um método provider lança uma exceção em tempo de execução, essa exceção é mapeada a um código de status HTTP adequado. Nós podemos customizar a nossa exceção conforme a necessidade, para isto, a especificação define a interface ExceptionMapper, com ela podemos criar nossos próprios providers e customizar este mapeamento, para tanto, a implementação desta interface deve estar anotada com @Provider. Veja um exemplo na listagem 11:

@Provider
public class IdadeInvalidaExceptionMapper implements ExceptionMapper{
  public Response toResponse(IdadeInvalidaException ex) {
    return Response.status(412).entity(ex.getMessage()).build();
  }
}
Listagem 11: Mapeando uma exceção Java para uma Response.

Na listagem 11 perceba que registramos a classe ExceptionMapper da mesma maneira que registramos MessageBodyReaders e MessageBodyWriters. Ao utilizarmos a exceção IdadeInvalidaException em um método RESTful como no método da listagem 12, o contêiner irá em tempo de execução identificar o provider e irá mapear esta exceção com IdadeInvalidaExceptionMapper.


@GET
@Produces("application/xml")
@Path("/autores/{personName}/{idade: [0-9]+}/")
public PessoaBinding getPessoa(@PathParam("personName") String name, @PathParam("idade")
int idade, @HeaderParam("CPF") String numCPF) throws IdadeInvalidaException {
    if (idade <= 0 || idade > 120)
       throw new IdadeInvalidaException("Idade Inválida!");
    return new PessoaBinding(name, idade, numCPF);
}
Listagem 12: Uso de exceção de negócio, que é mapeada para Response.
Assim como toda nova tecnologia, JAX-RS não é uma bala de prata, mas sabendo o momento de usá-la se torna uma ferramenta poderosa de integração, em termos de facilidade no desenvolvimento e requerer uma
infraestrutura mais leve, dispensando o uso de um middleware WS-*.
Use e abuse! Diversão garantida!

Consumindo e Testando Clientes REST

terça-feira, 29 de dezembro de 2009



A especificação JAX-RS é uma ótima opção para criar web services REST e fornece meios de desenvolver componentes server-side, mas não descreve como os desenvolvedores devem desenvolver seus componentes client-side em Java, e essa já é uma das promessas para a próxima release do JAX-RS.

Pelo fato de nossos serviços RESTful serem URIs e a forma de acesso a estes serviços serem os próprios métodos HTTP, podemos trabalhar diretamente com requisições HTTP ou utilizar bibliotecas para facilitar este trabalho. Felizmente é relativamente fácil trabalhar diretamente com requests e responses HTTP, e as linguagens mais populares de programação possuem métodos/bibliotecas HTTP, como por exemplo, urllib2 e httplib em Python, libcurl em PHP, HTTPWebRequest em C#, open-uri em Ruby, e o pacote java.net.* e o projeto HttpClient da Apache para Java, entre outros. Mas para qualquer linguagem que seja feito a requisição ao serviço RESTful, temos que passar por alguns passos, conforme segue:
  1. Montar os dados que irão trafegar pelo requisição HTTP, como a URI, HTTP header (se houver), e o método HTTP desejado.
  2. Formatar estes dados como uma requisição HTTP, e enviá-lo para um servidor HTTP apropriado.
  3. Efetuar o parsing dos dados retornados (XML, JSON, etc..) para as estruturas de dados que o seu programa precisa.

Para facilitar a pesquisa, montamos um pequeno guia, para os desenvolvedores e estudiosos que querem aprender um pouco mais sobre REST, onde iremos apresentar algumas bibliotecas para teste e consumo de serviços RESTful.

cURL

Se o intuito for apenas testar os serviços REST desenvolvidos e validar o retorno, o mais simples é utilizar ferramentas existentes na web como é o caso da biblioteca cURL, que é uma ferramenta de transferência de arquivos entre cliente-servidor desenvolvida em C, e suporta protocolos como HTTP, HTTPS, FTP, FTPS, etc.
 A listagem 1 apresenta alguns exemplos de como fazer uma requisição GET e POST com uso da biblioteca cURL, como podemos ver, ela não possui uma interface gráfica, sendo uma ferramenta de linha de comando.
 Fazendo uma requisição (GET), passando como parâmetro de headerv tipo de conteúdo json, (-H "Accept:application/json")


// Fazendo uma requisição POST, passando como  query parameter name = JumboComLtda
$ curl -d name=JumboComLtda http://localhost:8080/Contatos/resources/customers/2/cliente/

// Excluindo um registro com DELETE, pelo parâmetro –X
$ curl -v –X DELETE http://localhost:8080/Contatos/resources/customers/99/


Registro excluído com sucesso !


Listagem 1: Uso da biblioteca cURL.
 

Referências:

RESTClient

 RESTClient é uma aplicação Java própria para auxiliar nos testes de serviços RESTful, complementar a isto, ela pode ser utilizada para testar Web Services POX (Plain Old XML) sobre HTTP. Para utilizar, basta efetuar o download do arquivo jar (com dependências) da ultima versão, no momento que escrevo este artigo, a versão mais recente é a versão 2.3, e vem com duas opções.

A versão GUI, é uma aplicação Swing com diversas opções, e bem conhecida de quem trabalha com o RESTClient desde suas primeiras versões, e a outra versão "cli" é para execução batch de arquivos .rcq. Para começar utilizar a versão em Swing, basta digitar o seguinte comando (A aplicação requer Java 6 para rodar):
$java -jar restclient-ui-2.3-jar-with-dependencies.jar
 
Após executar a aplicação, deverá ser apresentado a tela conforme ilustra a Figura 1.


Figura 01 - Interface Swing do RESTClient.

Pela aparência da interface gráfica, podemos deduzir facilmente o modo de utiliza-lá, basta digitar no campo URL o caminho desejado, selecionar algum método HTTP na aba Method, e executar a consulta clicando no botão [>>]. O resultado será apresentando no bloco HTTP Response.


Funcionalidades

 Com RESTClient, podemos fazer qualquer tipo de requisição HTTP (GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE), ainda existe o suporte a SSL e a possibilidade de adicionar parâmetros de Header adicionais.
É possível salvar as requests, responses, e o Response Body (atráves do menu File > Save Request, ou Save Response, Save Response Body), o que é útil para testes de regressão, que podemos utiliza-los posteriormente na versão de linha de comando.
RESTClient ainda vem com o Conteiner Jetty embutido, que possui um Servlet que imprime os detalhes das requisições submetidas a ele. Para iniciar o servidor basta acessar o menu Tools > Opção Start Trace Server (subirá na porta 10101).

E por fim, uma das funcionalidades mais interessantes é o seu suporte integrado para testes, que podem inclusive ser escritos em Groovy, o suporte a testes é baseado no JUnit 3.x e os tests são atachados a cada requisição. Para iniciar os testes, na aba "Test Script", clique o no botão Insert Template, RESTClient irá criar o código para você, conforme mostra a Listagem 02:
// The test class name should end with `Test'--this is a convention:
public class TemplateClassTest 
    extends org.wiztools.restclient.RESTTestCase{

  // Test method names should start with `test':
  public void testStatus(){
    if(response.getStatusCode() != 200){
      fail("This will fail the test!");
    }
  }
}
Listagem 2: Template de Test gerado pelo RESTClient.

A partir da versão 2.3, RESTClient possui uma versão em linha de comando, está versão é utilizada para executar requisições de forma batch e armazenar o resultado dos testes.  Para executar está versão, basta na linha de comando executar:

$java -jar restclient-cli-2.3-jar-with-dependencies.jar -o /temp/diretorioResponse *.rcq

Esse comando, irá executar todos as requisições contidas nos arquivos de extensão (.rcq) no diretório de execução atual, e irá salvar as responses (na extensão .rcs) no diretório /temp/diretorioResponse. E por fim, o RESTClient, imprime um resumo da execução dos testes. 


Referências:

Testando Web Services RESTful no NetBeans.

 Para quem é usuário do NetBeans, uma outra opção para testar Web Services RESTful é utilizar o suporte do próprio IDE, com um projeto Web criado e os serviços RESTful devidamente configurados, é possível testá-los clicando com o botão direito do mouse em cima do projeto e selecionar a opção “Test RESTful Web Services” (Figura 02), lembrando que está opção só estará disponível, se o projeto WEB possuir serviços WEB.


Figura 02 -Suporte a REST no NetBeans.

Ao selecionar esta opção, será feito o build e o deploy da aplicação web, e ao final do processo será disponibilizado uma página de testes web, como mostra a Figura 03.



Figura 03 - Tela de testes de Web Services RESTful

Na página apresentada é possível testar todos os serviços disponíveis, criar novos parâmetros para a requisição (botão “Add Parameter”), e também é possível selecionar o tipo de método HTTP para teste e o tipo MIME de retorno.

Para iniciar o teste, basta clicar no botão “Test”, após a execução, dentro da seção Response, podemos analisar os dados de retorno, os dados do cabeçalho e o status da chamada.

Além disso, de acordo com os serviços criados, o NetBeans ainda gera o arquivo WADL, visível no canto superior esquerdo da Figura 03.
 
Referências:

JAXB

JAXB (Java Architecture for XML Binding) fornece a API, as ferramentas e um framework que automatiza o mapeamento entre documentos XML e objetos Java. Ou seja, fornece compiladores que compilam Schemas XML para objetos Java. Em tempo de execução podemos deserializar (unmarshal) o conteúdo de um arquivo XML para representações Java.

Além disso, podemos acessar, alterar e validar a representação Java contra regras de um Schema e por fim, podemos serializar (marshal) o conteúdo de um objeto Java em conteúdo XML. Veja sua arquitetura na Figura 04:




Figura 04 - Overview do JAXB.

Esta fora deste artigo um estudo mais aprofundado sobre o JAXB, mas apenas para conhecimento, a API JAXB acabou se tornando a forma padrão de mapeamento entre Java e XML, com JAXB temos anotações que nos permitem criar uma representação em Java de um Schema XML, estas anotações estão presentes no pacote javax.xml.bind.annotations, e possuem anotações associadas a pacotes Java (@XmlSchema, @XmlSchemaType, etc..), a classes Java (@XmlType, @XmlRootElement), a propriedades e campos (@XmlElement, @XmlAttribute), entre outras anotaçõe.

Para exemplificar, considere o exemplo da listagem 3, esta é uma classe POJO representando uma pessoa, com anotações JAXB.  Ao fazer um marshalling de uma instância da classe PessoaBinding para XML, teremos o resultado apresentado na listagem 04.

@XmlRootElement(name="pessoa")
@XmlType(name="", propOrder={"nome","idade","statusCivil"})
public class PessoaBinding {
/* Construtores e Setters omitidos */
    private String nome;
    private int idade;
    private String statusCivil;
    private String cpf;

    @XmlElement
    public String getNome() {
        return nome;
    }
    @XmlElement
    public int getIdade() {
        return idade;
    }
    @XmlAttribute(name="num_cpf")
    public String getCpf() {
        return cpf;
    }
    @XmlElement
    public String getStatusCivil() {
        return statusCivil;
    }
}
Listagem 03 - Classe PessoaBinding com anotações JAXB.

   
       Wagner
       29
       Casado
   
Listagem 04 - XML Gerado após marshalling de classe JAXB PessoaBinding.

A especificação do JAX-RS fornece alguns Entity Providers padrões, entre eles, provedores para JAXB, para quando o tipo de conteúdo trafegado for do tipo xml (application/xml, text/xml e application/*+xml), de modo que o programador não precisa criar código para converter um objeto Java em código XML e vice versa, facilitando muito nossa vida.


Ainda na classe PessoaBinding da  listagem 03, poderíamos então, no nosso exemplo, criar um serviço RESTful cujo retorno seja a classe JAXB PessoaBinding , neste caso a declaração do serviço seria similar ao método da listagem 05.

    @GET
    @Produces("application/xml")
    @Path("/NetFeijao/autor/{idPessoa}/")
    public PessoaBinding getPessoa(@PathParam("idPessoa") Integer id) {
         return dao.getPessoaAsBinding(id); // Retorna uma entidade Pessoa como PessoaBinding
    } 
Listagem 05 - Serviço RESTful cujo retorno é uma classe JAXB.

Ao fazermos o consumo deste serviço RESTful, vamos perceber que a conversão é feita automaticamente pelo entity provider padrão para XML (veja o teste na Figura 05, utilizando a ferramenta RESTClient). De maneira inversa poderíamos criar um serviço RESTful para receber requisições PUT e receber como parâmetro de entrada do método a classe PessoaBinding via HTTP Body.  Conforme apresenta a listagem 06:





Figura 05 - Retorno do serviço RESTful cujo retorno é uma classe JAXB.

    @PUT
    @Consumes("application/xml")
    @Path("/NetFeijao/")
    public void putPessoa(PessoaBinding pessoa) {
        // Operação de update
    } 
Listagem 06 - Convertendo código XML para objeto JAXB em chamada PUT com REST.



Referências:

JAKARTA COMMONS - HTTP CLIENT

HttpClient é um subprojeto open source da Jakarta Commons que se tornou independente em 2007, e que foi concebido para facilitar o desenvolvimento de aplicações que utilizam o protocolo HTTP.
 Ele é um projeto escrito totalmente em Java, e implementa todos os métodos HTTP (GET, POST, PUT, DELETE, HEAD, OPTIONS e TRACE).

Possui suporte ao protocolo HTTPS, suporte ao gerenciamento de conexões para uso em aplicações multi-thread, suporte a cookie, possui mecanismos de autenticação Basic, Digest e criptografia NTLM.

 Na listagem 07, demonstramos o uso da biblioteca HttpClient, onde consumimos dois serviços RESTful, um com uma chamada GET e outra com uma chamada PUT.

     public void testHTTPClient() {
        try {
            HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager());
            client.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
            final String CONTENT_TYPE = "application/xml";
            final String CHARSET = "UTF8";

           /* Executando chamada com método HTTP GET */
        String getURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/Wagner/?idade=29";
        GetMethod get = new GetMethod(getURI);
        Header meuHeader = new Header("CPF","123456789");
        get.setRequestHeader(meuHeader);
        int statusCodeGET = client.executeMethod(get);
        String responseBody = get.getResponseBodyAsString();
        System.out.println("Chamada GET");
        System.out.println(" Status Code: "+statusCodeGET+" \nResponse Body:\n"+responseBody);

         /* Executando chamada com método HTTP PUT */
       String putURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/update/";
       PutMethod put = new PutMethod(putURI);
    StringRequestEntity requestEntity = new StringRequestEntity(responseBody, CONTENT_TYPE, CHARSET);
        put.setRequestEntity(requestEntity);
        int statusCodePUT = client.executeMethod(put);
        responseBody = put.getResponseBodyAsString();
        System.out.println("Chamada PUT");
        System.out.println(" Status Code: "+statusCodePUT+" \nResponse Body:\n"+responseBody);
    } catch (Exception ex) {/* OMITIDO */}
}
Retorno da chamada ao método.
Chamada GET
 Status Code: 200
Response Body:

  
       Wagner
       29
       Casado
  


Chamada PUT
 Status Code: 202
Response Body:

Bem vindo Wagner


Listagem 07: Consumindo serviços REST via GET e PUT com HTTPClient.

Primeiro, na linha 3 instanciamos a classe HttpClient que é o nosso agente HTTP que irá conter os atributos de persistência com cookies, e credenciais de autenticação através da classe HttpState. E também onde será armazenado uma ou mais conexões HTTP, cujo qual faremos chamadas aos métodos HTTP.

Na linha 4 atribuímos um timeout para a conexão de 30 segundos. Depois nas linhas 5, 6 e 9 declaramos as variáveis quer irão determinar o tipo de conteúdo, o character set e a URI de acesso ao serviço REST.

Na linha 10, instanciamos a classe GetMethod, que como o próprio nome indica representa o método GET, passando como parâmetro a URL do nosso serviço RESTful (getURI). Na linha 11 criamos um objeto Header, passando como parâmetro no construtor a chave e o valor que representam o parâmetro e o valor do cabeçalho, no nosso exemplo, passamos um número fictício de CPF. Na linha 12 atribuímos o objeto header para o objeto GetMethod.

 Na linha 13, fazemos a chamada ao serviço RESTful via HTTP GET, e armazenamos o código de status do retorno na variável statusCodeGET, na linha 14 extraímos os dados da Response como String para a variável responseBody. Pelo fato do retorno ser em XML, poderíamos facilmente utilizar JAXB para trabalhar o retorno como um objeto Java. Finalmente nas linhas 15 e 16 imprimimos no console o retorno da chamada a estes métodos.

A partir da linha 18, iniciamos o mesmo processo, mas agora para efetuar uma chamada via método PUT, as únicas diferenças, são o uso do método PutMethod, que implementa o método HTTP PUT e o uso da classe StringRequestEntity na linha  21,  com esta classe atribuímos uma entidade como String ao método PUT que será enviado junto a requisição.

Nas linhas 25 e 26 imprimimos o retorno da requisição PUT.

JavaScript:




Graças ao objeto XMLHttpRequest conseguimos nos comunicar com servidores de forma assíncrona,   desde então temos todas as vantagens do AJAX ao nosso dispor.  Para quem desenvolve interfaces WEB, este recurso resolveu grandes problemas no lado do cliente, mas vale lembrar que JavaScript não é Java, não possui threads, nem tipos, e possui uma grande gama de frameworks Ajax, como por exemplo Prototype, JQuery, Dojo, Script.aculo.us, Ext-JS, entre outros.

 Na listagem 08, temos um exemplo de uma função em JavaScript  que consume um serviço RESTful cujo retorno é um XML.




var xmlHttp;
function showCustomer(str){ 
    xmlHttp=GetXmlHttpObject(); // omitido código do método0
    if (xmlHttp==null) {
        alert ("Your browser does not support AJAX!");
        return;
    }
    var url='http://localhost:8080/Contatos/resources/customers/58/';
    xmlHttp.onreadystatechange=stateChanged;
    xmlHttp.open('GET',url,true);
    xmlHttp.send(null);
}

function stateChanged() { 
    if (xmlHttp.readyState==4){
        var xmlDoc=xmlHttp.responseXML.documentElement;
        document.getElementById("nome").innerHTML= 
        xmlDoc.getElementsByTagName("name")[0].childNodes[0].nodeValue;
    }
}
Listagem 08 - Consumindo um serviço RESTful (retorno XML) com Ajax.

Na listagem 08, vimos um exemplo de um serviço que retorna XML, mas uma das grandes vantagens dos serviços REST, é que podemos trabalhar com diversos formatos para troca de informação de um mesmo recurso. Entre eles JSON.

jQuery



JQuery é uma biblioteca JavaScript que vem chamando atenção por conta de sua facilidade de desenvolvimento, ela simplifica muito a manipulação dos elementos de um documento HTML, o tratamento de eventos e as interações Ajax para prover um desenvolvimento rápido de aplicações web, livrando o desenvolvedor de preocupações relacionadas a compatibilidade de navegadores e aderência a CSS.

A biblioteca jQuery fornece algumas funções para tratamento de requisições Ajax, ideais para o consumo de serviços REST, que reduzem muito a complexidade e a quantidade de linhas necessárias para consumir um serviço REST.  Com a função $.ajax() do jQuery, conseguimos um alto nível de controle nas requisições ajax.

A sintaxe do comando é $.ajax(options), onde o parâmetro options são as propriedades que passamos para controlar como a requisição é feita e retorno da chamada.
Na listagem 09, demonstramos o uso das funções $.ajax().
$.ajax({
    type: ‘DELETE’,
    url: "http://localhost:8080/ProjetREST/NetFeijao/autores/"+idAutor+"/",
    success: function(msg){
        $("#alert").html(msg);
    }
});
Listagem 09 - Consumindo um serviço REST com a função $.ajax().

Na listagem 09, usamos dois parâmetros na função $.ajax(), o parâmetro type para indicar o método HTTP que queremos executar e a url de chamada.

Para tratar tipos de retorno JSON, o jQuery oferece a função $.getJSON(), utilizada para carregar dados JSON mediante uma requisição HTTP GET.

Na listagem 10 mostramos um exemplo de uso da função $.getJSON() em um serviço REST do Flickr, nós fazemos uma chamada ao serviço REST e passamos o retorno da chamada ao método de callback. Dentro da função de callback criamos a tag passando como valor o endereço da foto retornada pelo serviço REST e a incluímos na div #foto. Note que a variável data, é um map chave-valor dos dados retornados pela função REST.
$.getJSON("http://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos& photoset_id=72157614488723406&format=json&jsoncallback=?",
function(data){
    $.each(data.photoset.photo, function(i,item){
        if (item.title == foto){
            $("").attr("src", "http://farm"+item.farm+".static.flickr.com/"+item.server+"/"+item.id+"_"+item.secret+"_m.jpg").appendTo("#foto");
        }
    });
});
Listagem 10 - Uso da função $.getJSON para consumo de dados no formato JSON.

É isso aí, consumir serviços REST é diversão garantida !!! E a todos um Feliz Ano Novo repleto de código \o/ !!!

[Just Java 2009] De Web Services RESTful a aplicações Mashup

segunda-feira, 5 de outubro de 2009

Nos dias 15 a 17 de Outubro, aconteceu no Centro de Convenções do Senac de Santo Amaro, mais uma edição do Just Java. E como sempre, esta foi uma ótima oportunidade para aprender novas tecnologias e fazer aquele Network.



Apresentei no auditório principal, a palestra "De Web Services RESTFul a aplicações Mashups", onde pude abordar os conceitos de REST proposto pelo Dr. Roy Fielding, passando pela especificação JAX-RS, que define API para criação de Web Services, demonstrando várias maneiras de consumir e testar serviços REST, até chegar ao mundo dos Mashups, apresentando várias ferramentas com exemplos de uso .

Por fim foi apresentado uma demo, que infelizmente por falta de acesso a internet, não pude apresentar em sua plenitude =(.
Para ver o restante da programação e baixar as apresentações que rolaram no evento, acesse este link.







Fotos: Crédito de Eduardo Quagliato -Link: JustJava 2009 no Flickr – Compartilhamento de fotos!

Segue abaixo a apresentação.
 Diversão Garantida !!!

Just Java 2009 - O principal evento da comunidade Java Brasileira

quarta-feira, 9 de setembro de 2009



Nos dias 15, 16 e 17 de Setembro acontece em São Paulo o Just Java 2009. Será a 8a. edição do principal evento da Comunidade Java Brasileira.
A grade do evento já está disponível no site http://grade.justjava.com.br/
Esse ano vou apresentar a palestra "De Web Services RESTFul a aplicações Mashups: Como chegar lá".
Onde vou apresentar o conceitos de REST, falar sobre especificação da JSR-311 que define o JAX-RS , falar sobre frameworks de teste, como consumir serviços REST e finalmente falar sobre Mashups, e a importância de REST neste contexto.
 Para se inscrever, acesse o site do evento aqui.

Diversão Garantida!!!

Web Services WS-* vs REST.

quinta-feira, 14 de maio de 2009

Muitos sites, blogs e fóruns têm colocado seus pontos de vista em relação ao uso de web services REST e SOAP, gerando muitas vezes calorosas discussões.

Na verdade, não existe uma disputa entre eles, pois cada um possui uma proposta bem diferente. Vários estilos diferentes de aplicações tem sido utilizadas para integrar sistemas de informação corporativos, entre as opções, existem os banco de dados compartilhados, transferência de arquivos (EDI ), remote procedure call (RPC), ou troca de mensagens assíncronas via uma sistema de mensageria. Ao fazermos uma comparação entre REST e WS-* (pronucia-se ws-star), precisamos fazer uma comparação quantitativa baseado em princípios arquiteturais que envolvem questões relacionadas a cenário, tecnologia, métodos, formato dos dados trafegados, segurança, transação, entre outros fatores da sua aplicação. Devemos lembrar que estas tecnologias surgiram para suprir estes problemas recorrentes na maioria dos projetos de software, que é a interoperabilidade.

Foi quando começaram a surgir esforços da comunidade de buscar dos grandes players interoperabilidade entre suas plataformas, aplicações, e linguagens de programação. Foi quando surgiram as especificações WS-*, que atendem tanto ao estilo RPC quanto mensageria. A especificação SOAP não define como deve ser um message header, ou elementos do corpo do envelope, dessa maneira podemos ter aplicações que customizem o tipo de header que ela aceita, e o tipo de informação que deve estar vinculado ao body para uma operação em particular, sem falar que algumas dessas informações podem ser compartilhadas por diferentes aplicações, sem falar em questões de segurança, roteamento de mensagens, entre outros fatores.

As especificações WS-* definem padrões para mensagem, troca de metadados, segurança, entre outros. No mundo Java, para implementar este mundo de especificações, foi aberto o projeto WSIT (antigo projeto Tango) como parte do projeto Metro, que por sua vez faz parte do projeto Glassfish, veja a Figura 01 os padrões (em verde) utilizado no projeto WSIT.

Figura 1: Padrões de Web Services utilizados no WSIT.

É claro que para a maioria dos projetos, um web service simples resolveria, mas se começarmos a entrar mais a fundo no mundo orientado a serviços, começa a surgir a necessidade de integração com diversos sistemas, naturalmente teremos que utilizar estes padrões. É somente olhar para a figura 01 que já causa calafrios em muitos desenvolvedores, mesmo com suporte eficiente nos IDEs existentes.

Com isto, vemos claramente que a arquitetura de web services baseadas nas especificações WS-* é muito bem definida, com regras para trocas de dados, segurança, o que por conta de seu excesso de padrões acabou se tornando uma solução muito complexa.

Mesmo com toda a complexidade, serviços WS-* têm tomado cada vez mais espaço no mercado, graças aos projetos SOA que tem adotado largamente serviços WS-* por sua independência e transparência de protocolo. Por outro lado, REST é muito mais simples, como uma resposta para todos estes padrões e especificações, para utilizar REST basta ter um conhecimento razoável sobre HTTP e seus métodos.

Enquanto web services WS-* são orientados a atividade/serviço, serviços REST são orientados a recurso. Quando falamos em desenvolver serviços SOAP, estamos falando em criar APIs, contratos (WSDL), onde o WSDL descreve os detalhes de implementação, como as operações e os tipos de dados trafegados. REST por outro lado, conforme explicado no inicio diz respeito a utilizar o protocolo HTTP para manipular o estado de um recurso. Fazendo uma analogia, podemos dizer que assim como a linguagem de manipulação de dados (DML) do SQL é utilizada para manipular as informações de um banco de dados transacional, REST utiliza os métodos (verbos) do protocolo HTTP para manipular o estado de uma informação. Com estes verbos, podemos fazer praticamente tudo o que quisermos com os dados, independente se usarmos SQL ou HTTP.
Ao mapear os métodos HTTP (POST, DELETE, GET E PUT) com operações DML de um banco de dados temos a seguinte estrutura, conforme ilustra a tabela 01.

Métodos HTTP / Operações CRUD
GET -> SELECT
POST -> INSERT, UPDATE
PUT -> INSERT, UPDATE
DELETE ->DELETE

Tabela 01. Associação dos métodos HTTP com operações CRUD.
Na tabela podemos notar que podemos ter mais de uma operação relacionada a um verbo HTTP, como por exemplo, o método POST, que pode ser utilizado para diversas ações. O método PUT nos dá a possibilidade de criar um novo recurso, ou substituir por outro mais atualizado. Apesar dos diversos tutoriais e exemplos que encontramos na internet sobre REST que envolvem operações CRUD, isso não quer dizer que temos que ficar presos somente a estes tipos de operações. Por conta de sua própria natureza, REST é mais fácil e funciona muito bem com CRUDs, mas podemos em nosso design criar serviços REST. Web Services RESTful.



Pontos Positivos
Pontos Negativos
  • Linguagem e plataforma agnóstica.
  • Simplicidade, interface imutável.
  • Interação assíncrona, não possui estado.
  • Facilidade de adoção, pois não requer uma grande infra-estrutura, muito menos um middleware para WS-* ou camada intermediária adicional.
  • Utiliza a própria web como meio de transporte, sendo assim uma carga baixa para a rede.
  • Utilizada por grande parte das aplicações Web 2.0. (Google, Flickr, Amazon, etc..). Portanto, ótimo para mashups.
  • Curva de aprendizagem baixa.

  • Faltam padrões.
  • Falta de segurança (dados sigilosos não deveriam ser enviados como parâmetros na URI).
  • Não é indicado para trafegar grandes volumes de parâmetros via URI, no caso de PUT/POST para inclusão de dados, por exemplo.
  • Em muitas empresas apenas os métodos GET e POST do HTTP são liberados em proxies e firewalls. Dentro desta limitação, muitos preferem utilizar os métodos GET para requisições de consulta e POST para todo o resto.
  • Não há mecanismos de transação (Do it yourself)
  • Não existe um padrão como UDDI para service discovery.

Tabela 02: Pontos positivos e negativos de REST

SOAP


Pontos Positivos
Pontos Negativos


  • Diversas ferramentas de desenvolvimento.
  • Tipagem forte e um vocabulário bem definido.
  • Quando utilizado sobre HTTP, dificilmente é bloqueado por proxies e firewalls.
  • Permite o uso de diferentes tipos de protocolos.
  • Plataforma independente.
  • Linguagem independente.
  • Diversos padrões.
  • Complexidade dos padrões.
  • Performance.
  • Mensagens podem ficar muito extensas, por serem codificadas com XML
Tabela 03: Pontos positivos e negativos com SOAP.

Fazendo esta pequena análise, chegamos á conclusão de que ambas as soluções são úteis, e a utilização de cada uma depende do contexto em que será aplicada.

Referências (Links):

[Parley] A Little REST and Relaxation: http://tinyurl.com/cm33t2
Estilo SOAP vs Estilo REST: http://www.ibm.com/developerworks/webservices/library/ws-restvsoap/
Descrevendo Serviços REST com WSDL 2.0: http://www.ibm.com/developerworks/webservices/library/ws-restwsdl/
Bruno Pereira: http://brunopereira.org/2008/05/14/precisamos-de-um-descritor-de-servicos-rest/

Entendendo REST (REpresentational State Transfer)

quarta-feira, 27 de agosto de 2008

Você já precisou explicitamente utilizar algum método (PUT, DELETE, POST, GET) do protocolo HTTP, muito dificil, geralmente quando o fazemos, nós fazemos isto ao desenvolver uma aplicação web para especificar o tipo de submit, enfim, agora encontraram uma solução muito útil para utilizar os tais métodos, que é através de REST (REpresentational State Transfer), que é o nome dado por Roy Fielding em sua tese de doutorado, muita gente confunde REST com Web Services SOAP, mas ambos são totalmente diferentes.

REST são serviços stateless e arquiteturas baseadas nela são construídas a partir de "pedaços de informação" únicas identificadas por URIs. Em sistemas REST, os recursos são manipulados através da troca de representações do recurso.

Ex.:
http://netfeijao.blogspot.com/colecao/marvel/spiderman/3

Neste exemplo, atráves desta URI estamos definindo como a URI mapeia nossos recursos, no exemplo fica muito fácil entender como funciona, identificamos nossa chave primária (3) no último elemento, e o nome da coleção (spiderman), podemos ainda definir um serviço que me retorne uma coleção de objetos do spiderman caso seja omitido a chave primária,

Por as URIs serem únicas ganhamos uma busca otimizada e posso ter multiplas representações oferecendo esta informação em vários tipos de formatos como XML, JSON e XHTML.

Temos um DE-PARA dos métodos HTTP com as funções CRUD que queremos desempenhar em um sistema baseado em REST, conforme tabela abaixo:

Características dos métodos HTTP em REST

Método GET.

Utilizado para retornar informação de acordo com a URI informada.
Não deve uma mudança de estado
Fica no cache.

Método POST

Utilizado para adicionar uma nova inforamação

Métodp PUT
• Utilize PUT para alterar uma informação
• Controle total na entidade utilizada quando o ID ou chave primária é conhecido

Ex.: PUT /colecao/marvel/spiderman/3-456789012


Método DELETE
Remove (logicamente) uma entidade
Ex.: DELETE /colecao/marvel/spiderman/3 (Exclui Spiderman nº 3)


Benefícios do REST.

Serviços baseados em REST são muito fáceis de entender e de se trabalhar, pois o cliente que vai utilizar o serviço REST não precisa utilizar nenhuma API especializada, ele utiliza apenas HTTP padrão =), podemos usar nosso browser para testes e experimentos.
URI é uma maneira uniforme de identificar recursos e o HTTP é o meio utilizado para manipular estes recursos.
Fácil consumir e desenvolver com linguagens de scripting..


Web Services SOAP vs Serviços REST

SOAP WS.

  • Poucas URIs, muitos métodos customizados
  • comicsPort.getComics("spiderman")
  • Utiliza HTTP para trafegar mensagens SOAP.
  • Muitos padrões (WS-*)
  • Deve seguir um contrato WSDL.
Web Services baseados em SOAP diz respeito a SOA.

ex: Serviço de venda de quadrinhos
comicService.vender("spiderman", 3, 250);

RESTful WS.
  • Muitos recursos (URIs), poucos métodos fixos.
  • HTTP é o protocolo de transporte.
Web Services baseados em REST diz respeito a um novo conceito chamado de ROA
(Resource-Oriented Architecture)

ex: Recurso de venda de quadrinhos

POST /colecao/marvel/spiderman/3-250

Para a construção de serviços baseados em REST em Java, foi disponibilizada o JAX-RS, que é uma API para Web Services RESTful, em breve vou blogar com exemplos no GlassFish