WebServices sem servidor de aplicação no java 6

Criando 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.xml.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

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.

20 Comentários

  1. mchiareli 17/07/2007 at 15:21 #

    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?

  2. Nico Steppat 17/07/2007 at 20:47 #

    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 …

  3. Anderson 31/07/2007 at 06:48 #

    Parabéns pelo artigo, bastante interessante e informativo!

  4. mchiareli 07/08/2007 at 09:30 #

    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…

  5. Paulo Nepomuceno 27/11/2007 at 15:35 #

    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!

  6. rafael 22/07/2008 at 20:00 #

    ó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?

  7. Rafael 05/11/2008 at 07:22 #

    Show de bola o tutorial, parabéns! Definitivamente, agora Web Service tá simples com o Java 6…

  8. fabiana 18/06/2009 at 11:47 #

    ótimo tutorial. Gostaria de saber se o webservice pode ser acessado externamente, através de javascript. Teria algum exemplo?
    obrigada!

  9. Leandro 09/12/2009 at 10:19 #

    javax.ws = javax.xml.ws
    :)

  10. Marcio Duran 21/12/2009 at 14:21 #

    Obrigado pelas as informações, também gostei do artigo bastante rico em informação !!!!

    abraçoss

  11. Sergio Oliveira Jr. 04/02/2010 at 01:23 #

    Caso queira um método bem simples de deployar um web service JAX-WS no tomcat dê uma olhada aqui: http://www.seducaotecnologica.com.br/tutorial-soa-passo-a-passo-4/

    Tb tem outros artigos de como usar um cliente Ruby e Java.

  12. André Thiago 29/10/2010 at 19:58 #

    Olá Nico Steppat ,

    Estou desenvolvendo um WS com a implementação JAX-WS que está conectando uma API COGROO do BrOffice. Tem alguma restrição eu não usar o servidor de aplicação para gerar um cliente? Estou com problemas qndo qro gerar o WSDL com esta API.

    vlws…

  13. Ricardo 08/12/2010 at 15:43 #

    Olá nico,
    Cheguei hoje no seu site e não sei se você vai ler este comentário, de qualquer forma vamos lá.

    Quando tento executar o exemplo ele dá erro no OiMundoService(), de onde vem isso? é gerado automaticamente? consigo importar o wsdl e gerar as classes, só não consigo testar…

    Obrigado.

  14. William Palermo 02/07/2013 at 16:30 #

    Excelente pra quem nunca fez nada de WS e precisa começar! Mto bom!

  15. aline 04/11/2013 at 10:41 #

    Bom dia Nico,

    Muito bem explicado o seu artigo, vc poderia me informar como criar um webservice dinamico, pois usei o dispatch mais estou tendo muitos problemas com ele. você poderia me ajudar?

  16. Antonio 27/02/2014 at 12:46 #

    Boa tarde. Fiz o curso de c# na Caelun. Muito bom o conteúdo. Estou trabalhando como desenvolvedor na área de T.I de Um hospital. Preciso desenvolver um webservice para envio e recebimento de arquivo xml padrão tiss. consegui gerar o arquivo já, o problema agora é como conseguir a configuração para envio deste arquivo de solicitação (de exames por exemplo) para o webservice da operadora de plano de saúde e receber o xml de resposta da mesma. alguém tem alguma idéia ?

Deixe uma resposta