tete du loic

 Loïc YON [KIUX]

  • Enseignant-chercheur
  • Référent Formation Continue
  • Responsable des contrats pros ingénieur
  • Référent entrepreneuriat
  • Responsable de la filière F2 ingénieur
  • Secouriste Sauveteur du Travail
mail
loic.yon@isima.fr
phone
(+33 / 0) 4 73 40 50 42
location_on
ISIMA
  • twitter
  • linkedin
  • viadeo

eco ZZouvenir money

Date de première publication : 2026/01/07

L'objectif de ce TP est d'exposer une API REST (de type HATEOAS) de données stockées dans une base non relationnelles comme MongoDB.

Les données exposées concernent la gestion de collections/d'albums de "billets souvenir".

Billet
Billet

Mongo DB

Les machines à l'ISIMA sont configurées pour vous permettre d'utiliser docker. Si vous voulez travailler sur votre propre machine, il vous faudra installer ce qu'il faut. Par exemple, sous MacOS, il faut installer Docker Desktop

Pour utiliser docker à l'ISIMA, vous devez toutefois lancer :


docker_rootless_init.sh

docker pull mongo:latest

docker run -d \
  --name mongodb \ 
  -p 27017:27017 \ 
  -v mongodb_data:$HOME/Documents/MONGO \ 
  mongo:latest

Voici quelques commandes docker pour la gestion de votre image :


docker ps

docker stop mongodb
docker start mongodb

docker rm mongodb # donnees conservees
docker volume rm mongodb_data # suppression des donnees

J'aime bien manipuler la base MongoDB en ligne avec le shell :


docker exec -it mongodb mongosh

Voici quelques commandes :


show dbs
use base
show collections

db.types.deleteMany({});
db.collections.find();

Vous pouvez également installer Mongo DB Compass qui propose une interface graphique pour manipuler les "bases"

Mise en place du projet

Il faut créer un nouveau projet Spring Boot et choisir les options suivantes :

On a sélectionné les options suivantes :

Dans le fichier application.properties, il faudra dire quelle base utiliser (on peut spécifier utilisateur et mot de passe entre autres) :


spring.mongodb.uri=mongodb://localhost:27017/zzouvenir

Nous allons avoir besoin de décrire les données à mettre en base :

Avec les options SpringBoot choisies, toutes les classes sont des Document - les instances peuvent être exposées.

Chaque document a besoin d'un identifiant , soit au travers d'un attribut annoté @Id, soit un champ _id calculé automatiquement par MongoDB.

La base MongoDB ne gère pas les relations comme pourrait le faire une base SQL et notamment les suppressions en cascade par exemple.

On peut gérer la notion de "clé étrangère" avec les annotations @DocumentReference (NOSQL - à privilégier), @DBRef (NOSQL) ou encore @OneToMany (objet).

Voici donc un squelette de code pour gérer tout cela : (n'hésitez pas à utiliser Lombok pour générer les méthodes)


import org.springframework.data.annotation.Id;

class BilletType {
    @Id
    String id;
    String annee;
    String amorce;

    public BilletType(String annee, String amorce) {
        this.id = annee+amorce;
        this.annee = annee;
        this.amorce = amorce;
    }

import org.springframework.data.annotation.Id;
import java.util.*;

class Album {

    @Id
    String id;
    List<Billet> billets;

    public Album(String id) {
        this.id = id;
        billets = new ArrayList<Billet>();
    }

    public void add(Billet billet) {
        billets.add(billet);
    }
}

Pour finir, la classe Billet :


class Billet {

    String id;
    BilletType type;
    String numero;

    public Billet(BilletType type, String numero) {
        this.id = type.getId()+numero;
        this.type = type;
        this.numero = numero;
    }
}

Il faut encore écrire les repositories BilletTypeRepository et AlbumRepository


import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

// annotation optionnelle, sauf si on veut changer le nom de publication
@RepositoryRestResource(collectionResourceRel = "types", path = "types")
public interface BilletTypeRepository extends MongoRepository {
}  

On doit encore tester que cela marche. Créons quelques données :


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ZZouvenirApplication  implements CommandLineRunner {

	@Autowired
	BilletTypeRepository types;

    @Autowired
	AlbumRepository albums;

	public static void main(String[] args) {
		SpringApplication.run(ZZouvenirApplication.class, args);
	}

	@Override
    public void run(String... strings) throws Exception {
		albums.deleteAll();
		types.deleteAll();

    BilletType type1 = new BilletType("2024", "AECG");
	BilletType type2 = new BilletType("2023", "FDSSS");
	types.save(type1);
	types.save(type2);

    Album album = new Album("loic");

	Billet billet = new Billet(type1, "000001");
	album.add(billet);
	album.add(new Billet(type2, "000002"));
	albums.save(album);

    
    System.out.println("BilletTypes found with findAll():");
    System.out.println("-------------------------------");
    for (BilletType btype : types.findAll()) {
      System.out.println(btype);
    }
	}
}

On peut vérifier que la base est bien peuplée avec CURL ou un navigateur :


curl http://localhost:8080
curl http://localhost:8080/types
curl http://localhost:8080/albums
curl http://localhost:8080/albums/loic


curl -i -X POST -H "Content-Type:application/json" -d "{  \"id\" : \"autre\" }" http://localhost:8080/albums

Par défaut, tous les repositories sont publiés. On peut se limiter à ceux qui sont annotés avec @RepositoryRestResource, il faut alors ajouter la configuration suivante : spring.data.rest.detection-strategy=annotated

On peut aussi interdire un type d'action à réaliser, soit en écrivant une configuration :


@Configuration public class RestConfig implements RepositoryRestConfigurer { 
   @Override 
   public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 
      config.getExposureConfiguration() 
        .forDomainType(BilletType.class) .withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.DELETE)) 
        .withCollectionExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.DELETE)); 
  } 
}

soit en annotant un repository :


@RepositoryRestResource
public interface BilletTypeRepository extends ... {

    @Override
    @RestResource(exported = false)
    void deleteById(String id);

    @Override
    @RestResource(exported = false)
    void delete(BilletTypeRepository entity);
}

Allez plus loin

Il faudrait maintenant sécuriser l'API pour que seuls certains utilisateurs (avec des rôles) puissent accéder aux informations.

Liens