Skip to content
Snippets Groups Projects
Commit e38abad8 authored by Yvan Peter's avatar Yvan Peter
Browse files

version initiale

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 925 additions and 0 deletions
# Created by https://www.gitignore.io/api/git,java,maven,emacs
### Emacs ###
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
projectile-bookmarks.eld
# directory configuration
.dir-locals.el
# saveplace
places
# url cache
url/cache/
# cedet
ede-projects.el
# smex
smex-items
# company-statistics
company-statistics-cache.el
# anaconda-mode
anaconda-mode/
### Git ###
*.orig
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
!/.mvn/wrapper/maven-wrapper.jar
# End of https://www.gitignore.io/api/git,java,maven,emacs
.classpath
.project
.settings
/.factorypath
default:
image: maven:3.6.3-openjdk-11
stages:
- build
- test
package:
stage: build
script:
- mvn clean package
test-application:
stage: test
script:
- mvn test
# Développement REST - tests et accès à la base de donnée
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
4. L'affichage des logs est maintenant géré par un fichier de configuration externe `logging.properties`
pom.xml 0 → 100644
<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>
<groupId>fr.ulille.iut</groupId>
<artifactId>jersey-todo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>jersey-todo</name>
<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>
<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>
<!-- 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.todo.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.todo.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>
package fr.ulille.iut.todo;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlite3.SQLitePlugin;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import fr.ulille.iut.todo.dao.UUIDArgumentFactory;
/* BDDFactory
* Cette classe permet d'initialiser la connexion JDBI avec la base de
* données et d'associer un DAO avec cette connexion.
* Elle permet d'avoir une base de production et une base de test
*/
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")
+ "_";
public static Jdbi getJdbi() {
if ( jdbi == null ) {
jdbi = Jdbi.create(dbPath + "todo.db")
.installPlugin(new SQLitePlugin())
.installPlugin(new SqlObjectPlugin()).registerArgument(new UUIDArgumentFactory());
}
return jdbi;
}
public static void setJdbiForTests() {
if ( jdbi == null ) {
jdbi = Jdbi.create(dbPath + "todo_test.db")
.installPlugin(new SQLitePlugin())
.installPlugin(new SqlObjectPlugin()).registerArgument(new UUIDArgumentFactory());
}
}
public static boolean tableExist(String tableName) throws SQLException {
DatabaseMetaData dbm = getJdbi().open().getConnection().getMetaData();
ResultSet tables = dbm.getTables(null, null, tableName, null);
boolean exist = tables.next();
tables.close();
return exist;
}
public static void dropTables() throws SQLException {
Handle handle = getJdbi().open();
DatabaseMetaData dbm = handle.getConnection().getMetaData();
ResultSet tables = dbm.getTables(null, null, "", null);
ArrayList<String> tableNames = new ArrayList<String>();
while ( tables.next() ) {
tableNames.add(tables.getString("TABLE_NAME"));
}
tableNames.forEach(name -> handle.execute("drop table " + name));
}
public static <T> T buildDao(Class<T> daoClass) {
return getJdbi().onDemand(daoClass);
}
}
package fr.ulille.iut.todo;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
public class DebugMapper implements ExceptionMapper<Throwable> {
public DebugMapper() {
System.out.println("###### Attention !! DebugMapper est actif !!!");
}
@Override
public Response toResponse(Throwable ex) {
ex.printStackTrace();
return Response.serverError()
.entity(ex.getMessage())
.build();
}
}
package fr.ulille.iut.todo;
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.todo");
// 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), rc);
}
/**
* 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.shutdownNow();
}
}
package fr.ulille.iut.todo.dao;
import java.util.List;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.customizer.BindBean;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import fr.ulille.iut.todo.service.Tache;
/**
* TacheDAO
*/
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();
}
package fr.ulille.iut.todo.dao;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.UUID;
import org.jdbi.v3.core.argument.Argument;
import org.jdbi.v3.core.statement.StatementContext;
public class UUIDArgument implements Argument {
private final UUID value;
public UUIDArgument(UUID value) {
this.value = value;
}
@Override
public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
statement.setString(position, value.toString());
}
}
package fr.ulille.iut.todo.dao;
import java.sql.Types;
import java.util.UUID;
import org.jdbi.v3.core.argument.AbstractArgumentFactory;
import org.jdbi.v3.core.argument.Argument;
import org.jdbi.v3.core.config.ConfigRegistry;
public class UUIDArgumentFactory extends AbstractArgumentFactory<UUID> {
public UUIDArgumentFactory() {
super(Types.VARCHAR);
}
@Override
protected Argument build(UUID value, ConfigRegistry config) {
return (position, statement, ctx) -> statement.setString(position, value.toString());
}
}
package fr.ulille.iut.todo.dto;
public class CreationTacheDTO {
private String nom;
private String description;
public CreationTacheDTO() {}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
package fr.ulille.iut.todo.ressource;
import java.sql.SQLException;
import fr.ulille.iut.todo.BDDFactory;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
/**
* BDDClearRessource
* Cette ressource permet de détruire toutes les tables de la base pour
* repartir à zéro. A enlever pour la mise en production (quand le schéma
* de base de données est stable).
*/
@Path("clearDatabase")
public class BDDClearRessource {
@GET
public void clearDatabase() throws SQLException {
BDDFactory.dropTables();
}
}
package fr.ulille.iut.todo.ressource;
import java.net.URI;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
import fr.ulille.iut.todo.dto.CreationTacheDTO;
import fr.ulille.iut.todo.service.Tache;
import fr.ulille.iut.todo.service.TodoService;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.EntityTag;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Request;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jakarta.ws.rs.core.UriInfo;
@Path("taches")
@Produces(MediaType.APPLICATION_JSON)
public class TodoRessource {
private final static Logger LOGGER = Logger.getLogger(TodoRessource.class.getName());
private TodoService todoService = new TodoService();
@Context
private UriInfo uri;
@Context
Request request;
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Tache> getAll() {
LOGGER.info("getAll()");
return todoService.getAll();
}
@POST
public Response createTache(CreationTacheDTO tacheDto) {
LOGGER.info("createTache()");
Tache tache = Tache.fromCreationTacheDTO(tacheDto);
todoService.addTache(tache);
URI location = uri.getAbsolutePathBuilder().path(tache.getId().toString()).build();
EntityTag etag = new EntityTag(Integer.toString(tache.hashCode()));
ResponseBuilder builder = request.evaluatePreconditions(etag);
if (builder == null) {
builder = Response.created(location);
builder.tag(etag);
builder.entity(tache);
}
return builder.build();
}
}
package fr.ulille.iut.todo.service;
import java.util.UUID;
import fr.ulille.iut.todo.dto.CreationTacheDTO;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Tache {
private UUID id = UUID.randomUUID();
private String nom;
private String description;
public Tache() {}
public static Tache fromCreationTacheDTO(CreationTacheDTO dto) {
Tache tache = new Tache();
tache.setNom(dto.getNom());
tache.setDescription(dto.getDescription());
return tache;
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
@Override
public String toString() {
return "Tache [description=" + description + ", id=" + id + ", nom=" + nom + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((nom == null) ? 0 : nom.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tache other = (Tache) obj;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (nom == null) {
if (other.nom != null)
return false;
} else if (!nom.equals(other.nom))
return false;
return true;
}
}
package fr.ulille.iut.todo.service;
import java.util.List;
import java.util.UUID;
import fr.ulille.iut.todo.BDDFactory;
import fr.ulille.iut.todo.dao.TacheDAO;
public class TodoService {
private TacheDAO taches;
public TodoService() {
taches = BDDFactory.buildDao(TacheDAO.class);
taches.createTable();
}
public Tache getTache(UUID id) {
return null;
}
public List<Tache> getAll() {
return taches.getAll();
}
public void addTache(Tache newTache) {
taches.insert(newTache);
}
public int deleteTache(String id) {
return 0 ;
}
public void updateTache(Tache tache) {
return;
}
}
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
package fr.ulille.iut.todo.ressource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import fr.ulille.iut.todo.BDDFactory;
import fr.ulille.iut.todo.DebugMapper;
import fr.ulille.iut.todo.dao.TacheDAO;
import fr.ulille.iut.todo.dto.CreationTacheDTO;
import fr.ulille.iut.todo.service.Tache;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Form;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
public class TodoRessourceTest extends JerseyTest {
private TacheDAO dao;
@Override
protected Application configure() {
BDDFactory.setJdbiForTests();
ResourceConfig rc = new ResourceConfig(TodoRessource.class);
// Dé-commenter pour avoir la trace des requêtes et réponses
// rc.register(new
// LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME),
// Level.INFO,
// LoggingFeature.Verbosity.PAYLOAD_ANY, 10000));
// Dé-commenter pour avoir une trace des erreurs internes serveur (les tests sur
// le code de retour vont échouer)
// rc.register(DebugMapper.class);
return rc;
}
@Before
public void setEnvUp() {
dao = BDDFactory.buildDao(TacheDAO.class);
dao.createTable();
}
@After
public void tearEnvDown() throws Exception {
dao.dropTable();
}
@Test
public void get_should_return_empty_list_at_startup() {
List<Tache> answer = target("taches").request(MediaType.APPLICATION_JSON).get(new GenericType<List<Tache>>() {
});
assertEquals(new ArrayList<Tache>(), answer);
}
@Test
public void post_should_return_201_location_and_task() {
CreationTacheDTO dto = new CreationTacheDTO();
dto.setNom("test");
dto.setDescription("description test");
Response response = target("taches").request().post(Entity.json(dto));
assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
Tache tache = response.readEntity(Tache.class);
assertEquals(target("taches").getUri().toString() + "/" + tache.getId().toString(),
response.getHeaderString("Location"));
assertEquals(dto.getNom(), tache.getNom());
assertEquals(dto.getDescription(), tache.getDescription());
}
@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);
}
@Test
public void get_for_description_should_work() {
}
@Test
public void delete_should_remove_task() {
}
@Test
public void put_should_replace_existing_task_values() {
}
@Test
public void partial_put_should_fail_with_400() {
}
@Test
public void post_with_form_data_should_return_201_location_and_task() {
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment