:: Enseignements :: Master :: M1 :: 2023-2024 :: Java Avancé ::
[LOGO]

Projet du premier semestre INFO2 - 2023


Exercice 1 - GitClout

Le but du projet GitCout est d'écrire une application web qui analyse les tags d'un repository git (par exemple sur github ou gitlab) et affiche différentes informations permettant de mieux comprendre les contributions de chaque collaborateur.
L'application GitCout est composée d'un back-end écrit en Java offrant différents services REST permettant d'accéder aux informations de contribution et d'un front-end écrit en JavaScript affichant les informations sous forme de graphe et autres gizmos visuels.
L’application doit permettre...
  • ... d'ajouter un nouveau repository. Il n'y a pas de notion d'utilisateur, tout le monde peut ajouter un repository
    Le repository est alors analysé et pour chaque tag, l'application doit calculer la contribution de chaque contributeur. Comme le calcul peut être lent (normalement pas trop), l'application doit visuellement afficher l'état du calcul (le nombre de tags pour lesquels les calculs ont été effectué par rapport aux nombres de tags total sous forme d'une barre de progression).
  • ... d'afficher pour chaque contributeur pour un tag, le nombre de lignes totales contribué (git blame permet de savoir qui a été le dernier à éditer une ligne) le nombre de lignes par type de fichiers (fichiers de codes (.java, .c, etc) sans compter les commentaires,, fichier de build (pom.xml), fichier de configuration du CI (dans le .github par exemple), fichier de resources (text, images, videos, etc), fichier de documentation (javadoc, docstring, fichier README.md (en fait, tous les fichiers .md)) un graphique radar par contributeur avec les valeurs ci-dessus, une par axe.
    Note: organiser vos axes intelligemment pour que cela corresponde à une certaine réalité la tendance par rapport à la moyenne des 5 tags (valeur que l'on peut changer) précédents pour les valeurs ci-dessus, avec des flèches ↑ et ↓
  • ... d'afficher un graphique en baton où l'on voit la contribution de l'ensemble des collaborateurs que l'on peut avec une barre par collaborateur (la barre étant composée de couleur pour chaque type de valeurs) que l'on peut trier en fonction des types des valeurs. Par exemple, on peut trier les collaborateurs (donc les barres des collaborateurs) en fonction du nombre de lignes de commentaire contribuées.

En termes d'interface graphique, votre application doit être composée de deux écrans :
  • Le premier écran sert d'écran d'accueil et affiche l'ensemble des repositories disponibles, avec les tags de chaque repositories.
    Il doit permettre d'ajouter un nouveau repository ou de mettre à jour un repository déjà existant. Visuellement, il est important de ne pas utiliser de fenêtre modale mais que l'on puisse saisir l'URL du nouveau repository directement sur la page.
  • Un seconde page affiche les informations pour un repository. L'écran est décomposé en trois parties sur l'axe vertical. La partie haute l'ensemble des tags (qui scrolle horizontalement, s'il y a trop de tags). La partie du milieu indique la contribution de tous les collaborateurs (en utilisant la vue en baton) pour un tag sélectionné dans la partie du haut. La partie du bas indique les diagrammes radar de chaque collaborateur. Cette partie peut aussi scroller quand il y a beaucoup de collaborateur.

Technologies à utiliser
  • Vous devez utiliser Maven comme outil de build et IntelliJ comme IDE, et la version 21 de Java.
  • Pour tester vos services REST, vous pouvez utiliser Postman ou tout autres clients capables de faire des requêtes REST.
  • Les test unitaires Java doivent être effectués avec JUnit 5.10.0, vous pouvez vous référer au guide d'utilisation.
    Chaque classe classe Java doit avoir une classe de test correspondante (pour au moins 80%) du projet.
  • Pour la sérialisation/dé-sérialisation JSON des requêtes, vous utiliserez une API de parsing JSON Jackson 2.15.2
  • Pour s'interfacer avec Git, vous utiliserez Jgit 6.7.0.202309050840-r.

