Skip to content

Serviço JAX-WS assíncrono

Maio 29, 2012

Antes de mais nada, quero ressaltar que não sou muito fã da utilização de JAX-WS para comunicação Webservice. Não que eu seja aqueles xiitas que odeiam a solução. Mas é que, infelizmente, 95% dos lugares onde vejo esse modelo sendo utilizado, reconheço a velha “bigorna para matar uma formiga”. Nestes cenários, uma simples comunicação HTTP, utilizando, por exemplo, serviços restfull, resolveria de forma muito mais enxuta e elegante o problema. Mas claro, sei que existem casos mais complexos onde o JAX-WS é necessário, principalmente quando estão envolvidas questões de formalidade.
Com isso, de tempos em tempos, preciso fazer alguma atividade relacionada com JAX-WS, e sempre que preciso relembrar algo, ou até mesmo buscar novas soluções, me deparo com documentações e exemplos não muito intuitivos. Deste modo, resolvi postar aqui um primeiro exemplo relacionado a esta tecnologia. Este trata-se de algo que é bastante utilizado no mundo JAX-WS, que é a comunicação assíncrona. Vamos então à narrativa:

Rafael Chies: Imagine que temos um cenário onde um código cliente quer invocar o serviço de um servidor. Porém, o cliente não deseja esperar pela resposta, pois o processo pode ser demorado. Ao invés dessa espera, o cliente deseja que o servidor lhe envie uma nova requisição de resposta, quando a mesma estiver pronta. Essa ideia é ilustrada na figura abaixo:

Requisição e reposta de forma assíncrona.

Leitor: Poxa, legal Rafael, mas como faço para que o meu Webservice lá do servidor seja assíncrono ?

Rafael Chies: Fácil, para isso existe o conceito de OneWay, presente na especificação (JSR224). A implementação da spec nos fornece uma anotação @OneWay, que devemos atribuir a um método void do serviço, que desejamos ser assíncrono. Com isso, quando o serviço receber a requisição, já é enviada a resposta HTTP 202, liberando a conexão com o cliente. Segue abaixo a listagem de exemplo de utilização do OneWay.

Método assíncrono anotado com @OneWay

Leitor: Legal, bem fácil mesmo. Mas, e como que fazemos a amarração de onde o servidor deve enviar a resposta quando a mesma for processada ? E como o cliente vai saber que uma resposta que chegou é de uma determinada requisição original ?

Rafael Chies: Boa pergunta. Para isso existe a especificação WS-Addressing. Esta permite, entre outras coisas, que o cliente envie, no Header da mensagem SOAP, as informações referentes ao retorno da resposta. Abaixo segue um ilustrativo da utilização do WS-Addressing.

SOAP Header

Rafael Chies: Como podemos ver, no header da mensagem SOAP, são enviados os parâmetros ReplyTo e MessageID. O primeiro é referente ao endereço em que o cliente deseja receber a resposta da requisição, enquanto que o segundo é responsável pelo ID único que deve ser enviado pelo cliente. Assim, quando o servidor for enviar a resposta, será enviado esse mesmo ID no parâmetro RelatesTo do Header, permitindo que o cliente faça o link entre requisição e resposta.

Leitor: Massa !! Acho que entendi como tudo funciona na teoria. Mas, veja bem, tem como postar um código para demonstrar esse exemplo ?

Rafael Chies: Claro. Na verdade, para não tornar esse post muito verboso e cansativo, o fonte que trás um exemplo completo deste cenário encontra-se no meu github (https://github.com/rafachies/jaxws-demos). Entretanto, para facilitar a visualização e execução deste código, segue uma imagem que ilustra o fluxo que o código de exemplo percorre.

Fluxo do exemplo

Rafael Chies: Pelo fluxo temos: A classe Main inicia as rotas do Camel. Sim, utilizei Camel pela simplicidade de levantar um serviço, junto ao CXF, sem necessitar de um servidor de aplicações. Também optei por utilizá-lo para fomentar novas implementações que pretendo fazer em próximos exemplos; Depois, A classe RequestSender executará o chamado ao serviço SOAP (RequestService), recebendo imediatamente um response 202 e fechando a conexão HTTP. Lembrando que, antes do envio da requisição, é colocado no header os dados do WS-Addressing; Chegamos ao ServerRoute, que está atrelado ao endpoint RequestService. Este, num primeiro momento, invoca o processor sleeper, que apenas deixa a Thread em espera por dez segundos, provando assim o assincronismo no processo; Na sequência, a rota chama o outro processor, que é quem vai enviar a resposta ao serviço ResponseService do cliente. Lembrando que, para isto, o processor utiliza os parâmetros ReplyTo e MessageID para saber como enviar a resposta; Por fim, o ClientRoute, percebendo a chegada da resposta, repassa a mensagem para o processor do cliente, que imprime a resposta e seu ID.

Bom, para exeuctar o exemplo, rodei pelo Eclipse mesmo, acionando a classe Main. Caso queiram gerar o JAR e executá-lo, sintam-se a vontade, o único problema é que o Camel e CXF geraram muita dependência, necessitando assim a cópia de várias bibliotecas para o devido funcionamento.
Qualquer coisa estou a disposição.

[]’s

From → Uncategorized

2 comentários
  1. Flávio Alves permalink

    Muito boa leitura. Mandou muito bem.

  2. Neylor Sousa permalink

    Muito bacana a forma que escreveu, simples e funcional! Parabéns!!!

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

Coding Horror

Um prato de informações tecnológicas com uma pitada de conhecimento aleatório.

InfoQ

Um prato de informações tecnológicas com uma pitada de conhecimento aleatório.

JBoss Developer Recent Posts

Um prato de informações tecnológicas com uma pitada de conhecimento aleatório.

JBossDivers

Mergulhando no Mundo JBoss

%d bloggers like this: