
Para o lado cliente, esta API fornece alguns modelos de consumo de serviços, sendo o consumo via proxy escolhido por nós do Rasea. Para consumir um serviço via classes proxy, é necessário executar o comando wsimport (via ant task ou linha de comando) para que sejam geradas as classes do serviço e os tipos usados.
wsimport http://localhost:8001/rasea-ws/AccessControl?wsdl
Excelente! Porém, o código da classe Service gerada instancía uma java.net.URL - num bloco static - para este caminho, além de estabelecer uma conexão a cada comunicação para o parse do WSDL em questão. Logo, podemos enumerar 2 problemas:
- Web service endpoint. Enpoint statico nas classes client;
- Wsdl location. Consumo de recursos - de rede - para fazer o parse do wsdl que se encontra no server.
Certamente o local do WSDL, bem como enpoint do serviço em uma companhia não coincidirão com os locais de WSDL e Web service enpoint de desenvolvimento do Rasea.
Como apresentado no post anterior, a companhia pode, e até recomenda-se, fazer uso de um barramento de serviços, logo é necessário que o usuário possa informar o endpoint correto. Por isso, o Rasea Client usa um arquivo de propriedades para configurar o servidor onde o serviço ficará de fato deployado.
Para o primeiro problema, decidimos embarcar o WSDL no próprio jar das classes client, o que evita o consumo de rede para alcancá-lo. Então foi necessário criar um xml de catalog JAX-WS que descreve um nome para o wsdl e um local alcançável a partir da pasta META-INF do jar.
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"
prefer="system">
<system systemId="http://rasea.org/wsdl/AccessControl"
uri="../AccessControl.wsdl"/>
</catalog>
<!-- https://glassfish.dev.java.net/public/CDDL+GPL.html -->
Note que o WSDL vai ficar na pasta raiz do jar. Mas para as classes client "entenderem" esta decisão nossa, precisamos de uns parâmetros a mais no wsimport.
wsimport -catalog ws/jax-ws-catalog.xml -wsdllocation
http://rasea.org/wsdl/AccessControl AccessControl.wsdl
É necessário informar o arquivo de catalog (que deve ser colocado na pasta META-INF do jar) e o local do wsdl (que será anotado na classe de serviço). Por último fornecemos o wsdl acessado localmente.
Como resultado temos:
@WebServiceClient(name = "AccessControlService", targetNamespace =
"http://rasea.org/ws/AccessControl", wsdlLocation = "http://rasea.org/wsdl/AccessControl")
public class AccessControlService
extends Service
{
...
}
Nos falta um meio de informar à esta classe, em tempo de execução, a localização correta do endpoint do serviço. A a interface javax.xml.ws.BindingProvider fornece um contexto de requisição através do método .getRequestContext() retornando um Map, eque é onde devemos informar o endpoint do seviço.
AccessControlService service = new AccessControlService();
AccessControl port = service.getAccessControlPort();
BindingProvider bindingProvider = (BindingProvider) port;
Map<String, Object> requestContext = bindingProvider.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
http://myserver:7001/rasea-ws/AccessControl);
Este trecho substitui o endpoint original provindo do WSDL do serviço permitindo que o client se conecte ao endpoint correto.
Pronto! Agora você pode deployar seu jar com os clients em qualquer lugar sem a necessida de acessar a rede constatemente para obter o WSDL do serviço e sem usar estaticamente um endpoint para acessar o serviço. Você pode ver a aplicação completa destas duas dicas no código fonte do Rasea Client.
Outra informação é que ao utilizar @WebServiceRef num session EJB, alguns servidores (ex.: BEA Weblogic Server) não conseguem fazer o deploy da aplicação quando os WSDLs dos serviços não sejam alcançáveis durante o deploy. Ou seja, se seus provedores de serviço estiverem indisponíveis, sua aplicação pode não ser publicada até que estes serviços voltem a funcionar.
Daí a importância de adotar uma política adequada na localização do WSDL e definição do endpoint não estaticamente.
Até a próxima!
0 comentários:
Postar um comentário