Pour implanter les différents services REST, votre application doit utiliser une des technos (c'est moi qui choisi pas vous) ci-dessous.
Attention à bien faire la différence entre les versions AOT ou JVM et les versions synchrone et asynchrone (reactive) des APIs ! Pour Spring, Quarkus et Micronaut, vous configurerez le serveur pour qu'il utilise des threads virtuelles.
Pour la version native image, l'application générée doit être un exécutable au lieu d'un jar.
Pour l'API REST, les entrées et les sorties JSON doivent utiliser des records si possible.
Pour la mapping Object / Relational, i.e voir une ligne d'une table de BDD comme un objet Java. Il y a deux implantations, une à base d'Hibernate qui peut être utilisée directement soit par l'intermédiaire de la spécification JPA (Jakarta Persistence API). Et une à base de JDBI.
Attention, l'ancienne version de la Jakarta Persistence API s'appelle la Java Persistence API, les deux ont le même acronyme JPA. On veut la nouvelle version donc la version Jakarta.
Pour le front-end web, vous avez besoin d'un framework graphique
Note : le front-end doit être "buildé" aussi en utilisant Maven (un seul POM pour front et le back), vous aurez peut-être besoin de plugin Maven spécifique pour cela.
Note2: vous avez besoin de npm pour la partie build, mais pas à l'exécution ! Vous pouvez de plus, utiliser une librairie spéciale pour la gestion de l'affichage du tableau pourvu quelle soit adaptée à votre framework (pas de react-grid si vous devez utiliser svelte).
Attention: lors du déploiement, vous ne devez pas utiliser nodejs comme serveur Web, car vous avez déjà un serveur Web qui sert l'API donc il peut aussi servir les pages statiques de votre librarie JS. Bien sûr, pour le build, vous pouvez utiliser nodejs et npm pour construire votre application web.
Pour vous aidez à avoir de belles pages, vous allez aussi utiliser une bibliothèque qui vous aide pour la partie CSS
L'application a besoin d'une base de données, mais vu le volume de données, pas forcément d'une "vrai" base de données, nous utiliserons donc des bases de données embedded.
L'intérêt d'une BDD embedded est qu'elle est prête à l'emploi directement à partir d'un jar.
Il y a deux façons d'accéder à une BDD en Java, en utilisant le Driver JDBC ou le DataSource JDBC. On vous demande d'utiliser le DataSource car la gestion des connexions à la BD est automatique. Dans le cas où vous utilisez JPA / Hibernate, il vous faut aussi ajouter une dépendence sur Dialect correspondant à votre base de donnees car chaque base de données parle un SQL un petit peu différent.
Attention, ces BDDs embedded peuvent être utilisées aussi comme des BDDs classiques extérieurs à l'application, ce n'est pas ce qui nous intéresse ici, on veut la version embedded !
Et on ne veut pas que la base de donnée disparaisse quand on quitte l'application !

REST API documentation
Nous allons documenter l'API REST de votre back-end en utilisant le format Open API 3.
Note : il y a deux façons d'utiliser Open API, soit on l'utilise comme un générateur qui génère le squelette de l'API, soit dans l'autre sens, on extrait les valeurs des classes Java. On va utiliser la seconde version, comme cela, la documentation de l'API sera toujours à jour avec le code.

Sécurité :
  • Pas de HTTPS pour ce projet (c'est mal) mais c'est pour vous aider à débugger !
  • Les entrées des services web au niveau de l'URL ou de la partie JSON doivent être validées et les sorties doivent être "escapées" pour éviter les injections de code.
  • Il n'est pas demandé d'identifier les utilisateurs, optionnellement, vous pouvez le faire, mais dans ce cas, vous devez utiliser des tokens JWT et la bibliothèque de votre choix.
  • Vous ne devriez pas avoir besoin de requêtes CORS ! Sinon, cela veut dire que l'API REST et votre application JavaScript ne sont pas servis par le même serveur.
  • Il n'y a aucune raison que le login/mdp de la BDD soit en dur dans votre code !

Binômes avec les technos qui doivent être utilisées
   Binome                 | BACKEND                | PERSISTENCE           | DB       | FRONTEND         | UI
   YAZAN-LE_SAGER         | Quarkus 3 native image | Jdbi                  | Sqlite   | react state hook | tailwind
   BARRAU-ARIK            | Micronaut 4 Reactive   | JPA                   | HyperSQL | svelte           | tailwind
   BASHEER-NAFIS_AOUDIA   | Helidon 3 MP Reactive  | JPA                   | HyperSQL | svelte           | semantic
   BENESBY-FORBIN         | Quarkus 3 Reactive     | Hibernate with panache| Derby    | svelte           | bulma
   BENMECHICH-KY          | Spring 6               | JPA                   | H2       | reactjs component| tailwind
   BERNIER-ROUX_DAUGROIS  | Helidon Nima           | DBClient              | Sqlite   | react state hook | bulma
   BONNIER-FRAIZE         | Quarkus 3 Reactive     | Hibernate with panache| H2       | solidjs          | tailwind
   CARRETTE-VU            | Spring 6               | JPA                   | Sqlite   | reactjs component| material UI
   DEBATS-LY_IENG         | Spring 6               | JPA                   | Derby    | vuejs            | semantic
   DJADJA-FERNANDES       | Helidon 3 MP           | JPA                   | HyperSQL | vuejs            | tailwind
   FOUILLE-SLOSSE         | Quarkus 3 native image | JPA                   | HyperSQL | vuejs            | semantic
   GARDABOU-ROBERT        | Micronaut 4            | Jdbi                  | Derby    | angular          | bootstrap
   GIL-ISTASSES           | Helidon 3 MP           | Jdbi                  | Sqlite   | react state hook | tailwind
   HAIDAMOUS-NGUYEN       | Spring 6               | JPA                   | Sqlite   | vuejs            | bulma
   HAMMA-EL_FAHEM         | Quarkus 3              | JPA                   | H2       | vuejs            | tailwind
   JAILLARD_THEPHARATH    | Quarkus 3              | JPA                   | H2       | reactjs component| material UI
   KINGUE-WANG            | Quarkus 3              | JPA                   | derby    | vuejs            | tailwind
   LY-EA                  | Quarkus 3              | JPA                   | HyperSQL | reactjs component| tailwind
   MAIBECHE-FANOUS        | Micronaut 4	           | JPA                   | Sqlite   | react state hook | bootstrap
   MELLOUK-MENSAH         | Quarkus 3              | JPA                   | Sqlite   | vuejs            | semantic
   MENLET-NSSAIR          | Spring 6 native image  | Jdbi                  | Sqlite   | react state hook | bulma
   MOKEDDEM-COUSSON       | Helidon Nima           | DBClient              | H2       | riotjs           | semantic
   NDIBODJO-LE            | Spring 6               | JPA                   | HyperSQL | vuejs            | bulma
   NIMALAKUMARAN_BAKHTI   | Spring 6 reactive      | JPA                   | HyperSQL | solidjs          | semantic
   NODA                   | Quarkus                | JPA                   | H2       | vuejs            | tailwind
   RADONIAINA-OEUVRARD    | Spring 6 reactive      | JPA                   | Sqlite   | riotjs           | bulma
   RAJON-SIDHOUM          | Spring 6 native image  | JPA                   | H2       | angular          | semantic
   RAMOS-LUIS_PERRIOT     | Micronaut 4	           | JPA                   | HyperSQL | vuejs            | bootstrap
   RAVELOMANANTSOA-ZINSOU | Quarkus 3 native image | JPA                   | H2       | svelte           | bootstrap
   SAUTIER-HYVERT         | Helidon 3 SE           | DBClient              | Derby    | riotjs           | tailwind
   SEBBAH-BASTOS          | Helidon 3 SE           | DBClient              | HyperSQL | react state hook | semantic
   SEILLIEBERT-BILINGI    | Micronaut 4 Reactive   | JPA                   | Sqlite   | solidjs          | bootstrap
   SUN-EBA                | Spring 6 native image  | JPA                   | HyperSQL | vuejs            | bulma
   TRAN-NINO              | Helidon 3 MP Reactive  | JPA                   | Sqlite   | solidjs          | bulma
   TREMELLAT-TAGNAN       | Micronaut 4	           | JPA                   | H2       | angular          | tailwind
   VECCHIO-ATTIG          | Helidon 3 MP           | JPA                   | H2       | angular          | bulma
  

Calendrier des rendus.
Soutenance intermédiaire (bêta) : mi-novembre (date exacte TBD)
Toutes les parties de l'architecture doivent être présentes et communiquer entre elles. Votre API REST doit être visible en utilisant Swagger (le frontend graphique OpenAPI). Il peut y avoir des bugs, ce n'est pas grave, mais on doit avoir la majorité de l'affichage qui marche.
Soutenance finale : 31 décembre 2023 à 23h59
Tout doit marcher parfaitement, les docs utilisateur et de développement doivent être présentes.

Pour vous aider, si vous ne respectez pas les indications de "sudden death" suivantes, votre projet sera considéré comme mort et noté 0.
Pour la partie Java, le programme doit être écrit en utilisant correctement les différents concepts vus lors du cours de Java Avancé (sous-typage, polymorphisme, pattern matching, lambdas, classes internes, exceptions, types paramétrés, collections, entrées/sorties).
  • Une des technologies que votre projet utilise n'est pas celle requise pour votre binôme
  • Vous avez la même API REST qu'un projet d'un autre binôme.
  • Il ne doit pas y avoir de warnings lorsque l'on compile avec javac -Xlint:all.
  • Dans un module, les packages d'implantation ne doivent pas être exportés et requires transitive doit être utilisé là où c'est nécessaire.
  • Il ne doit pas y avoir de raw types, de @SuppressWarning non justifié, de cast non justifié.
  • Le principe d'encapsulation et la programmation par contrat doivent être respectées.
  • Il ne doit pas y avoir de champs ou méthodes protected.
  • Il ne doit pas y avoir d'instanceof/if...else sur des types là où il est possible d'utiliser le polymorphisme ou le pattern matching.
  • Chaque interface devra être nécessaire.
    Une interface possède 0 ou 1 méthode (sinon justifiée).
  • Aucune classe abstraite ne doit être publique ou utilisée comme un type.
  • Chaque méthode devra être appelée (pas de code mort).
  • Aucune méthode ne doit faire plus de 10 lignes sans une vraie justification.
  • Il est interdit d'utiliser des champs static typés par un objet (pas de variables globales), seules les constantes (static final) de type primitif sont autorisées (et utiliser l'injection de dépendance SVP).
  • Le fichier POM.xml ne doit pas contenir de dépendances non listées dans ce document où ayant une autre version que la version demandée (à part les dépendances de dépendances).