Combinando Apache CXF com Spring Framework

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (3)  (0)

Veja neste artigo como trabalhar com o Apache CXF junto com o Spring Framework, utilizando um arquivo de descrição de web service (WSDL) previamente estruturado.

Nesse artigo vamos explorar o framework Apache CXF e como criar e publicar um WebService simples de forma prática e rápida utilizando o Spring framework para aumentar nossa produtividade.

O Apache CXF é um framework de integração que dá suporte à criação de serviços no padrão WebService. Através dele podemos criar e consumir serviços, utilizando código Java e configuração do framework Spring. Nesse artigo vamos utilizar um WSDL pronto para demonstrar como trabalhar com o Apache CXF junto com o Spring Framework.

O WSDL que utilizaremos é bem simples e oferece apenas uma operação que retorna obrigatoriamente uma resposta de sucesso ou um erro. Operações que trabalham requisição / resposta de forma síncrona são ditas que seguem o MEP (message exchange pattern) Request / Reply. Erros são comumente chamados de Fault.

Listagem 1: WSDL do serviço de exemplo





	
	 
		
		
		
		
			
				
			
		
		
			
				
			
		
		
			
				
			
		
	 
	
	
	
		
	
	
	
		 
	
	
	
		
	
	
	
		
			A operacao digaOla recebe um nome por parametro e devolve
			um cumprimento ou erro em situacoes especificas
		
		
			
			
			
		
	
	
	
		
		
			
			
				
			
			
				
			
			
				
			
		
	
	
	
		
			
		
	

Estrutura do WSDL

Figura 1: Estrutura do WSDL

Agora, vamos ao trecho do nosso projeto maven. O projeto completo e outros arquivos você poderá consultar no repositório github para esse artigo.

Listagem 2: Dependências especiais do nosso projeto

	    
	        org.springframework
	        spring-beans
	        ${spring.version}
	    
	    
	        org.springframework
	        spring-core
	        ${spring.version}
	    
	    
	        org.springframework
	        spring-test
	        ${spring.version}
	        test
	    	    
	    
	        org.springframework
	        spring-context
	        ${spring.version}
	    
	    
	        org.apache.cxf
	        cxf-api
	        ${project.version}
	    
	    
	        org.apache.cxf
	        cxf-rt-core
	        ${project.version}
	    
	    
	        org.apache.cxf
	        cxf-rt-transports-http
	        ${project.version}
	    
	    
	        org.apache.cxf
	        cxf-rt-transports-http-jetty
	        ${project.version}
	    
   	    
	        org.apache.cxf
	        cxf-rt-frontend-jaxws
	        ${project.version}
	    

Vemos várias dependências de Spring e CXF, sendo que as do CXF chamam bastante atenção porque têm palavras tais como transports e frontend. Isso não é por acaso. O diagrama de arquitetura do CXF (Figura 1) demonstra a separação das responsabilidades em módulos distintos, permitindo um ajuste fino do framework à real necessidade do projeto.

Um front-end nada mais é do que um modelo de programação. Usamos JAX-WS ou JAX-RS, mas poderíamos trabalhar com “Simple” ou JavaScript ou ainda algo totalmente novo que nós podemos inventar. Assim como o front-end, o Apache CXF suporta transportes diferentes. Nesse caso estamos expondo nosso WebService através de um servidor HTTP, por isso utilizamos os transportes selecionados, mas poderíamos utilizar JMS, SMTP, Local, Servlet e outros tantos mais. Uma observação importante: no WSDL definimos um transporte através do elemento “binding” em seu atributo “transport”. Em nosso exemplo utilizamos “http://schemas.xmlsoap.org/soap/http” que só funcionará se o CXF reconhecer esse namespace através de seus componentes.

Visão de módulos arquiteturais do Apache CXF

Figura 2: Visão de módulos arquiteturais do Apache CXF

Vamos agora dar uma olhada no código fonte do projeto.

Listagem 3: Comando maven para gerar projeto para IDE Eclipse

mvn clean package eclipse:eclipse

O arquivo principal é o que define o contexto do Spring. Nele podemos ver dois exemplos interessantes: jaxws:endpoint e jaxws:client. Eles configuram um servidor para hospedar nosso WebServive e um cliente para invocar operações nesse serviço.

Listagem 4: Implementação de exemplo




    
    
		
		    
		
        
            
        
    
    
            
       

Na definição de endpoint, passamos parâmetros “address” indicando em que endereço físico nosso serviço estará disponível, implementor contendo a classe que implementa nosso o WebService e onde está localizado o WSDL. Como o arquivo WSDL está na pasta src/main/resources, apenas colocamos o nome do arquivo. Se ele estivesse em src/main/resources/wsdl, a configuração seria “wsdl/HelloWorldService.wsdl” e assim por diante. A “feature” liga permite que sejam mostradas no log as mensagens SOAP de entrada e saída durante a execução do serviço.

Logo abaixo da definição do servidor vemos a definição do cliente. Ela é um pouco mais “complicada”, pois demanda que conheçamos o “serviceName” e o endpointName além do namespace do WebService. Esses valores estão no próprio WSDL como mostrado na Figura 3.

Configuração do cliente

Figura 3: Configuração do cliente

Claramente o namespace é aquele definido no início no WSDL (http://helloworldservice.devmedia.com.br/wsdl/). O serviceName tem seu valor retirado do atributo “name” do elemento wsdl:service enquanto que o endpointName é o atributo “name” do elemento wsdl:port. Fácil não é? Um programador pode gastar horas quebrando a cabeça até entender como configurar o cliente. Finalmente vamos olhar o código-fonte do teste unitário.

Listagem 5: Teste unitário para chamada do serviço

package br.com.devmedia.helloworldservice;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import br.com.devmedia.helloworldservice.schema.Nome;
import br.com.devmedia.helloworldservice.schema.Saudacao;
import br.com.devmedia.helloworldservice.wsdl.DigaOlaException;
import br.com.devmedia.helloworldservice.wsdl.DigaOlaPortType;

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class HelloWorldServiceTest {
	
	@Autowired
	DigaOlaPortType port;

	@Test
	public void requestResponseTest() throws Exception {
        Nome _digaOla_parametro = new Nome();
        try {
        	_digaOla_parametro.setConteudo("ze");
        	Saudacao ret = port.digaOla(_digaOla_parametro);
            Assert.assertEquals("Bom dia", ret.getConteudo());
        } catch (DigaOlaException e) { 
            System.out.println("Expected exception: DigaOlaException has occurred.");
            System.out.println(e.toString());
        }

        try {
        	_digaOla_parametro.setConteudo("maria");
        	Saudacao ret = port.digaOla(_digaOla_parametro);
            Assert.assertEquals("Ola", ret.getConteudo());
        } catch (DigaOlaException e) { 
            System.out.println("Expected exception: DigaOlaException has occurred.");
            System.out.println(e.toString());
        }
        try {
        	_digaOla_parametro.setConteudo("anonimo");
        	Saudacao ret = port.digaOla(_digaOla_parametro);
        	Assert.assertTrue(false);
        } catch (DigaOlaException e) { 
        	Assert.assertEquals("ERR_01",e.getFaultInfo().getConteudo());
            System.out.println("Expected exception: DigaOlaException has occurred.");
            System.out.println(e.toString());
        }
	}
}

Como estamos trabalhando com Spring, nada mais natural que usar o suporte do framework Spring a testes. Para isso, utilizamos duas anotações: ContextConfiguration e RunWith. A primeira indica que um contexto do Spring será criado quando o teste for executado. O arquivo XML deverá por padrão ter o nome -context.xml ou seja HelloWorldServiceTest-context.xml.

RunWith é uma anotação que permite ao framework Junit delegar a execução de Teste a uma classe executora específica que nesse caso é org.springframework.test.context.junit4.SpringJUnit4ClassRunner. O interessante do SpringJunit4ClassRunner é que através dela podemos trabalhar com outras funcionalidades de testes do Spring tais como injeção de dependências (@Autowired).

No teste, a nossa única preocupação foi implementar os cenários de teste para validar o serviço. Toda inicialização e execução do WebService está sob responsabilidade do Spring. Se reparamos no console, veremos também que todas as mensagens SOAP trocadas entre cliente e servidor estão sendo mostradas por que a feature de Logging está configurada.

É isso pessoal. Finalizamos a criação e chamada do nosso serviço utilizando o Apache CXF e Spring. Para ver o projeto completo, basta acessar o repositório do GITHUB https://github.com/leogsilva/ApacheCxfSpringHelloWorld.git. Até a próxima.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?