Labs SD >
O exemplo abaixo demonstra como configurar os tempos de espera pelas respostas de Web Services. No fim do tempo, caso a resposta não tenha sido recebida, é atirada uma excepção.
O JAX-WS distingue dois timeouts distintos:
Exemplo:
Este exemplo demonstra como definir operações unidireccionais, ou seja, operações de Web Service que não enviam resposta.
Em situações em que o cliente não pretenda ficar bloqueado à espera da resposta do servidor, é possível fazê-lo através de uma invocação assíncrona.
Uma possível maneira de fazer invocações assíncronas é através dos métodos com sufixo Async. Para que estes métodos sejam gerados é necessário do lado do cliente indicar um ficheiro de binding. Os stubs assim gerados passam a incluir tanto os métodos para invocação sincrona como assíncrona.
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://java.sun.com/xml/ns/jaxws" > <bindings node="wsdl:definitions"> <enableAsyncMapping>true</enableAsyncMapping> </bindings> </bindings>
Para uma invocação assíncrona, o cliente deve executar um método com o sufixo Async e de seguida usar o método Response.isDone() para verificar se a resposta já chegou. Nesta solução o cliente invoca o método remoto sem ficar bloqueado, ficando responsável por verificar quando o servidor já respondeu através do objecto Response. Só depois da resposta ter chegado, pode então obter o seu resultado através do objecto Response.
// asynchronous call with polling Responseresponse = port.echoAsync(name); while (!response.isDone()) { Thread.sleep(100 /* milliseconds */); /* while waiting for response do other calls... */ String result = port.fastEcho(name); System.out.print("Synchronous call result: "); System.out.println(result); } System.out.println("Async->" + response.get().getReturn());
Um outro modelo de funcionamento é o registo de um objecto de callback do tipo AsyncHandler aquando da execução da chamada assíncrona. Quando a resposta chega, um método desse objecto é invocado.
static boolean finished = false; ... // asynchronous call with callback port.echoAsync(name, new AsyncHandler() { @Override public void handleResponse(Response response) { try { System.out.println(); System.out.print("Asynchronous call result arrived: "); System.out.println(response.get().getReturn()); finished = true; } catch (InterruptedException e) { System.out.println("Caught interrupted exception."); System.out.print("Cause: "); System.out.println(e.getCause()); } catch (ExecutionException e) { System.out.println("Caught execution exception."); System.out.print("Cause: "); System.out.println(e.getCause()); } } }); while (!finished) { Thread.sleep(100); System.out.print("."); System.out.flush(); }
Em ambos os casos, a resposta é obtida invocando o método response.get() que lança uma excepção caso esta tenha sido retornada pelo método remoto. Caso o método remoto retorne Void, este método lancará uma NullPointerException. Caso contrário, o objecto retornado pode ser obtido com o método getReturn().
Repare que não é preciso alterar o servidor para que o cliente possa fazer invocações assíncronas.
O objetivo deste exercício é replicar o mediador e implementar o mecanismo de provas de vida entre mediador primário e secundário.
1) Replicar o mediator-ws:
... <group.id>CXX</group.id> <ws.i>1</ws.i> <ws.host>localhost</ws.host> <ws.port>807${ws.i}</ws.port> <ws.url>http://${ws.host}:${ws.port}/mediator-ws/endpoint</ws.url> <ws.name>${group.id}_Mediator</ws.name> <supplier.ws.name>${group.id}_Supplier</supplier.ws.name> ...
Cada instância, ao arrancar, deve imprimir para a consola uma mensagem que indique se está a funcionar como primário ou como secundário
A partir deste momento já existem duas instâncias do mediador a correr, mas ambas vão ter estados diferentes, pelo que não são ainda réplicas. A replicação de estado será tratada depois.
2) Pretende-se agora modificar o contrato WSDL do mediador para permitir uma operação unidireccional de prova de vida: imAlive.
3) Pretende-se agora criar uma classe LifeProof.java que faz o lançamento de provas de vida do mediador primário para secundário.
Próximos passos:
4) Acrescentar à classe LifeProof.java o comportamento para o caso de ser o mediador secundário
5) Modificar novamente o contrato WSDL para conter as
operações auxiliares de atualização de estado do mediador secundário.
Estas operações devem ser unidireccionais.
6) Implementar a lógica de atualizações entre os dois mediadores, tendo em atenção a execução de pedidos repetidos avaliando a idempotência das operações
7) Utilizar as invocações de operações com timeout para alterar o MediatorClient de modo a garantir um front-end com a semântica pretendida no enunciado, tendo em atenção os vários tipos de exceções de comunicação.
Continuação de bom trabalho!
© Docentes de Sistemas Distribuídos,
Dep. Eng. Informática,
Técnico Lisboa