Serviços RESTful com Apache CXF e Camel

Veja neste artigo uma abordagem sobre a construção de serviços RESTful utilizando os frameworks Apache CXF e Apache Camel. Veremos também um resumo dos princípios arquiteturais de REST.

Neste artigo vamos abordar uma nova arquitetura para construção de serviços. Estamos falando de serviços Restful baseados nos princípios arquiteturais definidos por REST. Utilizaremos os frameworks Apache CXF e Apache Camel para demonstrar como é simples implementar serviços que seguem o padrão Restful construídos com a especificação JAX-RS.

Figura 1. Operações HTTP para serviços Restful

De forma bem simples, REST (Representation State Transfer) é um conjunto de princípios. A promessa é que uma vez seguidos esse conjunto de princípios enquanto você desenha a sua aplicação, ao final você terá um sistema que explora e faz uso de todo o benefício da arquitetura Web. Vamos ver rapidamente quais são os princípios:

Seguindo esses princípios, conseguimos ter soluções com comportamentos bem definidos, escaláveis e mais facilmente interoperáveis já que consumir uma URL é algo facilmente realizado por qualquer cliente HTTP..

Um serviço Restful é uma aplicação construída dentro dos princípios explicados. Existe uma API Java conhecida por JAX-RS que pretende trazer a mesma facilidade para construção de serviços Restful que JAX-WS traz para a construção de WebServices.

Vamos agora examinar um exemplo muito simples de construção de serviço Restful utilizando o Apache CXF e Apache Camel. No nosso exemplo, o CXF é o responsável pela execução do servidor HTTP, características de transporte e ciclo de vida do serviço. O Apache Camel será a implementação do serviço gerênciado pelo CXF. Vamos dar uma olhada no serviço HelloWorldServiceRest na listagem 1.

@Path("/helloworldservice") public class HelloWorldServiceRest { @GET @Path("/hello") @Produces("application/json") public String hello(@QueryParam("nome") String name) { return null; } }
Listagem 1. Interface do Serviço Restful

É bem simples. Vemos uma primeira anotação @Path, determinando parte da url que dá acesso ao nosso serviço. Uma operação chamada “hello” anotada com @GET indicando que o verbo GET é suportado. @Produces indica o MIME type do retorno desse método. @QueryParam captura o parâmetro nome passado na URL. Veja um exemplo de chamada dessa operação que pode ser facilmente testado em um navegador da internet: http://localhost:8090/hello/helloworldservice/hello?nome=John.

Na listagem 2 vemos o nosso arquivo de configuração do Spring que inicia o nosso serviço no endereço físico “http://localhost:8090/hello”. Através do namespace cxf, temos acesso ao bean rsServer que utiliza a classe da listagem 1 para iniciar nosso serviço na porta configurada.

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://camel.apache.org/schema/cxf" xmlns="http://www.springframework.org/schema/beans" xmlns:camel="http://camel.apache.org/schema/spring" xsi:schemaLocation=" http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" > <cxf:rsServer id="server" address="http://localhost:8090/hello" serviceClass="br.com.devmedia.helloworldservice .HelloWorldServiceRest"></cxf:rsServer> <bean id="routeBuilder" class="br.com.devmedia.helloworldservice.camel.HelloWorldServiceRouteBuilder" /> <camelContext xmlns="http://camel.apache.org/schema/spring"> <routeBuilder ref="routeBuilder" /> </camelContext> </beans>
Listagem 2. Arquivo de configuração do Spring

Reparem que temos também o camelContext, responsável por gerenciar a execução das rotas. No nosso caso especial, as rotas dizem respeito à implementação do serviço e estão descritas na classe br.com.devmedia.helloworldservice.camel.HelloWorldServiceRouteBuilder. Veja a listagem 3.

from("cxfrs:bean:server") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { Message inMessage = exchange.getIn(); String operationName = inMessage.getHeader(CxfConstants. OPERATION_NAME, String.class); MessageContentsList list = exchange.getIn().getBody( org.apache.cxf.message.MessageContentsList.class); org.apache.cxf.message.Message cxfMessage = inMessage.getHeader( CxfConstants.CAMEL_CXF_MESSAGE, org.apache.cxf.message.Message.class); ServletRequest request = (ServletRequest) cxfMessage.get("HTTP.REQUEST"); String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class); if ("hello".equals(operationName)) { String nome = request.getParameter("nome"); if (nome == null) { Response r = Response.status(404). entity("Nome nao pode ser nulo " + path).build(); throw new WebApplicationException(r); } else { exchange.getOut().setBody("Hello " + nome); } } } });
Listagem 3. Builder para rotas do Camel

A rota inicia-se com from(“cxfrs:bean:server”). Isso quer dizer que estamos consumindo qualquer tipo de dado que vier do bean server, que é o id do cxf:rsServer. Mas não estamos, de fato, interessados em qualquer conteúdo. Um pouco mais abaixo, obtemos o nome da operação que foi invocada pelo cliente através do “header” da mensagem encapsulada pelo apache Camel dentro do objeto exchange.

Reparem que para implementarmos a lógica da operação “hello” da Listagem 1, basta fazermos “if “hello”.equals(operationName)”. A nossa lógica é bem simples: apenas retornamos “Hello” concatenado ao nome passado por parâmetro. Se o nome for nulo, retornamos status 404. O resultado deve ser passado de volta ao camel, através do exchange.getOut().setBody(..).

Na listagem 4 veremos um exemplo de código de cliente para esse serviço.

WebClient client = WebClient.create( "http://localhost:8090/hello/helloworldservice"); client.accept("application/json").type("application/json").path("/hello") .query("nome", "John"); String result = client.get(String.class); Assert.assertEquals("Hello John", result);
Listagem 4. Cliente para serviço Restful

Na listagem 4 fica claro como é fácil interagir com esse tipo de serviço. A classe WebClient faz parte do framework apache CXF. Através dela configuramos o endereço físico, o MIME type das mensagens que transmitimos e aceitamos os parâmetros (nesse caso “nome”) e obtemos o resultado. Existem outros métodos interessantes nessa classe que o leitor deve olhar com mais calma.

Esse exemplo simples demonstrou como é fácil darmos início a um projeto de serviço Restful se usarmos o suporte e os frameworks corretos. Para melhor entendimento do que foi dito sobre REST e RESTFUL, recomendo o excelente livro RESTful Java with JAX-RS escrito pelo grande Bill Burke. É uma verdadeira aula de como construir uma infra-estrutura SOA baseada em ideias relativamente simples.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados