Este artigo mostra como construir e fazer o deploy de um web service e um cliente utilizando JAX-WS. A figura 1 ilustra como a tecnologia JAX-WS gerencia a comunicação entre o web service e o cliente. A comunicação é feita basicamente com a troca de mensagens SOAP.
![JAX-WX: comunicação entre o web service e o cliente](http://gabrielamorim.com/wp-content/uploads/2013/02/jaxws-simpleclientservice.gif)
O ponto de início para construir um web service com JAX-WS é uma classe Java anotada com javax.jws.WebService. A anotação WebService define a classe como uma provedora (web service endpoint).
Uma service endpoint interface ou service endpoint implementation (SEI) é uma interface ou classe Java, respectivamente, que declaram os métodos que um cliente pode chamar no serviço. Uma interface não é necessária quando construímos um web service com JAX-WS, a implementação (SEI) JAX-WS implicitamente define uma interface.
Você pode definir explicitamente uma interface utilizando o elemento endpointInterface na anotação WebService na classe de implementação (SEI). Dessa forma, você deverá prover uma classe concreta (SEI) que defina os métodos públicos que serão disponibilizados no web service.
Os passos básicos para a construção de um web service e um cliente são:
- Codificar a classe do web service
- Compilar a classe do web service
- Fazer o deploy do web service.
- Codificar a classe cliente.
- Usar o utilitário wsimport para gerar e compilar os artefatos do web service necessários para se conectar ao serviço.
- Compilar a classe cliente.
- Executar o cliente.
As seções seguintes abordam estes passos de forma mais detalhada.
Requisitos de um JAX-WS Endpoint (Web Service)
JAX-WS endpoints devem seguir as seguintes regras:
- A classe do web service deverá ser anotada por uma das seguintes anotações: javax.jws.WebService ou javax.jws.WebServiceProvider.
- A classe do web service poderá explicitar uma referência a uma SEI por meio do elemento endpointInterface da anotação @WebService.
- Os métodos de negócios da classe do web service devem ser públicos e não devem ser declarados static ou final.
- Métodos de negócios que são expostos aos clientes do web service devem ser anotados com javax.jws.WebMethod.
- Métodos de negócios que são expostos aos clientes do web service devem ter parâmetros e tipos de retorno compatíveis. Veja também Default Data Type Bindinds.
- A classe do web service não deve ser declarada final e não deve ser abstract.
- A classe do web service deve ter um construtor padrão público.
- A classe do web service não deve definir o método finalize.
- A classe do web service pode usar as anotações javax.annotation.PostConstruct ou javax.annotation.PreDestroy em seus métodos para controle de callbacks em seu ciclo de vida.
O método @PostConstruct é chamado pelo container antes que a classe comece a responder aos clientes do web service.
O método @PreDestroy é chamado pelo container antes que o web service seja removido.
Codificando a implementação do web service (Service Endpoint)
No exemplo, a classe Hello é anotada como um web service endpoint com a anotação @WebService. A classe Hello declara um único método chamado sayHello anotado com anotação @WebMethod. A anotação @WebMethod expõe o método anotado para os clientes do web service. O método sayHello retorna uma saudação para o cliente, usando o nome passado para sayHello para compor a saudação. A classe Hello também deve definir um construtor padrão público sem argumento.
package helloservice.endpoint; import javax.jws.WebService; import javax.jws.WebMethod; @WebService() public class Hello { private String message = new String("Hello, "); public Hello() { } @WebMethod() public String sayHello(String name) { return message + name + "."; } }
Construindo, empacotando e fazendo o deploy do web service
Uma das versões originais deste artigo mostra duas formas para construir, empacotar e fazer o deploy do web service. A primeira é com o NetBeans e a segunda utilizando o Ant. Como eu usei o Eclipse, pulei essa parte. Para informações sobre como construir, empacotar e fazer o deploy do web service com o NetBeans ou Ant consulte o artigo original disponível em http://docs.oracle.com/javaee/6/tutorial/doc/bnayn.html.
Como eu fiz a construção, empacotamento e deploy do web service
Usei o utilitário wsgen para gerar os artefatos do web service com o comando:
wsgen –wsdl –r WebContent\WEB-INF\wsdl –d build –s build –classpath build\classes helloservice.endpoint.Hello
Este comando gera os fontes, as classes e o arquivo WSDL necessários para o web service.
O arquivo WSDL gerado precisa ser editado. Abra o arquivo WSDL e procure por REPLACE_WITH_ACTUAL_URL substituindo pela URL do web service. A minha URL é http://localhost:8080/ws_trainning/Hello.
Depois disso, basta empacotar e fazer o deploy. Meu Eclipse é integrado ao JBoss AS 7, basta um clique com o botão direito sobre o projeto >> Run as… >> Run on Server.
O seguinte endereço mostra o arquivo WSDL: http://localhost:8080/ws_trainning/Hello?wsdl.
Testando o web service sem um cliente
É fácil testar o web service no Eclipse. Localize o arquivo WSDL na àrvore de diretórios, clique com o botão direito >> Web Services >> Test with Web Services Explorer. O Web Service Explorer é simples e intuitivo para ser usado.
Criando um cliente JAX-WS
A classe HelloAppClient é uma classe padrão que acessa o método sayHello de HelloService. Esta chamada é feita por meio de uma porta, um objeto local que atua como um Proxy para o serviço remoto. A porta é criada no tempo de desenvolvimento pelo utilitário wsimport, que gera os artefatos JAX-WS baseados em um arquivo WSDL.
O comando para geração dos artefatos com wsimport é:
wsimport –keep –verbose http://localhost:8080/ws_trainning/Hello?wsdl
Codificando a aplicação cliente
- Use a classe HelloService, gerada pelo comando wsimport, que representa o serviço:
import com.gabrielamorim.webservices.HelloService; import javax.xml.ws.WebServiceRef; public class HelloAppClient { @WebServiceRef(wsdlLocation = "http://localhost:8080/ws_trainning/Hello?wsdl") private static HelloService service = new HelloService();
- Obtenha um Proxy para o serviço, também chamado de porta, invocando getHelloPort no serviço:
com.gabrielamorim.webservices.Hello port = service.getHelloPort();
- Invoque o método sayHello da porta, passando uma string para o serviço:
return port.sayHello(arg0);
Abaixo está o código fonte completo do cliente:
package appclient; import com.gabrielamorim.webservices.HelloService; import javax.xml.ws.WebServiceRef; public class HelloAppClient { @WebServiceRef(wsdlLocation = "http://localhost:8080/ws_trainning/Hello?wsdl") private static HelloService service = new HelloService(); public static void main(String[] args) { System.out.println(sayHello("world")); } private static String sayHello(java.lang.String arg0) { com.gabrielamorim.webservices.Hello port = service.getHelloPort(); return port.sayHello(arg0); } }
Pronto, ao executar o código como uma aplicação Java, você deverá ver a saudação “Hello, world”.
Este artigo é uma versão resumida e traduzida baseado nas duas versões dos tutoriais Creating a Simple Web Service and Client with JAX-WS, disponíveis em http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/ e http://docs.oracle.com/javaee/6/tutorial/doc/bnayn.html.
As versões originais possuem alguns passos utilizando ferramentas diferentes, fiz, então, algumas mudanças no passo a passo do tutorial e resolvi registrá-las para alguma eventual consulta.
Eu uso Mac OS X, qual o comando equivalente ao wsgen?
seria o java2wsdl.sh ???
o wsimport é o wsdl2java.sh certo?
obrigado
Richard,
acredito que os comandos para o Mac sejam os mesmos que do Linux.
Gabriel, disso eu tenho certeza, só não estou achando, só vejo exemplos com o wsimport, obrigado