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.
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.
Mais informação:
JAX-WS
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.
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
Início da primeira parte do projeto (P1)
O objectivo é construir um dos Web Services da primeira parte do projeto,
seguindo a abordagem contract-first.
O ponto de partida é o projeto base.
Este código inclui o servidor incompleto
(station-ws) e
o cliente incompleto
(station-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 station-ws:
-
A estrutura do servidor está representada neste
diagrama de classes .
- O pacote à esquerda contém as classes que são geradas a partir do contrato WSDL.
- O pacote à direita contém as classes do servidor:
- a App onde a aplicação arranca,
- o EndpointManager que disponibiliza o endereço do serviço,
- o PortImpl que concretiza as operações definidas no WSDL, e
- as classes de domínio que representam a informação armazenada pelo serviço.
-
As classes de domínio da aplicação já estão implementadas no ponto de partida.
-
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:
- Station 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 station-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
(right-click, Maven, Update Project..., Force Update of Snapshots/Releases, OK)
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.
Algumas partes estão comentadas e podem ser descomentadas.
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 getInfo, getBina e returnBina
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 station-ws-cli para testar o servidor.
-
A estrutura do cliente está representada neste
diagrama de classes .
- O pacote à direita contém as classes que são geradas a partir do contrato WSDL.
- O pacote à esquerda contém as classes do servidor:
- a ClientApp onde a aplicação arranca, e
- o Client que usa o stub gerado para fazer invocações remotas.
Existem também os testes de integração, em que cada classe de testes se destina a testar uma operação remota.
-
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
- confirmar que a fase de wsimport está configurada.
-
cd station-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 antes da aula?
-
No servidor:
-
Implementar getInfo, getBina e returnBina
de acordo com o enunciado do projeto
(em especial, as secções 1.3 e 1.4).
-
No cliente:
-
Fazer testes de integração das operações implementadas
Não esquecer os casos com entradas incorretas: null, "", valores inesperados, etc
-
A alínea secreta será entregue na aula e pedirá um ou mais testes específicos.
-
Os testes de integração correm com mvn verify no cliente
Bom trabalho!
Entrega da solução
Fénix, Avaliação, Projetos, mini Exercício 3 - Web Services
A solução completa deverá ser submetida no Fénix
antes do fim da sua aula de laboratório.
Trabalhos submetidos depois da hora de fim da aula não serão considerados.
Ter atenção ao seguinte:
- Só são aceites trabalhos de estudantes que estiveram
presentes no laboratório.
- Deverá também incluir um ficheiro instrucoes.txt
com resumo da funcionalidade implementada e com instruções para
colocar o programa a funcionar como esperado.
Por exemplo:
- A funcionalidade pedida foi total/parcialmente implementada
...
- O servidor deve executar com o seguinte comando:
mvn clean install exec:java
- O cliente deve executar com o comando:
mvn clean verify
- Assegure-se que a solução é enviada em formato ZIP e que não
contém código compilado (faça mvn clean antes de
comprimir).