diff --git a/.gitignore b/.gitignore index e940f50d8d969e55d74eec229e2e53a80430b4c7..67516d3a4b87a2cc0ead755323100a2083eca900 100644 --- a/.gitignore +++ b/.gitignore @@ -206,5 +206,7 @@ local.properties ### VisualStudioCode Patch ### # Ignore all local history of files .history - +.project +.settings +.classpath # End of https://www.gitignore.io/api/eclipse,visualstudiocode diff --git a/README.md b/README.md index 7f16058543c83b9f04f56b4a010e09498bfc2191..ffe4bdbb88466662a228971229fc21e939502694 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,6 @@ # Développement REST avec Jersey ## Mise en place de l'environnement -Ce tutoriel utilise [Apache Maven](http://maven.apache.org/) pour -l'automatisation des tâches de développement (compilation, tests, -déploiement...). - -Si votre machine se trouve derrière un -proxy, vous devrez mettre la configuration suivante dans le fichier -`~/.m2/settings.xml` (à adapter à votre environnement) : - - <settings> - <proxies> - <proxy> - <id>lille1-proxy</id> - <active>true</active> - <protocol>http</protocol> - <host>cache.univ-lille.fr</host> - <port>3128</port> - </proxy> - <proxy> - <id>lille1-proxy-sec</id> - <active>true</active> - <protocol>https</protocol> - <host>cache.univ-lille.fr</host> - <port>3128</port> - </proxy> - </proxies> - </settings> - -En local, vous pouvez également recopier le fichier `/home/public/peter/maven/settings.xml`. ## Récupération du projet initial Pour récupérer le projet vous pouvez utiliser la commande `git clone @@ -61,8 +33,6 @@ les paquetages Java qui contiennent les ressources. │ ├── resources │ │ ├── ingredients.json │ │ └── logback.xml - │ └── webapp - │ └── WEB-INF └── test ├── java │ └── fr @@ -97,12 +67,12 @@ Un ingrédient comporte uniquement un identifiant et un nom. Sa représentation JSON prendra donc la forme suivante : { - "id": 1, + "id": "f38806a8-7c85-49ef-980c-149dcd81d306", "name": "mozzarella" } Lors de la création, l'identifiant n'est pas connu car il sera fourni -par la base de données. Aussi on aura une +par le JavaBean qui représente un ingrédient. Aussi on aura une représentation JSON qui comporte uniquement le nom : { "name": "mozzarella" } @@ -169,6 +139,7 @@ Le code suivant qui se trouve dans la classe `IngredientResourceTest` montre la mise en place de l'environnement (`configure()`) et l'amorce d'un premier test. +~~~java public class IngredientResourceTest extends JerseyTest { @Override @@ -189,10 +160,11 @@ d'un premier test. assertEquals(0, ingredients.size()); } +~~~ En héritant de JerseyTest, votre classe de test se comporte comme un [`Client` -JAX-RS](https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Client.html). La +JAX-RS](https://docs.oracle.com/javaee/7/api/jakarta/ws/rs/client/Client.html). La méthode `target()` notamment permet de préparer une requête sur une URI particulière. @@ -207,6 +179,7 @@ DTO `IngredientDto`. Pour commencer, on se contentera de l'implémentation minimale suivante : +~~~java package fr.ulille.iut.pizzaland.dto; public class IngredientDto { @@ -215,23 +188,27 @@ suivante : } } +~~~ A ce stade, vous pouvez lancer un premier test au moyen de la commande `mvn test`. Évidemment, ce test va échouer. +~~~ $ mvn test Results : Failed tests: testGetEmptyList(fr.ulille.iut.pizzaland.IngredientResourceTest): expected:<200> but was:<404> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0 - +~~~ + Pour réussir, ce premier test, nous allons mettre en place la ressource `IngredientResource`. Une première implémentation de la ressource pourra avoir la forme suivante : +~~~java @Path("/ingredients") public class IngredientResource { @@ -247,27 +224,30 @@ suivante : return new ArrayList<IngredientDto>(); } } - +~~~ + Avec cette première implémentation, on va pouvoir tester notre ressource : +~~~ $ mvn test Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +~~~ ### Récupérer un ingrédient existant Nous allons continuer en ajoutant la possibilité de récupérer un ingrédient particulier à partir de son identifiant. Pour cela voici un premier test qui permettra de vérifier cela : - + +~~~java import fr.ulille.iut.pizzaland.beans.Ingredient; @Test public void testGetExistingIngredient() { Ingredient ingredient = new Ingredient(); - ingredient.setId(1); ingredient.setName("mozzarella"); Response response = target("/ingredients/1").request().get(); @@ -276,12 +256,14 @@ Pour cela voici un premier test qui permettra de vérifier cela : Ingredient result = Ingredient.fromDto(response.readEntity(IngredientDto.class)); assertEquals(ingredient, result); } +~~~ Vous pourrez vérifier que le test échoue au moyen de la commande `mvn test` Afin de réussir ce test, nous devons compléter la classe IngredientDto avec les getter/setter correspondant aux propriétés de l'object JSON. +~~~java public class IngredientDto { private long id; private String name; @@ -304,10 +286,12 @@ avec les getter/setter correspondant aux propriétés de l'object JSON. return name; } } +~~~ Du côté de la ressource, on peut fournir une première implémentation : - import javax.ws.rs.PathParam; +~~~java + import jakarta.ws.rs.PathParam; import fr.ulille.iut.pizzaland.beans.Ingredient; @GET @@ -319,11 +303,13 @@ Du côté de la ressource, on peut fournir une première implémentation : return Ingredient.toDto(ingredient); } +~~~ Pour cette méthode, nous avons introduit la classe `Ingredient`. Ce JavaBean représente un ingrédient manipulé par la ressource. Voici une implémentation pour cette classe : +~~~java package fr.ulille.iut.pizzaland.beans; import fr.ulille.iut.pizzaland.dto.IngredientDto; @@ -396,11 +382,14 @@ Voici une implémentation pour cette classe : return "Ingredient [id=" + id + ", name=" + name + "]"; } } +~~~ Le test devrait maintenant réussir : +~~~ $ mvn test - +~~~ + ## Introduction de la persistence Pour aller plus loin et mettre en place la création des ingrédients il va falloir introduire la persistence. Pour cela, nous allons utiliser @@ -409,6 +398,7 @@ base de données. Pour cela nous allons devoir implémenter le DAO (Data Access Object) `IngredientDao` : +~~~java package fr.ulille.iut.pizzaland.dao; import java.util.List; @@ -440,6 +430,7 @@ Pour cela nous allons devoir implémenter le DAO (Data Access Object) `Ingredien @RegisterBeanMapper(Ingredient.class) Ingredient findById(long id); } +~~~ JDBI fonctionne par annotations : - Les annotations `sqlUpdate` et `SqlQuery` correspondent à des @@ -459,7 +450,8 @@ tests qui est définie via la classe `BDDFactory`. Les méthodes `setEnvUp` et `tearEnvDown` permettent de créer et détruire la base de données entre chaque test. - + +~~~java import fr.ulille.iut.pizzaland.dao.IngredientDao; public class IngredientResourceTest extends JerseyTest { @@ -499,15 +491,17 @@ détruire la base de données entre chaque test. Ingredient result = Ingredient.fromDto(response.readEntity(IngredientDto.class)); assertEquals(ingredient, result); } +~~~ ### La ressource avec la base de données +~~~java import fr.ulille.iut.pizzaland.BDDFactory; import fr.ulille.iut.pizzaland.dao.IngredientDao; import java.util.stream.Collectors; - import javax.ws.rs.WebApplicationException; + import jakarta.ws.rs.WebApplicationException; public class IngredientResource { private IngredientDao ingredients; @@ -538,42 +532,48 @@ détruire la base de données entre chaque test. throw new WebApplicationException(Response.Status.NOT_FOUND); } } - } +~~~ ### Les tests fonctionnent avec la base de données Nous pouvons maintenant vérifier que la base fonctionne avec la base de données : +~~~ $ mvn test Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 +~~~ ## Complétons maintenant les différents tests L'implémentation de la classe devrait fonctionner avec le test suivant : - +~~~java @Test public void testGetNotExistingIngredient() { Response response = target("/ingredients/125").request().get(); assertEquals(Response.Status.NOT_FOUND.getStatusCode(),response.getStatus()); } +~~~ +~~~ $ mvn test Results : Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 +~~~ ### Implementation de la méthode POST Il va falloir implémenter la méthode POST pour la création des ingrédients. Commençons par les différents tests : création, création de deux ingrédients identiques et création d'ingrédient sans nom. +~~~java import fr.ulille.iut.pizzaland.dto.IngredientCreateDto; @Test @@ -622,17 +622,19 @@ de deux ingrédients identiques et création d'ingrédient sans nom. assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus()); } +~~~ Nous utiliserons un DTO spécifique `IngredientCreateDto` dans la mesure où nous n'aurons que le nom de l'ingrédient pour la création. -La classe [`javax.ws.rs.client.Entity<T>`](https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Entity.html) permet de définir le corps de +La classe [`jakarta.ws.rs.client.Entity<T>`](https://docs.oracle.com/javaee/7/api/jakarta/ws/rs/client/Entity.html) permet de définir le corps de la requête POST et le type de données associée (ici `application/json`). Nous devons également fournir une implémentation de `IngredientCreateDto` pour pouvoir compiler notre code : - package fr.ulille.iut.pizzaland.dto; +~~~java + package fr.ulille.iut.pizzaland.dto; public class IngredientCreateDto { private String name; @@ -647,10 +649,12 @@ Nous devons également fournir une implémentation de return name; } } +~~~ Nous pouvons maintenant compiler notre code de test et constater que ceux-ci échouent. +~~~ $ mvn test Results : @@ -660,11 +664,13 @@ ceux-ci échouent. testCreateIngredient(fr.ulille.iut.pizzaland.IngredientResourceTest): expected:<201> but was:<405> Tests run: 6, Failures: 3, Errors: 0, Skipped: 0 +~~~ Nous pouvons maintenant implémenter notre méthode POST dans la ressource : - - import javax.ws.rs.POST; + +~~~java + import jakarta.ws.rs.POST; import fr.ulille.iut.pizzaland.dto.IngredientCreateDto; @@ -690,17 +696,21 @@ Nous pouvons maintenant implémenter notre méthode POST dans la throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE); } } +~~~ Comme nous vérifions qu'il n'y a pas déjà un ingrédient avec le nom fourni, nous devont ajouter une méthode `findbyName` à notre DAO +~~~java @SqlQuery("SELECT * FROM ingredients WHERE name = :name") @RegisterBeanMapper(Ingredient.class) Ingredient findByName(String name); +~~~ Nous avons également besoin de rajouter les méthodes de conversion pour ce DTO à notre bean `Ingredient` : - + +~~~java import fr.ulille.iut.pizzaland.dto.IngredientCreateDto; public static IngredientCreateDto toCreateDto(Ingredient ingredient) { @@ -716,14 +726,17 @@ Nous avons également besoin de rajouter les méthodes de conversion return ingredient; } +~~~ Nous pouvons maintenant vérifier nos tests : +~~~ $ mvn test Results : Tests run: 6, Failures: 0, Errors: 0, Skipped: 0 +~~~ Vous aurez peut-être un affichage d'exception liée au test de création de doublon, toutefois le test est réussi puisqu'il a levé une @@ -732,6 +745,7 @@ exception qui a été traduite par un code d'erreur HTTP 406. ### Implémentation de la méthode DELETE Les tests liés à la méthode DELETE sont les suivants : +~~~ @Test public void testDeleteExistingIngredient() { Ingredient ingredient = new Ingredient(); @@ -753,11 +767,13 @@ Les tests liés à la méthode DELETE sont les suivants : assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); } - +~~~ + Après avoir constaté que ces tests échouent, nous pouvons fournir une implémentation pour la méthode DELETE : - import javax.ws.rs.DELETE; +~~~java + import jakarta.ws.rs.DELETE; @DELETE @Path("{id}") @@ -770,12 +786,15 @@ implémentation pour la méthode DELETE : return Response.status(Response.Status.ACCEPTED).build(); } +~~~ Nous devons également implémenter la méthode remove dans `IngredientDao` : +~~~java @SqlUpdate("DELETE FROM ingredients WHERE id = :id") void remove(long id); +~~~ Avec cette implémentation, nos tests réussissent. @@ -783,6 +802,7 @@ Avec cette implémentation, nos tests réussissent. Commençons par les tests correspondant à cette URI (GET /ingredients/{id}/name) +~~~java @Test public void testGetIngredientName() { Ingredient ingredient = new Ingredient(); @@ -802,9 +822,11 @@ Commençons par les tests correspondant à cette URI (GET assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); } +~~~ L'implémentation correspondant à ce test est simple : +~~~java @GET @Path("{id}/name") public String getIngredientName(@PathParam("id") long id) { @@ -815,6 +837,7 @@ L'implémentation correspondant à ce test est simple : return ingredient.getName(); } +~~~ ### Implémentation d'une méthode de création avec des données de formulaire La création d'un ingrédient pourrait également se faire via un @@ -823,8 +846,9 @@ formulaire Web. Dans ce cas, le type de représentation sera On peut déjà préparer un test pour cette méthode de création : - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Form; +~~~java + import jakarta.ws.rs.core.MediaType; + import jakarta.ws.rs.core.Form; import static org.junit.Assert.assertNotNull; @@ -843,9 +867,11 @@ On peut déjà préparer un test pour cette méthode de création : assertNotNull(result); } +~~~ On peut maintenant fournir une implémentation pour cette méthode : +~~~java @POST @Consumes("application/x-www-form-urlencoded") public Response createIngredient(@FormParam("name") String name) { @@ -871,7 +897,7 @@ On peut maintenant fournir une implémentation pour cette méthode : throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE); } } - +~~~ # Créer une base de données de test Nous avons maintenant implémenté et testé toutes les méthodes prévues @@ -883,6 +909,7 @@ d'une variable d'environnement : `PIZZAENV`. Quand cette variable aura la valeur `withdb`, nous allons remplir la base au démarrage avec le code suivant : +~~~java import fr.ulille.iut.pizzaland.beans.Ingredient; import fr.ulille.iut.pizzaland.dao.IngredientDao; @@ -892,8 +919,8 @@ base au démarrage avec le code suivant : import java.util.ArrayList; import java.util.List; - import javax.json.bind.Jsonb; - import javax.json.bind.JsonbBuilder; + import jakarta.json.bind.Jsonb; + import jakarta.json.bind.JsonbBuilder; @ApplicationPath("api/v1/") public class ApiV1 extends ResourceConfig { @@ -922,16 +949,20 @@ base au démarrage avec le code suivant : } } } +~~~ + Dans un terminal, nous pouvons maintenant fixer la variable d'environnemnet et démarrer notre serveur REST au moyen de la commande `mvn jetty:run` : - + +~~~ $ export PIZZAENV=withdb - $ mvn jetty:run - + $ mvn exec:java +~~~ Dans un autre terminal, nous pouvons utiliser `curl` pour tester nos différentes méthodes : +~~~ $ curl -i localhost:8080/api/v1/ingredients HTTP/1.1 200 OK @@ -941,6 +972,7 @@ différentes méthodes : Server: Jetty(9.4.26.v20200117) [{"id":1,"name":"mozzarella"},{"id":2,"name":"jambon"},{"id":3,"name":"champignons"},{"id":4,"name":"olives"},{"id":5,"name":"tomate"},{"id":6,"name":"merguez"},{"id":7,"name":"lardons"},{"id":8,"name":"fromage"},{"id":9,"name":"oeuf"},{"id":10,"name":"poivrons"},{"id":11,"name":"ananas"},{"id":12,"name":"reblochon"}] +~~~ # Implémentation de la ressource Pizza Une pizza comprend des ingrédients. Pour développer cette ressource, @@ -949,6 +981,7 @@ de données. Cela pourra être géré au niveau du DAO grâce à [JDBI](https://jdbi.org/#_default_methods). Cet extrait de code montre comment faire : +~~~java import org.jdbi.v3.sqlobject.transaction.Transaction; public interface PizzaDao { @@ -964,6 +997,7 @@ comment faire : createAssociationTable(); createPizzaTable(); } +~~~ Vous écrivez les différentes méthodes annotées avec `@SqlUpdate` ou `@SqlQuery`. Vous utilisez ensuite ces méthodes au sein d'une méthode diff --git a/pom.xml b/pom.xml index 362dc673b01e9df01f971094a02dd32718fce444..727e9e25a71351db6a8e318bd0af200eeb688902 100644 --- a/pom.xml +++ b/pom.xml @@ -1,128 +1,163 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> + <modelVersion>4.0.0</modelVersion> - <groupId>fr.ulille.iut.pizzaland</groupId> - <artifactId>pizzaland_jdbi</artifactId> - <packaging>war</packaging> - <version>1.0-SNAPSHOT</version> - <name>pizzaland</name> + <groupId>fr.ulille.iut.pizzaland</groupId> + <artifactId>pizzaland_jdbi</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>pizzaland_jdbi</name> - <build> - <finalName>pizzaland</finalName> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.1</version> - <inherited>true</inherited> - <configuration> - <source>1.8</source> - <target>1.8</target> - <compilerArgs> - <arg>-parameters</arg> - </compilerArgs> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-war-plugin</artifactId> - <version>3.2.3</version> - <configuration> - <failOnMissingWebXml>false</failOnMissingWebXml> - </configuration> - </plugin> - <plugin> - <groupId>org.eclipse.jetty</groupId> - <artifactId>jetty-maven-plugin</artifactId> - <version>${jetty-version}</version> - <configuration> - <scanIntervalSeconds>10</scanIntervalSeconds> - </configuration> - </plugin> - </plugins> - </build> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.glassfish.jersey</groupId> + <artifactId>jersey-bom</artifactId> + <version>${jersey.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <dependency> + <groupId>org.jdbi</groupId> + <artifactId>jdbi3-bom</artifactId> + <type>pom</type> + <version>${jdbi.version}</version> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> - <dependencyManagement> - <dependencies> - <dependency> - <groupId>org.glassfish.jersey</groupId> - <artifactId>jersey-bom</artifactId> - <version>${jersey.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - <dependency> - <groupId>org.jdbi</groupId> - <artifactId>jdbi3-bom</artifactId> - <type>pom</type> - <version>3.12.0</version> - <scope>import</scope> - </dependency> - </dependencies> - </dependencyManagement> + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-grizzly2-http</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.inject</groupId> + <artifactId>jersey-hk2</artifactId> + </dependency> - <dependencies> - <dependency> - <groupId>org.glassfish.jersey.containers</groupId> - <!-- use the following artifactId if you don't need servlet 2.x compatibility --> - <artifactId>jersey-container-servlet</artifactId> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.inject</groupId> - <artifactId>jersey-hk2</artifactId> - </dependency> - <!-- uncomment this to get JSON support --> - <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-json-binding</artifactId> - </dependency> - <!-- --> - <dependency> - <groupId>org.glassfish.jersey.test-framework.providers</groupId> - <artifactId>jersey-test-framework-provider-jetty</artifactId> - <version>2.30</version> - </dependency> - <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc --> - <dependency> - <groupId>org.xerial</groupId> - <artifactId>sqlite-jdbc</artifactId> - <version>3.30.1</version> - </dependency> - <!-- https://mvnrepository.com/artifact/org.jdbi/jdbi3-core --> - <dependency> - <groupId>org.jdbi</groupId> - <artifactId>jdbi3-core</artifactId> - <version>3.12.0</version> - </dependency> - <dependency> - <groupId>org.jdbi</groupId> - <artifactId>jdbi3-sqlobject</artifactId> - <version>3.12.0</version> - </dependency> - <dependency> - <groupId>org.jdbi</groupId> - <artifactId>jdbi3-sqlite</artifactId> - <version>3.12.0</version> - </dependency> - <dependency> - <groupId>org.jdbi</groupId> - <artifactId>jdbi3-testing</artifactId> - <version>3.12.0</version> - <scope>test</scope> - </dependency> - <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> - <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - <version>1.2.3</version> - </dependency> - </dependencies> - - <properties> - <jersey.version>2.30</jersey.version> - <jetty-version>9.4.26.v20200117</jetty-version> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - </properties> + <!-- uncomment this to get JSON support: --> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-binding</artifactId> + </dependency> + <!-- --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.test-framework.providers</groupId> + <artifactId>jersey-test-framework-provider-grizzly2</artifactId> + <version>${jersey.version}</version> + </dependency> + <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc --> + <dependency> + <groupId>org.xerial</groupId> + <artifactId>sqlite-jdbc</artifactId> + <version>${sqlite-jdbc.version}</version> + </dependency> + <!-- https://mvnrepository.com/artifact/org.jdbi/jdbi3-core --> + <dependency> + <groupId>org.jdbi</groupId> + <artifactId>jdbi3-core</artifactId> + </dependency> + <dependency> + <groupId>org.jdbi</groupId> + <artifactId>jdbi3-sqlobject</artifactId> + </dependency> + <dependency> + <groupId>org.jdbi</groupId> + <artifactId>jdbi3-sqlite</artifactId> + </dependency> + <dependency> + <groupId>org.jdbi</groupId> + <artifactId>jdbi3-testing</artifactId> + <version>3.12.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <version>3.0.0</version> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <version>3.0.0</version> + <scope>runtime</scope> + </dependency> + <!-- dependency> + <groupId></groupId> + <artifactId></artifactId> + <version></version> + </dependency--> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <inherited>true</inherited> + <configuration> + <release>11</release> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.2.1</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + </execution> + </executions> + <configuration> + <mainClass>fr.ulille.iut.pizzaland.Main</mainClass> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>${shade.version}</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>fr.ulille.iut.pizzaland.Main</mainClass> + </transformer> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <properties> + <jersey.version>3.0.0</jersey.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <shade.version>3.2.4</shade.version> + <lombok.version>1.18.16</lombok.version> + <jdbi.version>3.16.0</jdbi.version> + <sqlite-jdbc.version>3.34.0</sqlite-jdbc.version> + <jaxb.version>2.4.0-b180830.0359</jaxb.version> + </properties> </project> diff --git a/src/main/java/fr/ulille/iut/pizzaland/BDDFactory.java b/src/main/java/fr/ulille/iut/pizzaland/BDDFactory.java index 31845d1cd16ab4956c263d903daf752b51cbbd77..b9fc9bb6f8bfc5fee4b0c78e43adfef6afa0cd0a 100644 --- a/src/main/java/fr/ulille/iut/pizzaland/BDDFactory.java +++ b/src/main/java/fr/ulille/iut/pizzaland/BDDFactory.java @@ -10,26 +10,21 @@ import org.jdbi.v3.sqlobject.SqlObjectPlugin; public class BDDFactory { private static Jdbi jdbi = null; - private static String dbPath = "jdbc:sqlite:" - + System.getProperty("java.io.tmpdir") - + System.getProperty("file.separator") - + System.getProperty("user.name") - + "_"; - + private static String dbPath = "jdbc:sqlite:" + System.getProperty("java.io.tmpdir") + + System.getProperty("file.separator") + System.getProperty("user.name") + "_"; + public static Jdbi getJdbi() { - if ( jdbi == null ) { - jdbi = Jdbi.create(dbPath + "pizza.db") - .installPlugin(new SQLitePlugin()) - .installPlugin(new SqlObjectPlugin()); + if (jdbi == null) { + jdbi = Jdbi.create(dbPath + "pizza.db").installPlugin(new SQLitePlugin()) + .installPlugin(new SqlObjectPlugin()); } return jdbi; } public static void setJdbiForTests() { - if ( jdbi == null ) { - jdbi = Jdbi.create(dbPath + "pizza_test.db") - .installPlugin(new SQLitePlugin()) - .installPlugin(new SqlObjectPlugin()); + if (jdbi == null) { + jdbi = Jdbi.create(dbPath + "pizza_test.db").installPlugin(new SQLitePlugin()) + .installPlugin(new SqlObjectPlugin()); } } @@ -43,5 +38,5 @@ public class BDDFactory { public static <T> T buildDao(Class<T> daoClass) { return getJdbi().onDemand(daoClass); - } + } } diff --git a/src/main/java/fr/ulille/iut/pizzaland/Main.java b/src/main/java/fr/ulille/iut/pizzaland/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..1c96a03d45ec5c92140f090aa2692f2918a4b940 --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/Main.java @@ -0,0 +1,71 @@ +package fr.ulille.iut.pizzaland; + +import java.io.IOException; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.logging.LoggingFeature; +import org.glassfish.jersey.server.ResourceConfig; + +/** + * Main class. + * + */ +public class Main { + // Base URI the Grizzly HTTP server will listen on + public static final String BASE_URI = "http://localhost:8080/api/v1/"; + private static final LogManager logManager = LogManager.getLogManager(); + + static { + try { + logManager.readConfiguration(Main.class.getClassLoader().getResourceAsStream("logging.properties")); + } + catch ( Exception ex ) { + ex.printStackTrace(); + } + } + /** + * Starts Grizzly HTTP server exposing JAX-RS resources defined in this + * application. + * + * @return Grizzly HTTP server. + */ + public static HttpServer startServer() { + // create a resource config that scans for JAX-RS resources and providers + // in fr.ulille.iut.todo package + + /* ResourceConfig rc = new ResourceConfig().packages("fr.ulille.iut.pizzaland"); + // Activation des log des requêtes et réponses + String logging = System.getenv("LOG_MESSAGES"); + if ( logging != null && logging.equalsIgnoreCase("true") ) { + rc.register(new LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), Level.INFO, + LoggingFeature.Verbosity.PAYLOAD_ANY, 10000)); + } + String debug = System.getenv("DEBUG_INTERNAL"); + if ( debug != null && debug.equalsIgnoreCase("true") ) { + rc.register(DebugMapper.class); + }*/ + // create and start a new instance of grizzly http server + // exposing the Jersey application at BASE_URI + return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), new ApiV1()); + } + + /** + * Main method. + * + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + final HttpServer server = startServer(); + System.out.println(String.format( + "Jersey app started with WADL available at " + "%sapplication.wadl\nexport LOG_MESSAGES=true pour voir les requêtes et réponses\nexport DEBUG_INTERNAL=true pour voir les erreurs 500\nHit enter to stop it...", + BASE_URI)); + System.in.read(); + server.stop(); + } +} diff --git a/src/main/java/fr/ulille/iut/pizzaland/resources/BDDClearRessource.java b/src/main/java/fr/ulille/iut/pizzaland/resources/BDDClearRessource.java new file mode 100644 index 0000000000000000000000000000000000000000..54b7448ebdeed5518cc8d399e657e3ea49aa2424 --- /dev/null +++ b/src/main/java/fr/ulille/iut/pizzaland/resources/BDDClearRessource.java @@ -0,0 +1,19 @@ +package fr.ulille.iut.pizzaland.resources; + +import java.sql.SQLException; + +import fr.ulille.iut.pizzaland.BDDFactory; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +/** + * BDDClearRessource + */ +@Path("clearDatabase") +public class BDDClearRessource { + + @GET + public void clearDatabase() throws SQLException { + BDDFactory.dropTables(); + } +} diff --git a/src/main/resources/ingredients.json b/src/main/resources/ingredients.json index 2f6d0120787ad372eaa20f10622f421e2727f447..1dcc13bf14994920cf220d2bf4557181867be857 100644 --- a/src/main/resources/ingredients.json +++ b/src/main/resources/ingredients.json @@ -1,14 +1,14 @@ [ - { "name": "mozzarella"}, -{ "name": "jambon"}, -{ "name": "champignons"}, -{ "name": "olives"}, -{ "name": "tomate"}, -{ "name": "merguez"}, -{ "name": "lardons"}, -{ "name": "fromage"}, -{ "name": "oeuf"}, -{ "name": "poivrons"}, -{ "name": "ananas"}, -{ "name": "reblochon"} +{ "id": "f38806a8-7c85-49ef-980c-149dcd81d306", "name": "mozzarella"}, +{ "id": "d36903e1-0cc0-4bd6-a0ed-e0e9bf7b4037", "name": "jambon"}, +{ "id": "bc5b315f-442f-4ee4-96de-486d48f20c2f", "name": "champignons"}, +{ "id": "6a04320c-3a4f-4570-96d3-61faf3f898b0", "name": "olives"}, +{ "id": "c77deeee-d50d-49d5-9695-c98ec811f762", "name": "tomate"}, +{ "id": "c9375542-8142-43f6-b54d-0d63597cf614", "name": "merguez"}, +{ "id": "dee27dd6-f9b6-4d03-ac4b-216b5c9c8bd7", "name": "lardons"}, +{ "id": "657f8dd4-6bc1-4622-9af7-37d248846a23", "name": "fromage"}, +{ "id": "070d8077-a713-49a0-af37-3936b63d5ff2", "name": "oeuf"}, +{ "id": "5d9ca5c4-517f-40fd-aac3-5a823d680c1d", "name": "poivrons"}, +{ "id": "52f68024-24ec-46c0-8e77-c499dba1e27e", "name": "ananas"}, +{ "id": "dfdf6fae-f1b2-45fa-8c39-54e522c1933f", "name": "reblochon"} ] diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml deleted file mode 100644 index ff96a0719e2bcdd46ada8e16d6cd362a13ca787c..0000000000000000000000000000000000000000 --- a/src/main/resources/logback.xml +++ /dev/null @@ -1,12 +0,0 @@ -<configuration scan="true"> - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> - </appender> - - <root level="info"> - <appender-ref ref="STDOUT"/> - </root> - - <logger name="fr.ulille.iut.pizzaland" level="debug"/> - -</configuration> diff --git a/src/main/resources/logging.properties b/src/main/resources/logging.properties new file mode 100644 index 0000000000000000000000000000000000000000..db98114d366d9a6bfef0f729d08b24b09827227a --- /dev/null +++ b/src/main/resources/logging.properties @@ -0,0 +1,4 @@ +handlers= java.util.logging.ConsoleHandler +.level= INFO +java.util.logging.ConsoleHandler.level = INFO +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/.gitkeep b/src/main/webapp/WEB-INF/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000