A partir da especificação JSR-311, presente na plataforma Java Enterprise a partir da versão 6 (JEE 6), alguns frameworks foram desenvolvidos com o intuito de implementar esta especificação. Um desses frameworks é o RestEasy, que além de implementar a especificação, ainda foi incorporado nativamente ao servidor de aplicação JBoss AS7, facilitando a utilização dos web services Rest. Existem outros frameworks que implementam esta mesma especificação, inclusive o Jersey, framework que serviu como base para a JSR-311. Porém, pela facilidade de implementação e por este ser um artigo introdutório, o framework que iremos utilizar neste artigo é o RestEasy (o nome é bem sugestivo).
Para realizar o exemplo deste artigo, é necessário que se tenha o servidor de aplicação JBoss AS7 instalado e configurado, juntamente com o IDE Eclipse para JEE. Partindo deste ponto, vamos iniciar nossa aplicação criando um novo Dynamic Web Project no Eclipse, conforme observado na Figura 1. Esta figura mostra também que foi selecionado o JBoss 7.1 como servidor de aplicação (lembre, aquele servidor já configurado). Após isso, vamos em next, até a tela onde informaremos ao IDE que desejamos que gere o nosso Deployment Descriptor, ou mais conhecido web.xml, conforme pode ser visto na figura 2. Após isso, clique em finish.
Figura 1: Criando um novo Dynamic Web Project
Figura 2: Configurando o Deployment Descriptor
Pronto, agora vem a parte interessante. Para ficar mais claro o entendimento da aplicação, vamos separar as coisas. A nossa aplicação será dividida em duas partes, e cada parte será composta por apenas uma classe. Uma classe representará o serviço Rest, a chamaremos de SimpleService, e a colocaremos dentro de um pacote chamado resource, pois na realidade esta classe é realmente um recurso. A outra classe será responsável por consumir este serviço, será chamada de Client e estará dentro de um pacote chamado main.
Inicialmente iremos analisar a classe SimpleService. Esta classe representa um recurso determinado pela URI product, conforme pode ser visto na Listagem 1. Complicou? Vamos explicar melhor. A anotação @Path, de acordo com a especificação JAX-RS, permite que a nossa classe seja reconhecida como um recurso web. Esta anotação determina um identificador único para este recurso, no caso @Path(/product). Além disso, os métodos HTTP podem ser mapeados para métodos Java de uma classe recurso. Anotações como @GET e @POST são utilizadas para realizar esse mapeamento. Outra característica importante é o tipo de representação de retorno do serviço, definido pela anotação @Produces. Esta anotação utiliza a enum MediaType para definir os tipos de dados possíveis de retorno.
Listagem 1: Classe SimpleService
package resource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/myResource")
public class SimpleService {
@GET
@Produces(MediaType.TEXT_HTML)
public String getSimpleProduct() {
return "IPad";
}
}
Para nosso exemplo, a URL http://localhost:8080/restfulExample/product acessa o recurso product, obtendo como retorno o texto “IPad” em HTML. Existem muitas outras possibilidades para se utilizarem com as classes recurso, também trazidas pela especificação JAX-RS, mas como fogem ao objetivo deste artigo, serão tratadas em um outro momento.
A próxima classe a ser analisada é a Client. Esta classe utiliza a própria plataforma Java para obter uma conexão HTTP. Inicialmente, a partir da classe URL, se obtém um objeto que representa a própria URL, mais precisamente a URL do recurso disponibilizado. Esse objeto é utilizado para se abrir uma conexão HTTP a partir da classe abstrata HttpURLConnection. Estas classes estão presentes no pacote java.net. Com a conexão HTTP em mãos, é possível se manipular métodos e propriedades do próprio protocolo HTTP. A seguir, informamos que a conexão será baseada no método HTTP GET, e que terá como conteúdo texto HTML. Após isso, verificamos se o código de resposta é 200 (código HTTP de sucesso) , significando que tudo ocorreu bem. Se isso ocorrer, será obtida uma Stream a partir da conexão HTTP, e será mostrado no console do servidor o nosso produto. Caso contrário, uma exceção com o código HTTP de erro será mostrado no console. A classe Client pode ser vista na Listagem 2.
Listagem 2: Classe Client
package main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Client {
private static int HTTP_COD_SUCESSO = 200;
public static void main(String[] args) {
try {
URL url = new URL("http://localhost:8080/restfulExample/myResource");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-type", "text/html");
if (conn.getResponseCode() != HTTP_COD_SUCESSO) {
throw new RuntimeException("HTTP error code : "+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String saida;
System.out.println("Output from Server .... \n");
while ((saida = br.readLine()) != null) {
System.out.println(saida);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Quase pronto. Por fim, precisamos realizar algumas configurações no Deployment Descriptor, ou web.xml. O framework RestEasy recebe opções de configuração no elemento <context-param>, dentro do Deployment Descriptor. Existem dois tipos de configurações possíveis. O primeiro tipo de configuração é utilizando-se o parâmetro resteasy.resources, conforme ilustrado na Listagem 3. Este parâmetro delimita uma lista de classes que podem ser registradas como um recurso. Em nossa aplicação, poderíamos mapear a classe SimpleService, dentro do pacote resource na aplicação.
Listagem 3: Configuração de uma classe recurso no web.xml
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>resource.SimpleService</param-value>
</context-param>
Outro tipo de configuração possível é utilizar-se o parâmetro resteasy.scan, ilustrado na Listagem 4. Este parâmetro permite que as classes recurso possam ser identificadas automaticamente pelo framework, não sendo necessário informar uma a uma as classes recurso no Deployment Descriptor.
Listagem 4: Configuração de identificação automática das classes recurso
<context-param>
<param-name>resteasy.scan </param-name>
<param-value>true</param-value>
</context-param>
Por fim, o principal mapeamento a ser realizado no web.xml é a definição do servlet que será responsável por redirecionar todas as requisições feitas ao REST. Este servlet pertence ao próprio framework, e está mapeado para responder a qualquer url que contenha um recurso válido, conforme pode ser observado na Listagem 5.
Listagem 5: Mapeamento do Servlet responsável por tratar requisições ao serviço Rest
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Feito isso, podemos testar nosso exemplo. Execute o JBoss AS 7 e abra em seu browser favorito a url http://localhost:8080/restfulExample/product. Como o retorno é um html simples, o browser consegue identificá-lo sem problemas, conforme mostrado na Figura 3. Agora, vamos executar o a classe Client. Ainda com o JBoss AS 7 em execução, vá à classe Client e a execute-a como Java application. Devemos obter uma resposta como mostrado na Figura 4.
Figura 3: Resultado mostrado no browser
Figura 4: Resultado mostrado no console
Se tudo ocorreu bem, obteremos uma saída no console como a vista na figura. Caso contrário será recebido um código HTTP de erro. Se isso ocorrer, procure certificar-se que o servidor está em execução, ou se a URL está correta.
Bom pessoal, por hoje é isso, até um próximo post, abraço.