Materiais de apoio à aula
Exemplo:
- REST Hello World

- Para experimentar o código: fazer Clone or Download e depois seguir as instruções do README
Exercício a resolver até ao fim da aula
Neste exercício iremos transformar uma implementação do Jogo do Galo (Tic Tac Toe) numa aplicação distribuída utilizando REST.
Partindo de uma aplicação local, pretende-se desenvolver uma aplicação distribuída, com servidor e cliente.
O servidor guarda as variáveis do jogo.
O cliente faz a interface com o utilizador.
Existe um módulo adicional, o contrato, onde são definidas mensagens partilhadas entre o servidor e o cliente para que se possam fazer jogadas.
-
Começar por ver a implementação local do
Jogo do Galo/Tic Tac Toe
- Para experimentar o código: fazer Clone or Download e depois seguir as instruções do README
-
Analise o código do jogo de forma a compreender a implementação.
-
Experimente o jogo.
Indique a posição escolhida para cada jogador, até terminar o jogo.
-
Pretende-se que a nova versão do programa seja dividida em dois processos: servidor e cliente, através do Jersey.
Começar pela implementação do jogo
adaptada a este exercício.
-
Veja como o programa está estruturado em três módulos: contract, server e client.
Cada módulo tem um POM próprio.
-
Importe os projectos no Eclipse, recorrendo a File > Import > Maven > Existing Maven Projects
-
Nesta secção, vamo-nos focar apenas no server. O client já está todo implementado e vai ser utilizado para testar e jogar o jogo do galo na secção a seguir.
- Estude os principais ficheiros com a implementação do jogo (TTTGame.java, TTTResources.java do módulo server e PlayRequest.java do módulo contract).
-
Analise o ficheiro TTTGame.java e perceba como funciona o jogo do galo.
-
O ficheiro TTTResources.java contém dois métodos GET. Analise o que cada um faz.
-
Vá agora ao contract.
O ficheiro PlayRequest.java contém a informação necessária para fazer uma jogada (row, column e player).
Existe uma anotação @XmlRootElement.
Qual é o efeito desta linha de código?
-
Instale o contract utilizando mvn install.
-
Compile e corra o servidor utilizando mvn compile exec:java.
-
Abra o browser e aceda a http://localhost:8080/ttt/game/board.
Confirme que o que aparece no ecrã é um tabuleiro do jogo do galo.
-
Vamos agora implementar os métodos necessários para que o Jogo do Galo funcione numa aplicação cliente-servidor com REST, organizada em três módulos.
-
Baseando-se no ficheiro TTTResources.java da aplicação, crie um método GET para verificar qual o jogador que ganhou, utilizando o método checkWinner.
Sugestão: veja os métodos getBoard e resetBoard.
-
O pedido deve ser acedido no caminho "board/checkwinner", para manter consistência com os outros métodos já disponíveis.
-
Verifique sempre se o caminho funciona (depois de compilar e executar), acedendo com o browser.
-
O que é devolvido do pedido está no formato texto (MediaType.TEXT_PLAIN), mas o que o método devolve é um inteiro.
E se, em vez de texto, fosse pedido XML ou JSON?
-
Agora é necessária uma maneira de jogar, isto é, invocar o método play a partir de um cliente.
Para isso é necessário criar um método POST para enviar um pedido que contém a jogada que queremos efetuar.
-
Comece por analisar novamente o método play() do ficheiro TTTGame.java e o ficheiro PlayRequest.java.
-
No ficheiro TTTResources.java, crie um método POST no caminho "play" que receba um PlayRequest em JSON e que produza um PlayResult em JSON.
Este método vai-nos permitir enviar jogadas para o servidor.
Exemplo de um método que recebe qualquer coisa em XML e JSON e devolve qualquer coisa em XML:
@POST
@Path("caminho-aqui")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML})
public QualquerCoisa metodo(ClasseCoisa coisa) {
return qualquerCoisa;
}
-
Depois de terminado, compile o servidor utilizando mvn clean compile
-
Aceda agora à pasta que contém o cliente.
Compile o cliente utilizando mvn clean compile
-
Porque é que a compilação falhou?
Porque é que o Maven não consegue encontrar aquelas classes?
-
O cliente necessita de obter informação acerca de algumas classes que estão definidas no contract.
Para isso, é necessário criar uma dependência do contract no cliente:
...
<dependency>
<groupId>pt.ulisboa.tecnico.distsys.ttt-rest</groupId>
<artifactId>ttt-contract</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
...
-
Compile novamente o cliente e confirme que foi bem sucedido.
Experimente o jogo: mvn clean compile exec:java
Acima enviamos os parâmetros do método play utilizando um método POST em REST. Agora vamos enviar os argumentos encapsulando parâmetros no URL.
-
Para isso vamos criar outro método GET no ficheiro TTTResources.java.
-
Usando o código do ficheiro TTTResources.java do código base e o exemplo imediatamente abaixo, crie um método GET que permita enviar os argumentos utilizando parâmetros no URL.
Exemplo de utilização:
@GET
@Path("{arg1}/{arg2}")
@Produces(...)
public QualquerCoisa metodo(@PathParam("arg1") int arg1,
@PathParam("arg2") String arg2) {
return qualquerCoisa.fazcoisas(arg1, arg2);
}
-
Para testar a sua implementação, abra o browser e aceda a http://localhost:8080/ttt/game/board/reset para reiniciar o jogo.
-
Para fazer uma jogada, experimente, por exemplo, http://localhost:8080/ttt/game/play/1/1/0.
-
Se tudo correu bem, ao aceder agora a http://localhost:8080/ttt/game/board, o tabuleiro com a jogada anterior vai aparecer no ecrã.
-
O cliente está configurado para utilizar o método POST em vez do novo método GET para jogar. Para isso é necessário fazer algumas alterações.
-
Vá agora ao cliente e no ficheiro TTTPlayer.java comente as linhas seguintes desta forma:
/* Response response = client.target(restURL).path("play").request(MediaType.APPLICATION_JSON)
.post(Entity.entity(playRequest, MediaType.APPLICATION_JSON), Response.class); */
...
/* play_res = response.readEntity(PlayResult.class); */
-
Descomente a linha seguinte desta forma:
/* Uncomment to use URL parameter to play */
/* URL to play is: play/{row}/{column}/{player} */
String playString = "play/" + String.valueOf(row) + '/' + String.valueOf(column) + '/' + String.valueOf(player);
-
Finalmente, só precisamos de aceder ao URL que vai fazer a jogada e receber o resultado da jogada. Para isso, adicione a linha de código da seguinte forma:
play_res = client.target(restURL).path(playString).request().get(PlayResult.class);
O resto do enunciado será entregue na aula.
O objectivo será estender a solução resultante do enunciado acima com mais procedimentos remotos ou modificar alguns dos seus procedimentos actuais.
Entrega da solução
Fénix, Avaliação, Projetos, mini Exercício 1 - REST
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ó serão aceites trabalhos de estudantes que estiveram presentes no laboratório.
-
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 criar o zip)
-
Deverá também incluir um ficheiro README 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
...
- Para compilar: mvn compile
-
O servidor deve executar com o comando:
mvn exec:java &
-
O cliente deve executar com o comando:
mvn exec:java