WebServices sem servidor de aplicação no java 6
Por Nico Steppat em 11/07/07Criando WebServices num servidor de aplicação como glassfish ou jboss ficou muito fácil. Basta escrever um Session Bean Stateless e usar as anotações do pacote javax.ws que JavaSE 6 já fornece. Veja o exemplo:
@Stateless
@Remote(Oi.class)
@WebService
public class OiMundo {
@WebMethod
public String oi(String nome) {
return "Hallo " + nome;
}
}
public interface Oi {
String oi(String nome);
}
Pronto, fazendo deploy dessa classe no servidor do aplicação cria automaticamente o WebService e disponibiliza o WSDL. Aqui tem uma discussão mais ampla sobre webservices em um servidor de aplicação.
Sem servidor de aplicação
Com javaSE 6 nas mãos você nem precisa de um servidor de aplicação, nem mesmo um web server! Basta usar as anotações @WebService e @WebMethod na sua classe e a ferramenta apt (annotation processing tool – não o apt do Debian!, encontra-se na pasta bin do jdk) para gerar um WebService.
A conhecida classe:
@WebService
public class OiMundo {
@WebMethod
public String oi(String nome) {
return "Hallo " + nome;
}
}
O comando (imagina a classe OiMundo está no pacote br.com.caelum.ws):
$apt br/com/caelum/ws/OiMundo.java
gera um pacote br.com.caelum.ws.javaws com duas classes, uma classe Oi.java para os parâmetros do WebService (no nosso caso String nome do método oi) e outra OiResponse.java que representa o retorno.
Falta publicar o serviço/endpoint e iniciá-lo:
public class PublicaService {
public static void main(String[] args){
OiMundo service = new OiMundo();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/oi", service);
}
}
Pronto, o WebService está rodando sem servidor de aplicação nem web container. Tudo isso com javaSE 6 jdk. Para acessar a wsdl dele, usa-se o URL:
http://localhost:8080/oi?wsdl
Claro que isso não substitui o servidor por questões de performance, configuração e manutenção, mas é útil na hora de desenvolver e testar um serviço rapidamente.
Cliente
Para criar o cliente do serviço, javaSE 6 já vem com as ferramentas necessárias. Precisamos usar o wsimport (na pasta bin do jdk) para gerar as classes do cliente. Com o serviço rodando, fazemos na linha de comando:
$wsimport -keep -p br.com.caelum.cliente http://localhost:8080/oi?wsdl
A opção keep não apaga os arquivos fontes e p gera as classes dentre do pacote especificado.
Para chamar o serviço pelas classes geradas, escreva a seguinte classe dentro do pacote br.com.caelum.cliente:
public class TesteServico {
public static void main(String[] args) {
br.com.caelum.cliente.OiMundo port = new OiMundoService().getOiMundoPort();
System.out.println(port.oi("Johann"));
}
}
Repare que a classe OiMundo foi gerada pelo wsimport e é uma interface, não confundir com o serviço OiMundo que é uma implementação.
WebServices no WebContainer
Num WebContainer, usando Tomcat ou Jetty, é preciso usar um framework para criar um WebService. Já foi mencionado o Xfire nesse mesmo blog (que agora faz parte do projeto CXF), mas existem outros como o AXIS da Apache ou Metro do java.net. Metro é a implementação usada pelo Glassfish.
Vamos usar o Metro para criar um WebService dentro numa aplicação web usando Tomcat.
Faça o download do metro, instale e copie os jars da pasta metro/lib para a pasta tomcat/shared/lib, ou então para o lib exclusivo do seu projeto. São os seguintes:
- webservices-api.jar
- webservices-extra.jar
- webservices-tools.jar
- webservices-extra-api.jar
- webservices-rt.jar
- wstx-services.war
Crie um aplicação web comum e adicione a classe TchauMundo no seu projeto com as anotações:
@WebService
public class TchauMundo {
@WebMethod
public String tchau(String nome) {
return "Tschüss " + nome;
}
}
Gere novamente o serviço e execute o seguinte comando na pasta src do seu projeto:
$apt br/com/caelum/ws/TchauMundo.java
As classes geradas devem ficar na pastas WEB-INF/classes.
Agora é preciso registrar um servlet e listener que recebe as requisições do WebService. O web.xml:
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee">
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>webServiceServlet</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webServiceServlet</servlet-name>
<url-pattern>/tchau</url-pattern>
</servlet-mapping>
</web-app>
Além disso, falta um outro xml (mais um!) com a definição do serviço/endpoint. O arquivo sun-jaxws.xml deve estar na pasta WEB-INF. Veja o exemplo:
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name='tchauMundo'
implementation='br.com.caelum.ws.TchauMundo'
url-pattern='/tchau'/>
</endpoints>
Fazendo o deploy e acessando a seguinte url:
http://localhost:8080/ws/tchau
temos o nosso serviço:

A entrada de uma API para produzir e consumir webservices no Java SE 6 gerou muita polêmica, por inflar o tamanho da Java RE e ser pouco necessário na maioria dos projetos. Apesar disso, ter uma API unificada, além de ferramentas facilitadoras, possibilita uma mais fácil adoção de webservices por parte dos desenvolvedores Java.
Nico,
como eu posso criar um cliente que não fixo a um ws especifico, eu receberia o endereço do wsdl, metodo e parametro para chamar um ws, é possivel isso com a nova api do java? parecido com o modo que a classe Client do XFire trabalha.
você pode me ajudar com um exemplo simple deste client?
Comment by mchiareli — July 17, 2007 @ 3:21 pm
se vc criar o cliente com wsimport, sua classe FooBarService extende Service. Esta classe também pode ser usada para fazer chamadas dinamicas. Ela tem um factory metodo que vc pode usar para criar um dispatcher que faz a chamada para vc. Vc precisa o url do wsdl, nome do service e o namespace. Problema aqui é, que vc tem que criar a mensagem SOAP na mão ….
dê uma olhada aqui:
https://jax-ws.dev.java.net/nonav/2.1.1rc1/docs/dispatch.html
http://www.ibm.com/developerworks/webservices/library/ws-tip-jaxwsrpc4/
Se quiser, te mando o codigo completo …
Comment by Nico Steppat — July 17, 2007 @ 8:47 pm
Parabéns pelo artigo, bastante interessante e informativo!
Comment by Anderson — July 31, 2007 @ 6:48 am
se pudesse me enviar um código exemplo mesmo que simples, já me ajudava, vou precisar criar um cliente dinamico aqui, para diversas aplicações…
Comment by mchiareli — August 7, 2007 @ 9:30 am
Nico, parabéns pelo artigo! Está muito bom! Gostaria de aproveitar e fazer uma pergunta: Como faço para ter endpoints disponíveis?
Abraço!
Comment by Paulo Nepomuceno — November 27, 2007 @ 3:35 pm
[...] própria aplicação. Hoje em dia qualquer ferramenta como o Apache Axis, Apache CXF, ou mesmo o wsimport, que já vem no JDK 6, auxilia nessa tarefa de gerar Stubs que sabem trabalhar com o SOAP, sem que [...]
Pingback by » Os 7 hábitos dos desenvolvedores de WebServices altamente eficazes » blog.caelum.com.br — February 18, 2008 @ 4:38 am
ótimo tutorial!!!
o link do metro está direcionando para arquivo nao existente e os arquivos que tem la nao tem estas bibliotecas ae…
algum link xtra?
Comment by rafael — July 22, 2008 @ 8:00 pm