Upload
aurelien-maury
View
395
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Slides of my talk at the Mix-IT
Citation preview
Grails, from scratch to prod
… plus vite !
MAURY AurélienConsultant XebiaEmail : [email protected]
Twitter : @aurelienmauryLinkedIn : http://fr.linkedin.com/in/aurelienmauryBlog : http://blog.xebia.fr
Qu'est-ce que Grails ?
Qu'est-ce que Grails ? Framework d'application web complet
× MVC, basé sur le langage Groovy
Inspiré de RoR, Django, TurboGears× Adapté à la culture Java
Bâti sur le roc× Stack éprouvée : Spring, Hibernate, Tomcat
Buts Pile application web Java standard
× Fournir un niveau d'abstraction en plus
Réduire la complexité× En outillant l'existant
Augmenter la productivité× En scriptant les tâches répétitives
Approche Convention over configuration
× Principe de "défaut raisonnable"
Don't repeat yourself× Structure imposée pour réduire les duplications
Plateforme complète× Méthodologie et approche fournies
Histoire Janvier 2007
× Sortie de Groovy 1.0
Février 2008× Sortie de Grails 1.0
Novembre 2008× SpringSource rachète G2One
Rock Stars Guillaume Laforge (@glaforge)
× Leader Groovy chez SpringSource
Graeme Rocher (@graemerocher)
× Leader Grails chez SpringSource
Comment ça marche ?
Plateforme complète
Simplifié par Groovy Syntaxe allégée
× Accessible à tous les développeurs Java
Closures, Collections, Gpars, …× L'essayer c'est l'adopter
Scripts de génération de code× Facilement extensible
Développement rapide
warcreate run
Code
Test
Fix
Support IDE Intellij IDEA
Eclipse STS
Netbeans
$ grails create-app bookstore
Structure d'un projetbookstore|_grails-app| |_conf => BootStraping, Datasources, UrlMappings| |_controllers| |_domain| |_i18n => messages.properties internationalisés| |_services| |_taglib| |_utils| |_views => Groovy Server Pages|_lib => Dépendances Java|_scripts|_src| |_groovy| |_java|_test|_web-app => Ressources statiques: images, JS, CSS, etc
Scaffolding Génération de CRUD à partir des entités
× Economie de temps
Popularisé par Ruby on Rails× Orienté schéma base de données
Adopté par Grails× Orienté domaine
Scaffolding grails create-domain-class
grails create-controller
grails create-service
grails generate-all
Scaffolding
Scaffolding grails generate-all org.bookstore.Book
× BookController× BookControllerTest× grails-app/views/book/list.gsp× grails-app/views/book/show.gsp× grails-app/views/book/edit.gsp× grails-app/views/book/create.gsp
Scaffolding dynamiqueclass BookController {
def index = {…}
def list = {…}
def create = {…}
def save = {…}
def show = {…}
def edit = {…}
def update = {…}
def delete = {…}
}
class BookController {
def scaffold = true
}
GORM : Mapping
class Book {
String title
static belongsTo = [author: Author]
static hasMany = [chapters: Chapters]
static constraints = {
title nullable:false
}
}
GORM : RequêtageBook.list(sort: 'title', order: 'asc')
Book.getAll(37, 41, 43)
Book.findByTitleLike("Harry P%")
Book.withCriteria {
eq('title', 'Harry Potter')
author {
like('Rowli%')
}
}
GORM : Requêtage
class Book {
static namedQueries = {
withPotterInTitle {
like 'title', '%Potter%'
}
}
}
Book.withPotterInTitle.list()
Vues Groovy Server Pages
× HTML + Taglib groovy
Assemblage par Sitemesh× Commandé par tags GSP
Taglib Grails (Prototype pour le JS)× Formulaires, AJAX
Vues : exemples<g:formRemote name="myForm"
on404="alert('not found!')"
update="updateMe" // onSuccess="jsFunc"
url="[action:'show']">
Login: <input name="login" type="text"></input>
</g:formRemote>
<div id="updateMe">this div is updated by the form</div>
fieldRemote, remoteFunction
Vues : exemples<g:each var="book" in="${books}">
<p>Title: ${book.title}</p>
<p>Author: ${book.author}</p>
</g:each>
if, else, formatDate, sortableColumn, datePicker, …
Contrôleurs grails create-controller org.bookstore.Book
× Génère un contrôlleur coquille
Injection de dépendance× def leNomDeMonService en attribut de classe
Helpers× render as JSON, render as XML
Contrôleurs : exempleclass AuthorController {
def springSecurityService
def list = {
[ authorInstanceList: Author.list(), authorInstanceTotal: Author.count() ]
}
}
Configuration : dépendancesgrails.project.dependency.resolution = {
repositories {
grailsPlugins()
grailsHome()
grailsCentral()
mavenLocal()
mavenCentral()
mavenRepo "http://snapshots.repository.codehaus.org"
}
dependencies {
runtime 'mysql:mysql-connector-java:5.1.13'
}
}
Configuration : environnements
environments {
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:hsqldb:mem:devDB" } }
test { dataSource { … } }
production { dataSource { … } }
}
Environnements grails run-app => dev
grails test run-app => test
grails test-app => test
grails war => production
Extensible Dépôt de plugins centralisé grails install-plugin …
× spring-security-core× spring-security-ui× quartz× codenarc× mongodb× spock× …
Très extensible× app-engine (GORM en mode JPA)
× groovy-plus-plus× jquery× searchable× gwt× feeds× birt-report× …
ou : grails create-plugin monPlugin
Extensible Plugin Grails == Application Grails
Questions fréquemment posées
Intégration continue ?
Est-ce performant ? Overhead Groovy : x5-7
× Utilisez Groovy++ (x3-5)
Productivité contre vitesse d'exécution× Pas de compile check ? Pas grave.
Optimisations Java× "src/java" ou librairies
Et la courbe d'apprentissage ? Groovy s'apprend vite
× Bases ~ 2 jours, Courant ~ 1 mois
Pièges, GORM Gotchas× Dans l'ensemble, rien ne bloque longtemps
Au delà de la carrosserie× Sur le Tao de Grails, la stack tu maîtriseras
La communauté est-elle active ? 7 versions mineures en 1 an
~ 60 Users Group sur la planète
~ 800 repository GitHub autour de Grails
~ 2500 mails par mois sur les ML
Y a-t-il du support ?
Dans quels cas utiliser Grails ? Minimum Viable Product rapide
× Du prototype au produit en douceur
Reprise d'une application existante× IHM Web rapide, intégration existant en librairie
Tout nouveau projet d'appli web× En toute simplicité
Success stories
Bibliothèque
Linkothèque Groovy home
× http://groovy.codehaus.org/ Grails home
× http://www.grails.org Grails plugins
× http://www.grails.org/plugins/ An army of solipsists (this week in Grails)
× http://burtbeckwith.com/blog/
Questions ?
Merci à touset bon appétit