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
Response response = 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