Académique Documents
Professionnel Documents
Culture Documents
Gregory Galli
Enseignant et Chef de projet à l’Université Côte d’Azur (UCA)
Sophia Antipolis - France
1
Introduction
Développement Full Stack
2
Introduction
➢ Groovy
➢ Framework Grails
➢ API REST
➢ Sécurité
➢ Projet
3
Introduction
➢ Web
➢ Responsive
➢ Angular
➢ Projet
4
Introduction
➢ Actuellement ?
5
C’est quoi une Stack ?
➢ Stack technique
➢ Outils et technos
➢ Production d’application
➢ Exemples
➢ MEAN Stack
➢ LAMP Stack
6
Layers
➢ Bases de données
➢ Gestion de projet
➢ Planning
➢ Segmentation
➢ Estimation
➢ Backend
➢ API
➢ Frontend
7
Développeur Full Stack
➢ Extrêmement complexe
➢ Développeurs expérimentés
➢ Quantité de technologies
➢ Expérience suffisante
➢ Grande flexibilité
8
Développeur Full Stack
➢ Petits projets
➢ Economie de temps
➢ Gros projets
9
Développeur Full Stack
➢ Attention
➢ Taille de la Stack
➢ Evolution de la définition
10
Développeur Full Stack
➢ Spring Boot
➢ Angular / React
➢ Gestion de projet
➢ Test
➢ Déploiement
11
Développeur Full Stack – Conclusion
➢ Ce qui est vrai aujourd’hui peut ne plus l’être dans un futur proche
12
Développeur Full Stack – Conclusion
13
Module 1:
Développement Backend
Groovy – Grails – Présentation du projet
14
Langage Groovy
Présentation
15
Groovy
➢ Créé en 2003
➢ Inspirations
➢ Surcouche de Java
➢ Etend Java
➢ Librairies Java
16
Groovy
➢ Syntaxe
➢ Fonctionnalités
➢ Closures
➢ Collections
➢ Typage dynamique
➢ Et bien plus …
17
Groovy – Typage dynamique
➢ Avantages
➢ Flexibilité
➢ Codage plus rapide
➢ Type de la variable défini à la volée
➢ Inconvénients
➢ Rigueur
➢ Peut mener à des comportements inattendus
18
Groovy – Assertions
19
Langage Groovy – Closures
Présentation
20
Groovy – Closures
➢ Fonctions anonymes
➢ Peut prendre des arguments
➢ Retourne une valeur
➢ Peut être stocké dans une variable
➢ Pas lié au contexte
➢ Déclaration
➢ Paramètres optionnels
➢ Virgule séparatrice
➢ Flexibilité pour des opérations simples
21
Groovy – Closures – Déclaration
// Equivalents
def closureB = { println it } // Paramètre implicite
def closureC = { it -> println it } // Paramètre nommé, pas de type défini
def closureD = { def it -> println it } // Paramètre nommé, typage dynamique
def closureE = { String it -> println it } // Paramètre nommé, variable typée
22
Groovy – Closures – Appel
// Avec paramètre
def closureWithParam = { it }
23
Groovy – Closures – Examples
// Retourne la surface
def rectSurface = { int w, h -> w * h}
assert rectSurface(2, 3) == 6
24
Groovy Language –
Collections
Overview
25
Groovy – Collections
➢ Types de collection
➢ List
➢ Set
➢ Map
➢ Range
➢ Syntaxe simple
➢ Déclaration
➢ Utilisation
26
Groovy – Collections – List
➢ Ordonné
➢ Index débutant à 0
27
Groovy – Collections – List
// Liste vide
List emptyList = []
// Liste d’entiers
List integerList = [1, 2, 3, 4]
// Liste mixée
List mixedList = ['Mooc', 101, [1, 2], 1.01]
28
Groovy – Collections – List
➢ Manipulation
29
Groovy – Collections – List
➢ Manipulation
// Modification de la List
list.add('Rome')
assert list == ['Paris', 'London', 'Berlin', 'Rome']
assert list.pop() == 'Paris’
assert list == ['London', 'Berlin', 'Rome']
30
Groovy – Collections – Set
➢ Non ordonné
31
Groovy – Collections – Set
➢ Déclaration
// Set vide
Set emptySet = []
32
Groovy – Collections – Map
➢ Tableau associatif
➢ Non ordonné
33
Groovy – Collections – Map
➢ Déclaration
// Map vide
def emptyMap = [:]
// Map classique
Map map = [france: 'Paris', uk: 'London', germany: 'Berlin', italy: 'Rome']
34
Groovy – Collections – Range
// Range classique
def inclusiveRange = 11..15
assert inclusiveRange == [11, 12, 13, 14, 15]
35
Groovy – Collections – Les bases
➢ flatten : Explicite
36
Groovy – Collections – Plus / Minus
37
Groovy – Collections – Each
// Affiche
Paris
London
Berlin
38
Groovy – Collections – Each
// Parcours et affiche
map.each {
println "The capital of $it.key is $it.value"
}
// Equivalent
map.each { key, value ->
println "The capital of $key is $value"
}
// Affiche
The capital of france is Paris
The capital of uk is London
The capital of germany is Berlin
The capital of italy is Rome
39
Groovy – Collections – EachWithIndex
// Avec un index
map.eachWithIndex { key, value, index ->
println "[$index] The capital of $key is $value"
}
// Affiche
"""
[0] The capital of france is Paris
[1] The capital of uk is London
[2] The capital of germany is Berlin
[3] The capital of italy is Rome
"""
40
Groovy – Collections – Collect
// Collection à modifier
def newList = map.collect {
key, value ->
[ key.toUpperCase(), value ]
}
assert newList == [
['FRANCE', 'Paris'],
['UK', 'London'],
['GERMANY', 'Berlin'],
['ITALY', 'Rome']]
41
Groovy – Collections – Collect
def newOtherList = []
map.collect(newOtherList) {
key, value ->
[ key.toUpperCase(), value ]
}
assert newOtherList == [
['FRANCE', 'Paris'],
['UK', 'London'],
['GERMANY', 'Berlin'],
['ITALY', 'Rome']]
42
Groovy – Collections – Find
43
Groovy – Collections – Other
44
Groovy – Syntaxe
45
Groovy on Rails : Grails
Présentation
Grails – Contexte
47
Grails – Concepts & Avantages
➢ Prototypage facile
➢ Plugins
48
Grails – Concepts & Avantages
49
Grails – Concepts & Avantages
➢ GORM
➢ Hibernate (SQL)
➢ MongoDB
➢ Cassandra
50
Grails – Architecture
51
Grails – Used by
52
Grails – Plugins
➢ Par défaut
➢ Serveurs d’application: Tomcat / Glassfish
➢ Bases de données : H2 / Hibernate
➢ Gestion des ressources web : Assets
➢ Utile
➢ Sécurité : Spring Security Core / REST
➢ Services de paiement : Paypal / Stripe / …
➢ Mails
53
Grails
Modélisation
54
Grails – Modélisation
➢ Scalabilité
➢ Mappings
➢ Le DSL de GORM
55
Grails – Modélisation
class BaseTypes {
byte[] grails_byte_array
String grails_string
byte grails_byte
Character grails_character
Integer grails_integer
Double grails_double
Float grails_float
Long grails_long
Date grails_date
Boolean grails_Boolean
}
57
Grails – Modélisation
➢ Relations
➢ One-to-One
➢ One-to-Many
➢ Many-to-Many
class User {
String username
// One-to-One
Address address
58
Grails – Modélisation
➢ Unidirectionnel / Bidirectionnel
59
Grails
Hibernate, GORM & Requêtes
60
Grails – Hibernate
61
Grails – GORM
62
Grails – Hibernate / GORM – Avantages
63
Grails – Hibernate / GORM – Inconvénients
➢ Abstraction
➢ Ne veux pas dire que l’on peut ne pas comprendre ce qu’il se passe
64
Grails – GORM – Requêtes
➢ Dynamic Finders
➢ Where Queries
Request
Performances
complexity
➢ Criteria Queries
65
Conclusion
66
Conclusion
➢ Groovy
➢ Grails
➢ Modélisation
➢ Sécurité
68
Module 2:
Développement Backend
69
Grails – Plan
➢ Modélisation avancée
➢ Héritage
➢ Associations
➢ Contraintes
➢ Mapping
➢ lazy loading
➢ Contrôleurs
➢ Data Handling
➢ Services
➢ GORM & Hibernate Querying
70
Grails – Structure de projet
Structure de projet et plugin « Asset »
71
Grails – Structure de projet
72
Grails – Structure de projet
73
Grails – Plugin Asset
74
Grails – Plugin Asset
75
Grails – Plugin Asset – Sert les ressources
76
Grails – Plugin Asset – Taglibs
<head>
%{-- Javascript / CSS inclusion dans la page--}%
<asset:javascript src="application.js"/>
<asset:stylesheet src="application.css"/>
</head>
<body>
%{-- Référence simple à une resource --}%
<asset:image src="logo.png"/>
</body>
77
Grails – Structure de projet
– Configuration
78
Grails – Configuration
➢ Pas obligatoire
➢ Principalement des surcharges
➢ Configuration de build → build.gradle
➢ Configuration pour l’exécution → grails-app/conf/application.yml
➢ Peut être externalisé
# fichier : grails-app/conf/application.yml
server:
# Changement du port de déploiement
port: 8082
# Changement du context path
contextPath: /myProjetName
79
Grails – Data Sources
80
Grails – URL Mappings
➢Mapping URL
➢ Contrôleurs class UrlMappings {
➢ Actions static mappings = {
➢ Ressources REST "/$controller/$action?/$id?(.$format)?"{
constraints {
// apply Contraintes here
➢ Mapping par défaut }
➢ Pas vraiment une convention }
➢ Modifiable
"/"(view:"/index")
"500"(view:'/error')
"404"(view:'/notFound')
}
}
81
Grails – URL Mappings
"/users"(resources: "user")
82
Grails – URL Mappings
➢ Autres possibilités
➢ Variables prédéfinies
➢ Variables optionnelles
➢ Expressions régulières
83
Grails – URL Mappings
➢ Autres possibilités
➢ Variables prédéfinies
➢ Variables optionnelles
➢ Expressions régulières
84
Grails – Bootstrap
85
Grails – Plugins
86
Grails – Modélisation
87
Grails – Modélisation – Héritage
class Client extends User { class User { class Prospect extends User {
String clientRef String username String prospectRef
} } }
88
Grails – Modélisation – Héritage
89
Grails – Modélisation – Héritage
90
Grails – Modélisation – Héritage
class Client extends User { class User { class Prospect extends User {
String clientRef String username String prospectRef
} }
static mapping = {
tablePerHierarchy false
}
91
Grails – Modélisation – Héritage
92
Grails – Modélisation – Héritage
93
Grails – Associations
94
Grails – Modélisation – Associations
➢ Solutions possibles
➢ Many-to-one
➢ One-to-One
➢ One-to-Many
➢ Many-to-Many
➢ Cas complexes
➢ Plusieurs propriétés d’un même type
➢ Auto-références
➢ Gérer les suppositions « fausses » de GORM
95
Grails – Associations
96
Grails – Associations – Many-to-One
97
Grails – Associations – Many-to-One
98
Grails – Associations – One-to-One
99
Grails – Associations – One-to-One
// User.groovy
class User {
String username
Address address
}
// Address.groovy
class Address {
static belongsTo = [user: User]
}
// Sauvegarde user ET address
def userInstance = new User(username: "username")
userInstance.address = new Address()
userInstance.save()
// Address.groovy
➢ hasOne toujours bidirectionnel class Address {
// Référence simple
// pas de cascade sur delete
➢ Sans « belongsTo » User user
➢ Cascade les sauvegardes et updates
}
➢ Avec « belongsTo »
➢ Cascade delete en plus
101
Grails – Associations – One-to-One
// La classe Address a une reference vers User, impossible de créer sans lien
new Address().save()
102
Grails – Associations
One-to-Many
103
Grails – Associations – One-to-Many
// Message.groovy
class Message {
➢ Nom de la table et des colonnes String content
}
personnalisable avec « mappedBy »
➢ Comportement de cascade
➢ Cascade sauvegardes et mises à jour
➢ Cascade suppression (si belongsTo)
➢ La propriété « message » sera un « Set »
➢ Peut être surchargé
104
Grails – Associations – One-to-Many
106
Grails – Associations – One-to-Many
107
Grails – Associations – One-to-Many
109
Grails – Associations – One-to-Many
class User {
String username
static hasMany = [messages: Message] class Message {
static mapping = { String content
messages cascade: 'all-delete-orphan' }
}
}
110
Grails – Associations – One-to-Many
➢ Sans « belongsTo »
➢ Table d’association
111
Grails – Associations – One-to-Many
➢ Avec « belongsTo »
➢ Pas de table d’association
➢ Le côté « Many » référence le côté « One »
112
Grails – Associations
Many-to-Many
113
Grails – Associations – Many-to-Many
// Author.groovy
// Book.groovy class Author {
class Book { String name
String title
static hasMany = [books: Book]
static hasMany = [authors: Author] // Author est le côté faible
} static belongsTo = Book
}
114
Grails – Associations – Many-to-Many
115
Grails – Associations – Many-to-Many
116
Grails – Associations – Sets & Lists
117
Grails – Modélisation &
Contraintes
118
Grails – Modélisation – Contraintes
119
Grails – Modélisation – Contraintes
120
Grails – Modélisation – Contraintes
121
Grails – Modélisation – Contraintes
class User {
String username
String email
static hasOne = [address:Address]
static hasMany = [messages: Message]
static constraints = {
// le username ne pourra pas être null ou vide et aura entre 5 et 15 chars
username blank: false, nullable: false, size: 5..15
// email non vide, non null et format valide et unique
email blank: false, nullable: false, email: true, unique: true
// address devra être définie pour un User
address nullable: false
}
}
122
Grails – Modélisation
Mapping
123
Grails – Modélisation – Mapping
➢ Personnalisation du mapping
class User {
➢ Personnalisation […]
➢ Nom des tables static hasMany = [messages: Message]
➢ Nom des tables de jointure String description
➢ Nom des champs Date dateCreated
➢ Gestion de la version Date lastUpdated
➢ Lazy / Eager fetching static mapping = {
➢ Stratégie de gestion du cache // Disable autotimestamping
➢ Auto timestamping autoTimestamp false
➢ dateCreated // Force field type to 'text'
➢ lastUpdated description type: 'text'
➢ et bien plus … // Custom join table
messages joinTable: [name : 'user_messages',
key : 'user_id',
column: 'message_id']
} 125
Grails – Modélisation – Mapping
➢ Comportement de Cascade
➢ save-update : cascade les sauvegardes et mises à jour
➢ delete : cascade uniquement les suppressions
➢ all : cascade tout
➢ all-delete-orphan :cascade tout et tente de supprimer les références orphelines
➢ autres cas : http://gorm.grails.org/6.0.x/hibernate/manual/#customCascadeBehaviour
➢ Par défaut
class User {
➢ hasMany cascade save-update
static hasMany = [messages: Message]
➢ belongsTo cascade all-delete-orphan
static mapping = {
// Define cascade behaviour
messages cascade: 'all-delete-orphan'
}
}
126
Grails – Contrôleurs
127
Contrôleurs – Notions de base
➢ Répond à l’appelant
128
Contrôleurs – Scopes (Objets)
129
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ Instance de ServletContext
➢ Aussi appellé « Application scope »
➢ Disponible de manière global sur l’application
➢ Un contexte par application
➢ session
➢ request
➢ params
➢ flash
130
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ session
➢ Instance de HttpSession
➢ Utilisé pour stocker de l’information associée à un utilisateur
➢ Session HTTP
➢ request
➢ params
➢ flash
131
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ session
➢ request
➢ Utilisé pour stocké de l’information sur la requête courante
➢ Instance de HttpServletRequest
➢ Contient toutes les informations de la requête
➢ Cookies
➢ Format
➢ Locales
➢ Informations de sécurité
➢ Request data
➢ Host information
➢ …
➢ params
➢ flash
132
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ session
➢ request
➢ params
➢ Tableau associatif multi dimensionnel
➢ Même portée que la requête
➢ Sorte d’équivalent du scope « request » proposé sous forme de Map (et plus synthétique)
➢ Contient les paramètres des requêtes
➢ Utilisation fréquente pour la récupération des paramètres de requête
➢ Très utilisé pour le « data binding »
➢ flash
133
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ session
➢ request
➢ params
➢ Url appelée
http://myserver.url/test?f_name=first_name&l_name=last_name
➢ Contenu du scope « params »
➢ flash
134
Contrôleurs – Scopes (Objets)
➢ servletContext
➢ session
➢ request
➢ params
➢ flash
➢ Scope temporaire
➢ Information disponible pour la requête courante AINSI QUE la suivante
➢ Vidé après la prochaine requête
➢ Très utile pour certains cas comme par exemple passer des données après un redirect
135
Contrôleurs – Scope (portée)
➢ 3 scopes disponibles
➢ prototype
➢ session
➢ singleton
136
Contrôleurs – Scope (range/reach)
➢ prototype
➢ Une nouvelle instance est créée pour chaque requête
➢ session
➢ Une nouvelle instance est créée pour chaque session utilisateur
➢ singleton
➢ Une instance unique et globale est créée et partagée
➢ Attention : pas de définition de propriété car partagé
137
Contrôleurs – Intercepteurs
➢ Peut être utilisé pour une implémentation très basique d’une sécurité
138
Grails – Contrôleurs –
Gestion de la data
139
Data handling
➢ Data binding
➢ Transition entre le web / les formulaires vers des données dans le monde Groovy
➢ Validation des données
➢ Sécurité
➢ Responses
➢ Comment retourner l’information à un utilisateur
➢ Les formats
➢ Converters
➢ Marshallers
➢ Méthodes à utiliser (respond…)
➢ JSON Builder
140
Data handling – Binding
➢ Requête à un serveur
➢ Formulaires
➢ Invocation HTTP
141
Data handling – Binding
class User {
class Address {
String username
String address
Integer age
User user
static hasOne = [address: Address]
}
}
def map = [username: "username", age: "50", address: [address: "3 Groovy Place"]]
142
Data handling – Binding
class User {
String username class Message {
Integer age String content
static hasOne = [address: Address] static belongsTo = [user: User]
static hasMany = [messages: Message] }
}
def map = [username: "username", age: "50", address: [address: "3 Groovy Place"],
"messages[0]": [content: "Message content"],
"messages[1]": [content: "Other message content"]]
143
Data handling – Binding
// Chargement du User
def userInstance = User.get(1)
// Donnée dans une Map
def map = [ username: "username", age: "50", address: [address: "3 Groovy Place"],
"messages[0]": [content: "Message content"],
"messages[1]": [content: "Other message content"]]
// Liaison des données au modèle de cette manière
userInstance.properties = map
// Sauvegarde l’User
userInstance.save(flush: true)
144
Data handling – Binding
145
Data handling – Response
➢ Méthode « respond »
➢ Méthode « withFormat »
➢ Builders
➢ Marshallers
146
Data handling – Response - Model and views
➢ Plusieurs méthodes
➢ Choisir la vue
➢ Via les conventions
➢ Choix explicite
147
Data handling – Response - Model and views
/views/controllerName/actionName.gsp
148
Data handling – Response - Model and views
// UserController.groovy
def show()
{
// Retourne l'instance de User dans la variable "user"
[user: User.get(params.id)]
}
/views/user/show.gsp
149
Data handling – Response - Model and views
➢ Autres méthodes
➢ return ModelAndView
➢ méthode « render »
// Strict équivalent
return new ModelAndView("/user/show", [user: User.get(params.id)])
// Aussi équivalent
render(view: "/user/show", model: [user: User.get(params.id)])
150
Data handling – Response - Respond
151
Content negotiation
152
Data handling – Response - Respond
➢ Exemple
class User {
String username
Integer age
static hasOne = [address: Address]
static hasMany = [messages: Message]
}
// UserController.groovy
def list()
{
// Gestion de la négociation de contenu
// Retourne la donnée dans le format “le plus approprié”
respond User.list()
}
153
Data handling – Response - Respond
➢ Appel - http://myserver.url/user/list
➢ A partir d’une requête HTTP (avec cURL par exemple) sans plus de précision
donnnera le même résultat
curl http://myserver.url/user/list -I
154
Data handling – Response - Respond
[
{
"id":1,
"address":{"id":1},
"age":25,
"username":"username-5",
"messages":[{"id":1}]
}
]
155
Data handling – Response - Respond
[
{
"id":1,
"address":{"id":1},
"age":25,
"username":"username-5",
"messages":[{"id":1}]
}
]
156
Data handling – Response - WithFormat
157
Data handling – Response – Builder
158
Data handling – Response – Builder
159
Data handling – Response – Marshallers
160
Data handling – Response – Marshallers
161
Grails – Services
Notions de base
162
Services – Notions de base
163
Rappel – Transactions – A.C.I.D.
➢ Dans l'environnement Grails, les exceptions lancées dans une transaction peuvent
déclencher un retour en arrière.
➢ Le retour en arrière peut se produire lorsque l'événement n'est pas explicitement appelé.
164
Rappel – Transactions – A.C.I.D.
➢ C pour Cohérence
➢ L'état de la base de données avant et après la transaction doit respecter l'unicité, les clés
étrangères ou d'autres contraintes.
➢ La cohérence doit être préservée
➢ Quelques exceptions pour l'état " au milieu ".
➢ I pour Isolation
➢ Problématique la plus difficile
➢ Définir comment gérer les lectures / mises à jour / suppressions concurrentes sur une base
de données.
➢ Les données que je vais mettre à jour peuvent avoir changé entre le moment où je les ai lues et le
moment où je vais les mettre à jour.
➢ Ecrire les données sans vérifier si les modifications précédentes ont été annulées.
➢ Revenir sur les changements que j'allais faire annule une action qui aurait dû être exécutée.
➢ Aller au milieu peut entraîner une corruption des données dans la base de données.
165
Rappel – Transactions – A.C.I.D.
/ User score = 13
166
Rappel – Transactions – A.C.I.D.
➢D pour Durabilité
➢ Si un commit est validé par le SGBD, l'intégrité des données doit être maintenue.
➢ Même si
➢ Une erreur se produit
➢ Le serveur est arrêté
➢ Le serveur doit s'assurer que les données ne sont pas perdues
➢ Conclusion
➢ Les transactions sont essentielles à l'intégrité des données
➢ Les transactions peuvent entraîner des « inconvénients » qui doivent être contournés par
de bonnes pratiques de développement.
167
Services – @Transactional
➢ Possibilité de définir un service comme " Transactionnel " avec cette Annotation
@Transactional(readOnly = true)
➢ Rollback déclenché sur le lancement def get() { }
d'une RuntimeException
@NotTransactional
def doThis() { }
}
168
Services – withTransaction
➢ Transaction programmatique
class UserService {
def create(String name, Integer age) {
User.withTransaction {
status ->
new User(name: name, age: age).save()
}
}
}
169
Services – withTransaction
➢ Scopes disponibles
➢ Prototype - nouvelle instance du service pour chaque injection
➢ Request - nouveau service par demande
➢ Session - nouveau service pour chaque session utilisateur
➢ Et bien d’autres…
171
Services – Injection
Queries
173
Grails – GORM – Querying – Basic CRUD
class Exemple {
➢ Créer
String name
Integer rating
➢ Créer une instance d'objet Boolean isValid
}
➢ Appeler la méthode save() pour demander à Hibernate de persister
// Demande la persistance
ExempleInstance.save()
174
Grails – GORM – Querying – Basic CRUD
➢ save : options
➢ validate : détermine si l’étape de validation doit être ignorée
➢ insert : Lorsque définie à « true », force Hibernate à effectuer un INSERT SQL, utile dans
certaines situations (par exemple lors de l'utilisation d'identifiants assignés) et Hibernate
ne peut pas détecter s'il faut effectuer un INSERT ou un UPDATE.
➢ failOnError : si la valeur est "true", une exception sera levée et le serveur d'application
sera arrêté si la validation échoue. Doit être utilisé lors de la définition de données
essentielles.
➢ deepValidate : par défaut "true", si défini à false, ne valide pas les associations.
175
Grails – GORM – Querying – Basic CRUD
➢ Exemple
// On instancie un User
def userInstance =
new User(username: "username",
email: "user@email.com",
description: "description",
address: new Address())
.addToMessages(new Message(content: "message content"))
176
Grails – GORM – Querying – Basic CRUD
➢ Lecture
177
Grails – GORM – Querying – Basic CRUD
➢ Mise à jour
➢ Chargement d’une instance
➢ Modification des propriétés // Mise à jour
➢ Sauvegarde def ExempleInstance = Exemple.get(1)
ExempleInstance.name = "new name"
ExempleInstance.save()
// Supprimer
ExempleInstance.delete()
➢ Supprimer
178
Grails – Dynamic Finders
Chargement de données
179
Grails – GORM – Querying - Dynamic Finders
➢ Dynamic Finders
➢ Méthodes auto-générées à l’exécution
➢ Basé sur les propriétés des classes
➢ Utilisation comme n’importe quelle méthode statique
➢ Idéal pour des requêtes simples
➢ Rapidement difficile à lire / comprendre sur des requêtes longues
➢ Pas optimisé
➢ Where Queries
➢ Criteria Queries
➢ Hibernate Query Language (HQL)
180
Grails – GORM – Querying - Dynamic Finders
➢ Récupération de données
// Chargement via ID, exploite le cache, une requête
def userInstance = User.get(1)
// Strictement identique
// Plus lent
def sameUserInstance = User.findById(1)
// Récupération de liste
def allUsers = User.list()
def alsoAllUsers = User.getAll()
181
Grails – GORM – Querying - Dynamic Finders
➢ Récupération de données
182
Grails – GORM – Querying - Dynamic Finders
➢ Dynamic Finders
class Book { class Author {
String title String name
Author author }
}
183
Grails – GORM – Querying - Dynamic Finders
➢ Opérateurs
➢ InList
➢ Like / Ilike
➢ LessThan / LessThanEquals / GreaterThan / GreaterThanEquals
➢ IsNull / IsNotNull
➢ Between
➢ Rlike
➢ NotEqual
➢ InRange
184
Grails – GORM – Querying - Dynamic Finders
➢ Rapidement incompréhensible
185
Grails – Where Queries
Chargement de données
186
Grails – GORM – Querying – Where Queries
➢ Dynamic Finders
➢ Where Queries
➢ Plus flexible que les Dynamic Finders
➢ Moins verbeux que les Criteria
➢ Utilise les opérations de comparaison classiques
➢ En deux étapes
➢ Construction de la requête
➢ Exécution
➢ Criteria Queries
➢ Hibernate Query Language (HQL)
187
Grails – GORM – Querying – Where Queries
Opérateurs Description
== Egalité stricte
!= Différence
➢ Exemples
class Book { class Author {
String title String name
Author author }
}
// Construction de la requête
def bookQuery = Book.where { title == "title" }
// Exécution de la requête
Book bookInstance = bookQuery.find()
List bookList = bookQuery.findAll()
Méthode Description
➢ Requêtes complexes
191
Grails – GORM – Querying – Where Queries
192
Grails – GORM – Querying – Where Queries
class Comment {
➢ Sous-requêtes Integer rating
➢ Impossible avec les Dynamic finders String comment
// Sélectionne les commentaires avec un rating String author
// supérieur à la moyenne
def commentQuery = Comment.where { static belongsTo = Book
rating > avg(rating) }
}
193
Grails – Criteria
Chargement de données
194
Grails – GORM – Querying – Criteria
➢ Dynamic Finders
➢ Where Queries
➢ Criteria Queries
➢ Plus flexible de que les « Where Queries »
➢ Bien plus verbeux
➢ Construction avec createCriteria() ou withCriteria()
➢ Conditions de niveau 0 liées par un « et » logique
➢ Possibilité de regrouper avec des blocks « and », « or » ou « not »
➢ Dernière possibilité avant de recourir au HQL
195
Grails – GORM – Querying – Criteria
Méthode Description
eq Egalité stricte
ne Différence
gt Supérieur à
lt Inférieur à
ge Supérieur ou égal à
le Inférieur ou égal à
196
Grails – GORM – Querying – Criteria
➢ Exemple
197
Grails – HQL
Querying
198
Grails – GORM – Querying – HQL
➢ Dynamic Finders
➢ Where Queries
➢ Criteria Queries
➢ Hibernate Query Language (HQL)
➢ Option la plus flexible
➢ Moyen le plus direct de s’adresser à l’ORM
➢ Moins d’abstraction, meilleures performances
➢ Construction avec find(), findAll() ou executeQuery()
➢ Mieux qu’utiliser du SQL pour conserver l’abstraction du SGBD
199
Grails – GORM – Querying – HQL
➢ Exemple
200
Grails – GORM - Conclusion
201
Grails – Projet – Création du
Backend
202
Grails – Projet
➢ Backend : Besoin
➢ Configuration
➢ Associations
➢ Contraintes
➢ Scaffolding
➢ Tests
203
Grails – Projet – Besoins
204
Grails – Projet
➢ Backend
➢ User
➢ Annonce de vente
➢ Illustration
➢ Configuration
➢ Port de déploiement
205
Grails – Projet – Modèle
206
Grails – Projet
➢ Classe User
➢ User name
➢ Creation date
➢ Classe Annonce
➢ Title
➢ Description
➢ Price
➢ Status
➢ Creation date
➢ Last update date
➢ Classe Illustration
➢ File name
207
Grails – Projet –
Associations
Création de relations
208
Grails – Projet
➢ Associations
➢ User – Annonce
➢ Un User peut publier plusieurs Annonces
➢ La collection d’Annonces n’a pas besoin d’être ordonnée
➢ Relation forte entre l’Annonce et l’User
➢ L’Annonce doit être supprimée si l’User est supprimé
➢ Annonce – Illustration
➢ Une Annonce peut avoir plusieurs Illustrations
➢ L’ordre peut être important dans ce cas
➢ Relation forte entre Annonce et Illustration
➢ Les Illustrations doivent être effacées si l’Annonce est effacée
209
Grails – Projet – Terminer et
tester
210
Grails – Projet
➢ Contraintes
➢ Scaffolding
➢ Tests
211
Grails – Projet – Bootstrap
212
Grails – Conclusion
213
Grails – Conclusion
214
Module 3:
REST API
Concepts – Développement – Tests – Sécurité
215
Sommaire
216
REST API
Concepts
217
REST
➢ Autour de 2000
➢ Roy Fielding PhD
➢ REpresentational State Transfer
➢ Repose intégralement sur HTTP
➢ On accède à des ressources
➢ Utilisation des verbes HTTP
➢ REST RESTful
218
REST & SOAP
➢REST
➢ Principes architecturaux
➢ SOAP
➢ Spécifications d’un protocole de communication
219
REST & SOAP
➢ Différences majeures
➢ Implémentation
➢ Lisibilité
➢ WSDL
➢ Format du message
➢ Méthodes accessibles
➢ Emplacement
220
REST & SOAP – Comparaison ?
➢ REST ➢ SOAP
➢ Architecture ➢ Protocole
➢ Agnostique vis-à-vis du format ➢ seulement avec XML
➢ Repose intégralement sur HTTP ➢ Pas limité à HTTP
➢ Léger ➢ Fiable, Solide
➢ Lisible ➢ Moins lisible
➢ Gestion du cache (HTTP GET) ➢ HTTP POST, pas de Cache
➢ Une documentation doit être fournie ➢ WSDL
➢ Stateless ➢ Statefull ou Stateless
➢ Pas de surcharge des échanges ➢ Enveloppes SOAP + Headers optionnels
➢ Moins verbeux ➢ Structuré
➢ Pas de fonctionnalités optionnelles ➢ Couches optionnelles pour plus de
fonctionnalités
221
REST & SOAP
➢ SOAP
➢ Besoin de sécurité
➢ Gestion de données de santé
➢ Domaine bancaire
➢ Besoin de fonctionnalités additionnelles
➢ REST
➢ Prototypes
➢ Besoin d’une grande segmentation Client - Serveur
➢ Besoin d’autre chose que du XML
222
REST API
Contraintes
223
REST – Propriétés & Contraintes
➢ Gestion du cache
➢ Clients et Serveurs peuvent mettre des données en cache
➢ Les Réponses doivent être explicitement déclarée comme « pouvant être mis en cache »
➢ Evite que les utilisateurs ne récupèrent des données périmées
➢ Améliore l'extensibilité
224
REST – Propriétés & Contraintes
➢ Stateless
➢ Le maintient de l’état est à la charge seule du Client
➢ Le Serveur ne stocke pas de contexte lié à ses Clients
➢ Accroit la segmentation Client – Serveur
➢ Les requêtes client doivent contenir toutes les informations nécessaires afin que le
Serveur puisse répondre de la manière appropriée
➢ Exception pour le stockage des sessions
➢ Afin que les User n’aient pas à renvoyer systématiquement les informations d’identification
➢ Pas de lien permanent entre le Client et le Serveur
➢ Pas de monopolisation de Serveur par un Client
➢ Pas de saturation Serveur même en cas d’accès concurrents
➢ Meilleure extensibilité
225
REST – Propriétés & Contraintes
➢ Système en couche
➢ Un système peut être segmenté en couches hiérarchiques
➢ Contraint le comportement des composants
➢ Chaque composant n’a de visibilité sur son n+1 ou n-1
Chaque composant est moins complexe
Réduction de la complexité globale
➢ Capacité à gérer des besoins croissants
➢ Load balancers
➢ Serveurs intermédiaires
➢ Doit être transparent du point de vue de l’utilisateur final
➢ Inconvénient : plus de couches : plus de latence
➢ Peut être limité avec l’utilisation de caches partagés
226
REST – Propriétés & Contraintes
227
REST – Propriétés & Contraintes
➢ Interface uniforme
➢ Identification des ressources
➢ Utilisation des URIs pour identifier les ressources
➢ Différencier la représentation d’une ressource de la ressource elle même
➢ Autorise une montée en version indépendante
➢ Manipulation des ressources au travers de leur représentation
➢ Une fois une ressource identifiée, manipulation facile via les différentes méthodes HTTP (GET, POST, PUT &
DELETE)
➢ Message auto-descriptifs
➢ Chaque message doit inclure assez d’information pour être capable de le comprendre et donc de pouvoir le
gérer correctement (formats, cache, timestamps)
➢ Hypermedia as the engine of application state (HATEOAS)
➢ Les réponses peuvent inclure des liens, donnant la possibilité au client de naviguer au travers des différentes
actions possible pour la ressource
➢ Pour et contre ?
➢ Les données sont normalisées, la structure et prédictible
➢ L’évolution des composants est plus simple
➢ L’implémentation côté client peut être plus difficile
➢ Réduit les performances globales
228
REST API
Principe d’implémentation
229
REST – Principe d'implémentation
230
REST – Principe d'implémentation
231
REST – Format handling
Accept: <MIME_type>/<MIME_subtype>
Accept: <MIME_type>/*
Accept: */*
Content-Type : <MIME_type>/<MIME_subtype>
Content-Type : <MIME_type>/*
Content-Type : */*
232
REST API
Méthodes HTTP
233
REST – Méthodes HTTP – GET
234
REST – Méthodes HTTP – POST
235
REST – Méthodes HTTP – PUT
236
REST – Méthodes HTTP – PATCH
237
REST – Méthodes HTTP – DELETE
➢ Return
➢ HTTP 200 (OK)
➢ HTTP 204 (NO CONTENT)
➢ HTTP 404 (NOT FOUND)
➢ HTTP 400 (BAD REQUEST)
238
REST – Méthodes HTTP – OPTIONS
HTTP/1.1 200 OK
Allow: GET,HEAD,POST,OPTIONS
Content-Type: text/html; charset=UTF-8
Date: Wed, 25 Sep 2019 13:17:54 GMT
Content-Length: 0
239
REST – Méthodes HTTP – HEAD
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Wed, 25 Sep 2019 13:17:54 GMT
Content-Length: 15426
Last modified: Tue, 24 Sep 2019 00:00:00 GMT
240
REST API
Exemple d’échange
241
REST – Echange (1)
➢ Définition de ressource
➢ Ressource singleton
➢ Collection de ressource
242
REST – Echange (2)
➢ Résoudre l’action
➢ Génération de la réponse
➢ Définition du format
➢ Retourner la représentation de la ressource ou de la collection de ressources dans le format approprié
➢ Retourne le code HTTP approprié
243
REST – Echange (3)
244
REST – Echange – Conclusion
245
REST – Echange – Conclusion
➢ Tests
➢ Utilisation des outils de développement / débug des navigateurs
➢ Chrome DevTools
➢ Firefox Firebug
➢ cURL
➢ Postman
246
REST API
Codes de réponse HTTP
247
REST – Codes de réponse HTTP
➢ 200 OK
➢ Requête traitée avec succès
➢ Contenu dépend de la méthode HTTP utilisée
➢ 201 CREATED
➢ Requête traitée avec succès
➢ La ressource a été créée
➢ 204 NO CONTENT
➢ Requête traitée avec succès
➢ Pas de donnée retournée
248
REST – Codes de réponse HTTP
➢ 401 UNAUTHORIZED
➢ Le Serveur n’autorisera pas l’accès à la ressource demandée sans authentification
➢ 403 FORBIDDEN
➢ La requête est valide mais l’authentification fournie ne permet pas d’accéder à la
ressource demandée
249
REST – Codes de réponse HTTP
250
REST API – HATEOAS & HAL
Hypermedia As The Engine Of Application State
251
REST – HATEOAS – Concept
252
REST – HATEOAS – Concept
253
REST – HATEOAS – Concept
254
REST – HATEOAS – HAL
➢ Principes
➢ Format simple pour lier les ressources
➢ Rendre l'API navigable
255
REST – HATEOAS – HAL
➢ Objectifs
➢ Consacrer moins de temps à la conception du format
➢ Se concentrer sur l'implémentation et la documentation
➢ Construire des APIs « explorables »
➢ Les associations permettent d'identifier les ressources et les interactions possibles
256
REST – HATEOAS – HAL
➢ Ressources
➢ Contiennent des liens
➢ Définissent d'autres sous-ressources
➢ Définissent un état
➢ Lien
➢ Définit une cible (URI)
➢ Lié à une relation (rel)
➢ Contient des Propriétés optionnelles pour gérer la gestion des versions et des formats.
257
REST – HATEOAS – HAL
258
REST – HATEOAS – HAL – Example
259
REST – HATEOAS – CURIEs
➢ URIs compacts
➢ Raccourci pour les liens
➢ Peut avoir de nombreuses variantes
➢ Utilisation d'un caractère de remplacement ({rel})
➢ Appel de la méthode find sur http://example.com/docs/rels/orders{?id}
260
REST – HATEOAS – HAL – Content Type
➢ REST classique
➢ Spécifique à HAL
261
REST API – Exemple détaillé
Mise en œuvre et test d’une API REST
262
REST – Implémentation
class Book {
class Library {
String title
String name
String author
String address
Date dateCreated
static hasMany = [books: Book]
static belongsTo = [library: Library]
}
}
263
REST – Implémentation
➢ Données d’initialisation
class BootStrap {
def init = { servletContext ->
new Library(name: "Library name", address: "Library address")
.addToBooks(new Book(title: "Library's first book", author: "Unknown"))
.addToBooks(new Book(title: "Library's second book", author: "Unknown"))
.addToBooks(new Book(title: "Library's last book", author: "Unknown"))
.save(flush:true, failOnError: true)
}
}
264
REST – Implémentation – Resources
➢ Ressources disponibles
➢ Library
➢ Bibliothèque
http://my.server.com/library/{id}
➢ Collection de bibliothèques
http://my.server.com/libraries
➢ Book
➢ Livre
http://my.server.com/book/{id}
➢ Collection de livres
http://my.server.com/books
265
REST – Implémentation – Actions disponibles
266
REST – Implémentation – Actions disponibles
➢ http://server/library
➢ Considéré par certains comme faux ou pas assez précis
➢ http://server/libraries
➢ Considéré comme étant la meilleure option la plus part du temps
267
REST – Implémentation – Actions disponibles
➢ Les requêtes GET / PUT / PATCH / DELETE ciblent une simple ressource.
➢ Identifiée par un ID
268
REST – Implémentation – Actions disponibles
GET http://server/book/1
GET http://server/books/
269
REST – Implémentation – Tests
➢ Options importantes
➢ -X Méthode HTTP
➢ -I Affiche le header de la réponse
➢ -H Définition du header de la requête
➢ -d Définition des données à transmettre
➢ -v Verbeux
270
REST API – Grails
Implémentation
Implémentation d’une API REST basique & tests
271
REST – Implémentation – Grails
class Book {
class Library {
String title
String name
String author
String address
Date dateCreated
static hasMany = [books: Book]
static belongsTo = [library: Library]
}
}
272
REST – Implémentation – Grails
// ApiController.groovy
class ApiController {
/**
* Gèrera les requêtes GET / PUT / PATCH / DELETE
*/
def book() {render "ok"}
/**
* Gèrera les requêtes GET / POST
*/
def books() {}
def libraries() {}
def library() {}
}
273
REST – Implémentation – Grails
$ curl http://localhost:8080/api/book -I
HTTP/1.1 200
Content-Type: text/html;charset=utf-8
Transfer-Encoding: chunked
Date: Wed, 02 Oct 2019 17:33:29 GMT
274
def book() {
switch(request.getMethod())
{
REST – Implémentation case "GET":
if (!params.id)
return response.status = 400
def bookInstance = Book.get(params.id)
➢ Implémentation simple if (!bookInstance)
➢ Gérer les erreurs de base return response.status = 404
➢ Gérer les méthodes de requête response.withFormat {
➢ Gérer les formats de base xml { render bookInstance as XML}
json { render bookInstance as JSON }
}
➢ Dans tous les cas break
➢ Retourner un code HTTP explicite case "PUT":
break
case "PATCH":
break
case "DELETE":
break
default:
return response.status = 405
break
}
return response.status = 406
275
}
REST – Implémentation – Grails
➢ Donnée retournée
276
REST – Implémentation – Grails
277
REST – Implémentation – Grails
➢ Gestion du format
➢ Plusieurs possibilités
response.withFormat {
switch(request.getHeader("Accept"))
xml { render bookInstance as XML}
{
json { render bookInstance as JSON }
case 'json':
}
case 'text/json':
case 'application/json':
➢ Logique basique render bookInstance as JSON
break
case 'xml':
case 'text/xml':
case 'application/xml':
render bookInstance as XML
break
}
278
REST – Implémentation – Grails
String title
String author
Date dateCreated
static Contraintes = {
}
}
279
REST – Implémentation – Grails
class UrlMappings {
static mappings = {
"/books"(resources: "book", excludes:['update','create'])
"/books"(resources: "book", includes:['index','show','delete'])
"/books"(resources: "book")
{
"/authors"(resources: "author")
}
}
}
280
REST API – Sécurité
Mécanismes de protection
281
REST – Sécurité
➢ Nombreuses solutions
➢ Authentification
➢ Token
➢ Signature
➢ Demandes signées à usage unique
➢ HTTPS
282
REST – Sécurité – Hash
283
REST – Sécurité – Authentification
➢ Authentification classique
➢ Envoyer le login + le mot de passe (hash) dans la requête
➢ Toujours utiliser un "sel" pour améliorer la sécurité
➢ Problèmes
➢ Peut facilement faire l'objet d'une force brute
➢ Informations d'identification envoyées
➢ Si la requête est interceptée, nous pouvons utiliser l'API avec les identifiants récupérés
284
REST – Sécurité – Token
➢ Problème
➢ Si le « Token » est intercepté, nous pouvons toujours utiliser l'API jusqu'à la fin de la durée
de vie du « Token »
285
REST – Sécurité – Signature
➢ En cas d'interception, il est impossible de recréer une signature valide pour une
nouvelle demande.
➢ Problème
➢ Si la demande est interceptée, elle peut être rejouée.
286
REST – Sécurité – Signature
287
REST – Sécurité – Signature
288
REST – Sécurité – Requête signée à usage
unique
289
REST – Sécurité – HTTPS
➢ Sécurité du canal
➢ Assurance pour le serveur que la requête reçue est identique à celle envoyée.
➢ Assurance que l'expéditeur est bien la personne qui prétend avoir envoyé la
demande.
291
REST API – Projet
Construction d’une API REST basique
292
REST API – Projet
➢ Contrôleur
➢ Tests
➢ Etapes suivantes
293
Module 4 :
Spring Security
294
Authentification
➢ Spring Security
➢ Shiro
295
Spring Security
➢ User
➢ Role
➢ UserRole
➢ Script à lancer
296
Spring Security
➢ s2- quickstart
➢ Exemples
297
Spring Security
➢ Personnaliser
➢ Configurer
➢ Très flexible
298
Spring Security : TagLibs
➢ Security TagLibs
<sec:ifLoggedIn>
<g:link controller="">Special link only accessible when logged in</g:link>
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
<g:link controller="">Special link only accessible when not logged in</g:link>
</sec:ifNotLoggedIn>
299
Spring Security : Service
➢ getCurrentUser()
➢ Retourne l’instance de l’utilisateur identifié
➢ isLoggedIn()
➢ Retourne un booléen indiquant si l’utilisateur courant est identifié
➢ getAuthentication()
➢ Retourne l’utilisateur identifié dans un objet
300
Spring Security : Events
➢ Login validé
➢…
301
Spring Security : Domain
➢ Besoin de changer quelques petites choses dans le Bootstrap pour gérer la nouvelle
structure
➢ Etapes
302
Spring Security : Bootstrap example
➢class BootStrap {
def init = {
def adminRole = new Role(authority: 'ROLE_ADMIN').save()
def userInstance = new User(username: 'username', password: 'password').save()
UserRole.create userInstance, adminRole
UserRole.withSession {
it.flush()
it.clear()
}
assert User.count() == 1
assert Role.count() == 1
assert UserRole.count() == 1
}
}
303
Spring Security
# config/application.groovy
grails.plugin.springsecurity.logout.postOnly = false
➢ Bcrypt : defaut
➢ Sha-256
➢ PBKDF2
304
Spring Security
➢ Annotations
@Secured(value=["hasRole('ROLE_ADMIN')"], httpMethod='POST')
def index(Integer max) {
➢ S’applique aux
➢ Méthodes
➢ Contrôleurs
grails.plugin.springsecurity.securityConfigType = "Annotation"
305
Spring Security
➢ Static Rules
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
[pattern: '/', access: ['permitAll']],
[pattern: '/**/css/**', access: ['permitAll']],
[pattern: '/**/images/**', access: ['permitAll']],
[pattern: '/**/favicon.ico', access: ['permitAll']]
]
➢ Peut cibler un chemin même s’il n’est pas lié à un contrôleur / méthode
306
Spring Security
➢ Plus flexible
➢ RequestMap
307
Spring Security
308
Objectifs
➢ On reprend le projet
https://gitlab.com/mooc-sources/grails-salead
➢ C’est partis
309
Objectifs
➢ Spring Security
➢ Vérification de la configuration
➢ Modification du Bootstrap
➢ Test
310
Objectifs
➢ Définir le JWT
➢ Vérifier l’authentification
➢ Tester l’API
311
Conclusion
Spring Security
312
Ressources
➢ JWT à utiliser
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJtb29jX3NwcmluZ19zZWN1cml
0eSIsImlhdCI6MTU5NjIwNjcxMywiZXhwIjoxNjI3NzQyNzEzLCJhdWQiOiJtb29jX3N0d
WRlbnRzIiwic3ViIjoibW9vY19zcHJpbmdfc2VjdXJpdHkiLCJHaXZlbk5hbWUiOiJNb29jI
n0.gx1iCqhrx1gikFigcUTqlBBdGZPbXs6bZYxDp5V93fs
313
Documentations
➢ Groovy
http://docs.groovy-lang.org/next/html/documentation/
➢ Grails Core
https://docs.grails.org/latest/guide/single.html
➢ GORM for Hibernate
http://gorm.grails.org/latest/hibernate/manual/
➢ Spring SecurityCore
https://grails-plugins.github.io/grails-spring-Sécurité-core/latest/
➢ Hibernate
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_Us
er_Guide.html
➢ Asset Pipeline
http://www.asset-pipeline.com/manual/index.html
314
Références – Liens
315
Références – Illustrations
316
Références – Illustrations
317