Labs SD >

Chamadas remotas com REST

Objetivos da semana

Materiais de apoio à aula

Exemplo:

 

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.

Tic Tac Toe

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.

  1. Começar por ver a implementação local do Jogo do Galo/Tic Tac Toe GitHub
    • 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.

  2. 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 GitHub adaptada a este exercício.
    1. Veja como o programa está estruturado em três módulos: contract, server e client.
      Cada módulo tem um POM próprio.
    2. Importe os projectos no Eclipse, recorrendo a File > Import > Maven > Existing Maven Projects
    3. 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.
    4. 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).
      1. Analise o ficheiro TTTGame.java e perceba como funciona o jogo do galo.
      2. O ficheiro TTTResources.java contém dois métodos GET. Analise o que cada um faz.
      3. 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?
    5. Instale o contract utilizando mvn install.
    6. Compile e corra o servidor utilizando mvn compile exec:java.
    7. 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.

  3. 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.

    1. 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.
      1. O pedido deve ser acedido no caminho "board/checkwinner", para manter consistência com os outros métodos já disponíveis.
      2. Verifique sempre se o caminho funciona (depois de compilar e executar), acedendo com o browser.
      3. 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?

    2. 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.
      1. Comece por analisar novamente o método play() do ficheiro TTTGame.java e o ficheiro PlayRequest.java.
      2. 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;
            }
        
                                
      3. Depois de terminado, compile o servidor utilizando mvn clean compile
      4. 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?

      5. 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>
            ...
                
                
      6. Compile novamente o cliente e confirme que foi bem sucedido.
        Experimente o jogo: mvn clean compile exec:java

  4. 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.

    1. Para isso vamos criar outro método GET no ficheiro TTTResources.java.
      1. 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);
                }
        
                            
      2. Para testar a sua implementação, abra o browser e aceda a http://localhost:8080/ttt/game/board/reset para reiniciar o jogo.
      3. Para fazer uma jogada, experimente, por exemplo, http://localhost:8080/ttt/game/play/1/1/0.
      4. Se tudo correu bem, ao aceder agora a http://localhost:8080/ttt/game/board, o tabuleiro com a jogada anterior vai aparecer no ecrã.

    2. 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.
      1. 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); */
                            
      2. 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);
                            
      3. 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:


© Docentes de Sistemas Distribuídos, Dep. Eng. Informática, Técnico Lisboa