Web Services
Um serviço é uma funcionalidade de um sistema de informação que pode ser invocada remotamente através da rede.
Um Web Service é um serviço que usa os protocolos de comunicação da World Wide Web
- HTTP sobre TCP sobre IP -
e protocolos adicionais para descrever mensagens e dados
- SOAP sobre XML.
Para permitir uma definição rigorosa das operações e dos tipos de dados dos Web Services
são usadas as linguagens WSDL (Web Services Description Language) e
XSD (XML Schema Definition),
respetivamente.
Web Service contract
Os Web Services também têm uma linguagem própria para descrever o seu contrato com os clientes.
A WSDL permite especificar a interface funcional (port type)
- operações com entradas, saídas e erros -
e também a vinculação (binding) com tecnologias concretas
- habitualmente SOAP sobre HTTP.
A WSDL é baseada em XML de forma a ser independente da plataforma e
usa XSD para definir o detalhe dos tipos de dados de entrada e saída (e erros) em cada operação.
Exemplo:
- Ping.wsdl -
os comentários numerados explicam as diferentes seções do documento:
namespaces,
service definition,
binding definitions,
port type definitions,
message definitions e
type definitions.
Mais informação:
Java API for XML Web Services
As bibliotecas JAX (Java API for XML) são a família de bibliotecas da plataforma Java que lidam com tecnologias baseadas em XML,
como é o caso dos Web Services.
A JAX-WS (Java API for XML Web Services) é uma biblioteca para Java que permite implementar Web Services,
usando as normas:
HTTP/TCP/IP para mensagens,
SOAP/XML para mensagens,
WSDL e XSD para descrição.
É possível implementar Web Services partindo de um contrato WSDL (e XSD) já existente.
Esta abordagem ao desenvolvimento de serviços é chamada contract-first.
Mais informação:
JAX-WS
Exemplo Ping Web Service:
Nota: As pastas que contêm o código não devem ter espaços nem caracteres acentuados no seu caminho.
JUnit Integration Tests
Para garantir a qualidade do código do Web Service,
é necessário produzir testes de integração (IT)
que verificam o comportamento de todo o sistema através de invocações remotas.
O JUnit pode também ser usado para fazer testes de integração.
No contexto dos Web Services,
os testes de integração são um programa cliente (ws-cli) que faz invocações remotas a um programa servidor (ws),
verificando o contrato das operações remotas definidas no WSDL.
Assume-se que todos os Web Services já foram previamente lançados antes de correr os testes de integração.
Mais informação:
JUnit Integration Tests
Exercício
Primeira parte do projeto (P1)
O objectivo é construir o Web Service contract-first da primeira parte do projeto.
O ponto de partida é o projeto base.
Este código inclui o servidor incompleto
(supplier-ws
) e
o cliente incompleto
(supplier-ws-cli
).
Antes de começar, e para prevenir conflitos de módulos Maven,
alterar os pom.xml substituindo as referências
CXX pelo identificador do grupo.
Vamos começar pelo servidor supplier-ws
-
As classes de domínio da aplicação já estão implementadas.
-
Consulte o pacote domain.
-
Identifique o Domain Root e
as restantes entidades representadas nas classes.
-
Veja os mecanismos de sincronização que são utilizados para garantir que as classes podem ser chamadas corretamente por múltiplas tarefas (threads).
-
De seguida,
consultar o contrato WSDL do serviço a implementar:
- Supplier WSDL
-
Analise o contrato para ver que operações define e
quais os respectivos parâmetros e exceções.
-
Vamos gerar código Java a partir do WSDL.
O Maven está configurado para chamar a ferramenta wsimport.
-
Copie o ficheiro WSDL do serviço a implementar para a pasta
src/main/resources do servidor
-
cd supplier-ws
-
mvn generate-sources
Caso o WSDL esteja bem formado e válido,
a ferramenta wsimport gera vários ficheiros que suportam o web service.
Entre eles, estarão as classes para os tipos complexos usados como parâmetros
e a interface Java que define o Web Service.
-
Faça refresh no Eclipse e
consulte as classes geradas na pasta:
target/generated-sources/wsimport.
Em especial,
consulte a classe ...Service, e
descubra a interface Java ...PortType que foi gerada a partir do WSDL.
-
Vamos agora concretizar o serviço.
-
Consulte a classe de implementação do serviço ...PortImpl,
que deverá implementar a interface Java gerada.
-
Deverá associar a classe PortImpl ao WSDL através da
anotação @WebService com os seguintes atributos:
endpoint interface (nome do tipo Java do PortType),
wsdlLocation (nome do ficheiro WSDL),
name (definido no WSDL),
portName (WSDL),
targetNamespace (WSDL) e
serviceName (WSDL).
-
Além da anotação, todos os métodos listados na interface PortType
devem ser implementados na classe do serviço.
Cada método é uma operação do Web Service,
com entradas, saídas e excepções.
Para cada operação, confira se está corretamente implementada.
Adicione a anotação @Override antes de cada método de operação,
para que o compilador confirme que está a implementar corretamente
o método definido na interface.
Note que as operações searchProducts e buyProducts
não estão implementadas.
Para já vamos compilar e executar o servidor sem estas operações estarem concluídas.
-
Executar o servidor:
-
mvn compile exec:java
O nome da classe a executar e
os argumentos estão definidos no pom.xml
O servidor deve executar sem erros,
disponibilizando o endpoint address.
-
Confirmar que o servidor está à espera de pedidos no endereço:
Vamos agora usar o cliente supplier-ws-cli para testar o servidor.
-
Vamos gerar o código Java para invocação do serviço.
-
Consultar o pom.xml do cliente para confirmar que o WSDL está a ser corretamente referenciado
(propriedades wsdl.directory e wsdl.filename)
-
cd supplier-ws-cli
-
mvn generate-sources
As classes são geradas na pasta:
target/generated-sources/wsimport.
-
Vamos fazer uma chamada simples, correndo a aplicação cliente.
-
mvn compile exec:java
A operação auxiliar ping deverá ser invocada.
-
Depois do teste pontual, vamos correr os testes de integração já existentes.
-
mvn verify
O Maven executa todos os testes contidos em classes ...IT e
um resumo é apresentado.
O que falta fazer?
-
No servidor:
-
Implementar searchProducts e buyProduct
de acordo com o enunciado
-
No cliente:
-
Fazer testes de integração das operações implementadas
-
Testar casos mais importantes
-
Não esquecer os casos com entradas incorretas: null, "", valores inesperados, etc
-
Os testes de integração correm com mvn verify
Bom trabalho!