Skip to content
Snippets Groups Projects
README.md 7.49 KiB
Newer Older
Yvan Peter's avatar
Yvan Peter committed
# Développement REST - tests et accès à la base de données
Yvan Peter's avatar
Yvan Peter committed

Pour ce TP, nous allons développer la ressource de gestion de tâches que vous avez utilisée pour le TP HTTP.

## Le code récupéré
L'arborescence de source contient les fichiers suivants :
~~~
src/
├── main
│   ├── java
│   │   └── fr
│   │       └── ulille
│   │           └── iut
│   │               └── todo
│   │                   ├── BDDFactory.java
│   │                   ├── dao
│   │                   │   ├── TacheDAO.java
│   │                   │   ├── UUIDArgumentFactory.java
│   │                   │   └── UUIDArgument.java
│   │                   ├── DebugMapper.java
│   │                   ├── dto
│   │                   │   └── CreationTacheDTO.java
│   │                   ├── Main.java
│   │                   ├── ressource
│   │                   │   ├── BDDClearRessource.java
│   │                   │   └── TodoRessource.java
│   │                   └── service
│   │                       ├── Tache.java
│   │                       └── TodoService.java
│   └── resources
│       └── logging.properties
└── test
    └── java
        └── fr
            └── ulille
                └── iut
                    └── todo
                        └── ressource
                            └── TodoRessourceTest.java
~~~

On peut constater un certain nombre de changements par rapport au TP précédent :

1. L'arborescence de test comprend maintenant une classe de tests pour notre ressource
2. Un paquetage `dao` a été ajouté qui contient le code lié à la gestion de la persistance
3. Une classe `BDDFactory` est fournie qui gère la connexion à la base de donnée
Yvan Peter's avatar
Yvan Peter committed
4. La configuration de l'affichage des logs est maintenant géré par un fichier de configuration externe `logging.properties`

## Test manuel et découverte du code
Yvan Peter's avatar
Yvan Peter committed
Avant de commencer à compléter le code fournit, nous allons tester un petit peu :

Dans un terminal, lancez le serveur avec la commande `mvn compile exec:java`.

Dans un autre terminal, essayez la commande suivante pour créer une tâche : `curl -i -H "Content-Type: application/json" -d '{"nom": "tâche 1", "description": "tester la création"}' http://localhost:8080/api/v1/taches`.

Vous devriez obtenir le résultat suivant :

~~~
HTTP/1.1 201 Created
Location: http://localhost:8080/api/v1/taches/4ba24fd7-5856-4678-8f9e-84802e3334dd
ETag: "1387196213"
Content-Type: application/json
Content-Length: 98

{"description":"tester la création","id":"4ba24fd7-5856-4678-8f9e-84802e3334dd","nom":"tâche 1"}
~~~

Une requête pour obtenir la liste des tâches vous confirmera que votre tâche est bien conservée de manière persistante :

~~~
$ curl -i http://localhost:8080/api/v1/taches

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 100

[{"description":"tester la création","id":"4ba24fd7-5856-4678-8f9e-84802e3334dd","nom":"tâche 1"}]
~~~
Yvan Peter's avatar
Yvan Peter committed
On peut également vérifier la présence de nos données dans la base de données ( ̀sqlite` ) :

~~~
$ sqlite3 /tmp/peter_todo.db 
SQLite version 3.33.0 2020-08-14 13:23:32
Enter ".help" for usage hints.
sqlite> select * from taches;
4ba24fd7-5856-4678-8f9e-84802e3334dd|tâche 1|tester la création
~~~

Yvan Peter's avatar
Yvan Peter committed
Les opérations de manipulation de la table `taches` sont définies dans la classe `TacheDAO` avec des annotations [JDBI](https://jdbi.org/#_sql_objects) :

~~~java
public interface TacheDAO {
    @SqlUpdate("create table if not exists taches (id varchar(128) primary key, nom varchar not null, description varchar)")
    void createTable();

    @SqlUpdate("drop table if exists taches")
    void dropTable();

    @SqlUpdate("insert into taches (id, nom, description) values (:id, :nom, :description)")
    int insert(@BindBean Tache tache);

    @SqlQuery("select * from taches")
    @RegisterBeanMapper(Tache.class)
    List<Tache> getAll();
}
~~~

Ce DAO est utilisé dans la classe `Tache` qui représente une tâche particulière. Les tâches sont manipulées via la classe `TodoService`.

Yvan Peter's avatar
Yvan Peter committed
Si vous regardez le code de la classe `Tache`, vous constaterez que nous avons choisi d'identifier les tâches au moyen d'un identifiant unique ([UUID](https://fr.wikipedia.org/wiki/Universally_unique_identifier)). Comme ce type n'est pas géré nativement par JDBI, nous avons dû utiliser un [mécanisme d'extension](https://jdbi.org/#_custom_arguments) permettant la conversion entre le type `java.util.UUID` et `String` (classes `UUIDArgument` et `UUIDArgumentFactory`).

# Développement de la ressource
Dans la mesure où nous allons maintenant avoir des tests, ce développement se fera en TDD.

## Définition de l'API pour notre gestion des tâches
Yvan Peter's avatar
Yvan Peter committed
Notre ressource sera accessible via le chemin `/api/v1`. Le tableau ci-dessous liste les URI et les méthodes supportées par notre ressource ainsi que les représentation utilisés (au format JSON).

| URI                      | Méthode | MIME                                                                                       | Requête    | Réponse              |
|--------------------------|---------|--------------------------------------------------------------------------------------------|------------|----------------------|
Yvan Peter's avatar
Yvan Peter committed
| /taches                  | GET     | <-application/json<br><-application/xml                                        |            | liste des tâches     |
| /taches                  | POST    | <-:->application/json<br><-:application/x-www-form-urlencoded | tâche (T1) |                      |
| /taches/{id}             | GET     | <-:application/json<br><-:application/xml                                |            | la tâche (T2)         |
| /taches/{id}             | PUT     | <-:->application/json                                                  | tâche (T2)  | la nouvelle tâche (T2) |
Yvan Peter's avatar
Yvan Peter committed
| /taches/{id}             | DELETE  |                                                                                            |            | 204 No Content       |
Yvan Peter's avatar
Yvan Peter committed
| /taches/{id}/description | GET     | <-:text/plain                                                                     |            | chaîne de caractères |
Yvan Peter's avatar
Yvan Peter committed
## Récupérer une tâche
Nous pouvons déjà lancer les tests pour voir ce qu'il se passe : `mvn test`.

~~~
Results :

Tests in error: 
  get_with_id_should_return_task(fr.ulille.iut.todo.ressource.TodoRessourceTest): HTTP 404 Not Found

Tests run: 9, Failures: 0, Errors: 1, Skipped: 0
~~~

Le test en erreur correspond à la fonctionnalité à développer :

~~~java
@Test
    public void get_with_id_should_return_task() {
        Tache tache = new Tache();
        tache.setNom("test");
        tache.setDescription("description");
        dao.insert(tache);

        Tache returned = target("taches").path(tache.getId().toString()).request().get(Tache.class);

        assertEquals(tache, returned);
    }
~~~

Pour ce test, nous créons un objet `Tache` qui est ensuite directement inséré dans la base grâce au DAO. Nous utilisons ensuite l'API [Client](https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest3x/client.html) pour faire notre requête `GET`. Pour simplifier le développement des tests, nous utilisons les [classes de test de Jersey](https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest3x/test-framework.html).

Vous pouvez maintenant développer la méthode correspondante dans la classe `TodoRessource`.