SlideShare une entreprise Scribd logo
1  sur  76
Groovy: Efficiency Oriented Programming
Lecture 11
Master Proteomics & Bioinformatics - University of Geneva
Alexandre Masselot - summer 2011
Agenda

‣ CRUD
‣ Integration tests
‣ Domain relationships
‣ Application configuration
One domain based app ↔ one database
One domain class ↔ one table
One domain bean ↔ one table entry
One bean operations: CRUD
One bean operations: CRUD


         Action

        Create

         Read

        Update

         Delete
One bean operations: CRUD


         Action

        Create

         Read

        Update

         Delete
One bean operations: CRUD


         Action

        Create

         Read

        Update

         Delete
One bean operations: CRUD


         Action

        Create

         Read

        Update

         Delete
One bean operations: CRUD


         Action       SQL    Grails url

        Create      INSERT   create

         Read       SELECT    show

        Update      UPDATE   update

         Delete     DELETE   delete
One bean operations: CRUD


         Action       SQL    Grails url

        Create      INSERT   create

         Read       SELECT    show

        Update      UPDATE   update

         Delete     DELETE   delete
One bean operations: CRUD


         Action       SQL    Grails url

        Create      INSERT   create

         Read       SELECT    show

        Update      UPDATE   update

         Delete     DELETE   delete
Person joe = new Person(params)
   ➙ bean but no database entry creation
joe.save()
     ➙ insertion into table
(only if valid bean - constraints)
Validation

‣ Create only a valid bean
‣ 3 validation ways
Validation

‣ Create only a valid bean
‣ 3 validation ways
‣ Check explicitly for validation
 joe.validate()
Validation

‣ Create only a valid bean
‣ 3 validation ways
‣ Check explicitly for validation
 joe.validate()

‣ Save a catch exception
 joe.save(failOnError:true)
Validation

‣ Create only a valid bean
‣ 3 validation ways
‣ Check explicitly for validation
 joe.validate()

‣ Save a catch exception
 joe.save(failOnError:true)

‣ Save a check for non-null return
 assert joe.save()
Registered bean ⇔ joe.id != null
Reading a bean from the database
joe = Person.get(beanId)
Dynamic finders: retrieve from constraints
Dynamic finders (for single return)

‣ Domain class definition generate static methods
 def p = Person.findByUsername(‘lucky_luke’)
 def p = Person.findByFirstName(‘Lucky’)
 def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’)
Dynamic finders (for single return)

‣ Domain class definition generate static methods
 def p = Person.findByUsername(‘lucky_luke’)
 def p = Person.findByFirstName(‘Lucky’)
 def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’)

‣ Multiple results => returns first (sorted on id)
 def p = Person.findByLastName(‘Dalton’)
Dynamic finders (for single return)

‣ Domain class definition generate static methods
 def p = Person.findByUsername(‘lucky_luke’)
 def p = Person.findByFirstName(‘Lucky’)
 def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’)

‣ Multiple results => returns first (sorted on id)
 def p = Person.findByLastName(‘Dalton’)

‣ findByXxxx efficient with unique:true fields
Update



  ‣ Update: change fields values and save into database
Update



  ‣ Update: change fields values and save into database
  1. modify bean as usual
Update



  ‣ Update: change fields values and save into database
  1. modify bean as usual
  2. validate/save as for creation
joe.delete() removes entry from table
Scaffolded controller hides CRUD operations
Explicit controller

‣ It is possible to generate scaffold controller code
 generate-controller eop.lec11.twitter.Person
Explicit controller

‣ It is possible to generate scaffold controller code
 generate-controller eop.lec11.twitter.Person

‣ PersonController.groovy write operation & test
Explicit controller

‣ It is possible to generate scaffold controller code
 generate-controller eop.lec11.twitter.Person

‣ PersonController.groovy write operation & test
‣ For example, read:
     def show = {
         def personInstance = Person.get(params.id)
         if (!personInstance) {
             flash.message = "${message(code:
 'default.not.found.message', .....)}"
             redirect(action: "list")
         }
         else {
             [personInstance: personInstance]
         }
     }
Time to go back to test!
Unit testing ↔ no dependency
Integration testing ↔ more complex biotope
Integration tests

‣ Resides under test/integration/
PersonIntegrationTests.groovy
Integration tests

‣ Resides under test/integration/
PersonIntegrationTests.groovy

‣ Launched with
test-app -integration
Integration tests

‣ Resides under test/integration/
 PersonIntegrationTests.groovy

‣ Launched with
 test-app -integration

‣ Results:
  - summary on the console output (count success/failures)
  - html files under target/tests-reports/html

  - plain text files under target/tests-reports/html
  - failure summary available
  - stdout/stderr accessible for each test case
Faster grails command

‣ Launch command (<alt><ctrl>G) interactive
Faster grails command

‣ Launch command (<alt><ctrl>G) interactive
‣ On the console, enter command
test-app -integration
Faster grails command

‣ Launch command (<alt><ctrl>G) interactive
‣ On the console, enter command
 test-app -integration

‣ Hit enter to relaunch last command
Faster grails command

‣ Launch command (<alt><ctrl>G) interactive
‣ On the console, enter command
 test-app -integration

‣ Hit enter to relaunch last command
‣ After several commands, PermGenException can occur
  - terminate
  - relaunch interactive
Grails integration testing cons




         ‣ Slower to execute than unit
Grails integration testing cons




         ‣ Slower to execute than unit
         ‣ Test report is not integrated into eclipse
Grails integration testing cons




         ‣ Slower to execute than unit
         ‣ Test report is not integrated into eclipse
         ‣ Use only when unit test not possible
mockDomain: unit testing with domain class
mockDomain

‣ It is possible to make some unit testing with domain
mockDomain

‣ It is possible to make some unit testing with domain
‣ No real database is connected, but a fake layer
mockDomain

‣ It is possible to make some unit testing with domain
‣ No real database is connected, but a fake layer
‣ In each method (not setup())
 mockDomain(Person)
 mockDomain(Person, initialBeanList)
mockDomain

‣ It is possible to make some unit testing with domain
‣ No real database is connected, but a fake layer
‣ In each method (not setup())
 mockDomain(Person)
 mockDomain(Person, initialBeanList)

‣ All single domain CRUD (and more) operations possible
mockDomain example


 void testDelete(){
     //buildDaltonFamily() return a list of 4 Person

 
 mockDomain(Person, buildDaltonFamily())


 
     assert Person.count() == 4

 
     Person p=Person.findByUsername('joe_dalton')

 
     assertNotNull p


 
     p.delete()


   
   // we should only have 3 members left

   
   assert Person.count() == 3

   
   p=Person.findByUsername('joe_dalton')

   
   assertNull p

   }
mockDomain limits



‣ No explicit database operation (hibernate criteria, HQL) are
  possible
mockDomain limits



‣ No explicit database operation (hibernate criteria, HQL) are
  possible
‣ Multiple domain class interaction are fully possible (cf.
  relationships)
mockDomain limits



‣ No explicit database operation (hibernate criteria, HQL) are
  possible
‣ Multiple domain class interaction are fully possible (cf.
  relationships)
‣ Connection with data already entered in a database
Hermit domain not very useful
Need for relationships
Twitter: Person ↔ Message
Message domain

create-domain-class Domain
Message domain

create-domain-class Domain

‣ Just a text (String) and a commiter (Person)
class Message {
    String text
    Person commiter

    static constraints = {
        text(size:1..140, blank:false)
        commiter(nullable:false)
    }
}
Message + Person

‣ Attach two messages to a user
 Person joe=Person.findByUsername('joe_dalton')
 new Message(text:'hello', commiter:joe).save()
 new Message(text:'world', commiter:joe).save()
Message + Person

‣ Attach two messages to a user
 Person joe=Person.findByUsername('joe_dalton')
 new Message(text:'hello', commiter:joe).save()
 new Message(text:'world', commiter:joe).save()

‣ Look for message from joe
 Message.findAllByCommiter(joe)
Message + Person

‣ Attach two messages to a user
 Person joe=Person.findByUsername('joe_dalton')
 new Message(text:'hello', commiter:joe).save()
 new Message(text:'world', commiter:joe).save()

‣ Look for message from joe
 Message.findAllByCommiter(joe)

‣ Not possible to access to message directly from joe bean
  - one solution: explicitly declare setCommiter(Person p) in
    Message.groovy that would add the message to a list in joe;
  - problem for deletion, save inconsistency...
Define a one-to-many relationship
One-to-many relationship



‣Message.groovy
//Person commiter
static belongsTo = [commiter:Person]
One-to-many relationship



‣Message.groovy
//Person commiter
static belongsTo = [commiter:Person]




‣Person.groovy
static hasMany = [messages: Message]
One-to-many relationship                        (cont’d)



‣ Add a message:
joe.addToMessages(new Message(text:‘hello world’)).save()
One-to-many relationship                         (cont’d)



‣ Add a message:
 joe.addToMessages(new Message(text:‘hello world’)).save()

‣ Will execute the following actions
  - create a message with joe as commiter
  - save the message
  - add the message to joe’s list
One-to-many relationship   (cont’d)

‣ Access to the list
 joe.messages
One-to-many relationship                                     (cont’d)

‣ Access to the list
 joe.messages

‣ Deleting will cascade
 joe.delete()
  - all messages with joe as commiter will also be deleted
Testing

‣ Test database consistency with two domain: integration testing
     // taken from MessageIntegrationTests.groovy
     // 4 Person are added in the setup() method
 
   public void testListMessagesUserDeletion(){
 
   
 Person joe=Person.findByUsername('joe_dalton')
 
   
 Person averell=Person.findByUsername('averell_dalton')
 
   
 
   
 joe.addToMessages(new Message(text:'hello world')).save()
 
   
 joe.addToMessages(new Message(text:'i'm running')).save()
 
   
 averell.addToMessages(new Message(text:'i'm eating')).save()
 
   
 
   
 assert Message.count() == 3
 
   
 assert Person.count() == 4
 
   
 
   
 joe.delete()
 
   
 assert Person.count() == 3

 
 
    //having deleted joe should delete all message related to joe
 
 
    assert Message.count() == 1
 
 }
Back to the web: 2 scaffolded controllers
groovy & grails - lecture 11
groovy & grails - lecture 11
groovy & grails - lecture 11

Contenu connexe

Tendances

Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Kenji Tanaka
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemKostas Saidis
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.Workhorse Computing
 
GoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDGoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDBartłomiej Kiełbasa
 
Practical git for developers
Practical git for developersPractical git for developers
Practical git for developersWim Godden
 
Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Workhorse Computing
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about GradleEvgeny Goldin
 
Challenges of container configuration
Challenges of container configurationChallenges of container configuration
Challenges of container configurationlutter
 
BASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic InterpolationBASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic InterpolationWorkhorse Computing
 
Pragmatic Browser Automation with Geb - GIDS 2015
Pragmatic Browser Automation with Geb - GIDS 2015Pragmatic Browser Automation with Geb - GIDS 2015
Pragmatic Browser Automation with Geb - GIDS 2015Naresha K
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Workhorse Computing
 
Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Devon Bernard
 
The Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockNaresha K
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestMyles Braithwaite
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with JasmineLeon van der Grient
 

Tendances (20)

Short Introduction To "perl -d"
Short Introduction To "perl -d"Short Introduction To "perl -d"
Short Introduction To "perl -d"
 
Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -Stubる - Mockingjayを使ったHTTPクライアントのテスト -
Stubる - Mockingjayを使ったHTTPクライアントのテスト -
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystem
 
Smoking docker
Smoking dockerSmoking docker
Smoking docker
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
GoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDDGoCracow #5 Bartlomiej klimczak - GoBDD
GoCracow #5 Bartlomiej klimczak - GoBDD
 
Practical git for developers
Practical git for developersPractical git for developers
Practical git for developers
 
Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.Keeping objects healthy with Object::Exercise.
Keeping objects healthy with Object::Exercise.
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about Gradle
 
Challenges of container configuration
Challenges of container configurationChallenges of container configuration
Challenges of container configuration
 
BASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic InterpolationBASH Variables Part 1: Basic Interpolation
BASH Variables Part 1: Basic Interpolation
 
Pragmatic Browser Automation with Geb - GIDS 2015
Pragmatic Browser Automation with Geb - GIDS 2015Pragmatic Browser Automation with Geb - GIDS 2015
Pragmatic Browser Automation with Geb - GIDS 2015
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
Memory Manglement in Raku
Memory Manglement in RakuMemory Manglement in Raku
Memory Manglement in Raku
 
Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]
 
The Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with Spock
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
 

Similaire à groovy & grails - lecture 11

GR8Conf 2011: GORM Optimization
GR8Conf 2011: GORM OptimizationGR8Conf 2011: GORM Optimization
GR8Conf 2011: GORM OptimizationGR8Conf
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Spring 4 final xtr_presentation
Spring 4 final xtr_presentationSpring 4 final xtr_presentation
Spring 4 final xtr_presentationsourabh aggarwal
 
Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingTricode (part of Dept)
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suckRoss Bruniges
 
Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.Julian Dunn
 
Sprout core and performance
Sprout core and performanceSprout core and performance
Sprout core and performanceYehuda Katz
 
Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Chris Richardson
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTim Berglund
 
Test First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTest First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTim Berglund
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e bigAndy Peterson
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third PluginJustin Ryan
 

Similaire à groovy & grails - lecture 11 (20)

GR8Conf 2011: GORM Optimization
GR8Conf 2011: GORM OptimizationGR8Conf 2011: GORM Optimization
GR8Conf 2011: GORM Optimization
 
Gorm
GormGorm
Gorm
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Spring 4 final xtr_presentation
Spring 4 final xtr_presentationSpring 4 final xtr_presentation
Spring 4 final xtr_presentation
 
Groovy Basics
Groovy BasicsGroovy Basics
Groovy Basics
 
Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching logging
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.
 
Sprout core and performance
Sprout core and performanceSprout core and performance
Sprout core and performance
 
Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)
 
What's New in Groovy 1.6?
What's New in Groovy 1.6?What's New in Groovy 1.6?
What's New in Groovy 1.6?
 
Griffon @ Svwjug
Griffon @ SvwjugGriffon @ Svwjug
Griffon @ Svwjug
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Test First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in GrailsTest First Refresh Second: Test-Driven Development in Grails
Test First Refresh Second: Test-Driven Development in Grails
 
Test First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in GrailsTest First, Refresh Second: Web App TDD in Grails
Test First, Refresh Second: Web App TDD in Grails
 
Gorm
GormGorm
Gorm
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third Plugin
 

Plus de Alexandre Masselot

Offshoring software development in Switzerland: You can do it
Offshoring software development in Switzerland: You can do itOffshoring software development in Switzerland: You can do it
Offshoring software development in Switzerland: You can do itAlexandre Masselot
 
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data Stack
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data StackDev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data Stack
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data StackAlexandre Masselot
 
Swiss Transport in Real Time: Tribulations in the Big Data Stack
Swiss Transport in Real Time: Tribulations in the Big Data StackSwiss Transport in Real Time: Tribulations in the Big Data Stack
Swiss Transport in Real Time: Tribulations in the Big Data StackAlexandre Masselot
 

Plus de Alexandre Masselot (10)

Offshoring software development in Switzerland: You can do it
Offshoring software development in Switzerland: You can do itOffshoring software development in Switzerland: You can do it
Offshoring software development in Switzerland: You can do it
 
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data Stack
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data StackDev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data Stack
Dev Wednesday - Swiss Transport in Real Time: Tribulations in the Big Data Stack
 
Swiss Transport in Real Time: Tribulations in the Big Data Stack
Swiss Transport in Real Time: Tribulations in the Big Data StackSwiss Transport in Real Time: Tribulations in the Big Data Stack
Swiss Transport in Real Time: Tribulations in the Big Data Stack
 
groovy & grails - lecture 8
groovy & grails - lecture 8groovy & grails - lecture 8
groovy & grails - lecture 8
 
groovy & grails - lecture 10
groovy & grails - lecture 10groovy & grails - lecture 10
groovy & grails - lecture 10
 
groovy & grails - lecture 1
groovy & grails - lecture 1groovy & grails - lecture 1
groovy & grails - lecture 1
 
groovy & grails - lecture 9
groovy & grails - lecture 9groovy & grails - lecture 9
groovy & grails - lecture 9
 
groovy & grails - lecture 7
groovy & grails - lecture 7groovy & grails - lecture 7
groovy & grails - lecture 7
 
groovy & grails - lecture 6
groovy & grails - lecture 6groovy & grails - lecture 6
groovy & grails - lecture 6
 
groovy & grails - lecture 3
groovy & grails - lecture 3groovy & grails - lecture 3
groovy & grails - lecture 3
 

Dernier

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 

Dernier (20)

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 

groovy & grails - lecture 11

  • 1. Groovy: Efficiency Oriented Programming Lecture 11 Master Proteomics & Bioinformatics - University of Geneva Alexandre Masselot - summer 2011
  • 2. Agenda ‣ CRUD ‣ Integration tests ‣ Domain relationships ‣ Application configuration
  • 3.
  • 4. One domain based app ↔ one database
  • 5. One domain class ↔ one table
  • 6. One domain bean ↔ one table entry
  • 8. One bean operations: CRUD Action Create Read Update Delete
  • 9. One bean operations: CRUD Action Create Read Update Delete
  • 10. One bean operations: CRUD Action Create Read Update Delete
  • 11. One bean operations: CRUD Action Create Read Update Delete
  • 12. One bean operations: CRUD Action SQL Grails url Create INSERT create Read SELECT show Update UPDATE update Delete DELETE delete
  • 13. One bean operations: CRUD Action SQL Grails url Create INSERT create Read SELECT show Update UPDATE update Delete DELETE delete
  • 14. One bean operations: CRUD Action SQL Grails url Create INSERT create Read SELECT show Update UPDATE update Delete DELETE delete
  • 15. Person joe = new Person(params) ➙ bean but no database entry creation
  • 16. joe.save() ➙ insertion into table (only if valid bean - constraints)
  • 17. Validation ‣ Create only a valid bean ‣ 3 validation ways
  • 18. Validation ‣ Create only a valid bean ‣ 3 validation ways ‣ Check explicitly for validation joe.validate()
  • 19. Validation ‣ Create only a valid bean ‣ 3 validation ways ‣ Check explicitly for validation joe.validate() ‣ Save a catch exception joe.save(failOnError:true)
  • 20. Validation ‣ Create only a valid bean ‣ 3 validation ways ‣ Check explicitly for validation joe.validate() ‣ Save a catch exception joe.save(failOnError:true) ‣ Save a check for non-null return assert joe.save()
  • 21. Registered bean ⇔ joe.id != null
  • 22. Reading a bean from the database
  • 24. Dynamic finders: retrieve from constraints
  • 25. Dynamic finders (for single return) ‣ Domain class definition generate static methods def p = Person.findByUsername(‘lucky_luke’) def p = Person.findByFirstName(‘Lucky’) def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’)
  • 26. Dynamic finders (for single return) ‣ Domain class definition generate static methods def p = Person.findByUsername(‘lucky_luke’) def p = Person.findByFirstName(‘Lucky’) def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’) ‣ Multiple results => returns first (sorted on id) def p = Person.findByLastName(‘Dalton’)
  • 27. Dynamic finders (for single return) ‣ Domain class definition generate static methods def p = Person.findByUsername(‘lucky_luke’) def p = Person.findByFirstName(‘Lucky’) def p = Person.findByFirstNameAndLastName(‘Joe’, ‘Dalton’) ‣ Multiple results => returns first (sorted on id) def p = Person.findByLastName(‘Dalton’) ‣ findByXxxx efficient with unique:true fields
  • 28. Update ‣ Update: change fields values and save into database
  • 29. Update ‣ Update: change fields values and save into database 1. modify bean as usual
  • 30. Update ‣ Update: change fields values and save into database 1. modify bean as usual 2. validate/save as for creation
  • 32. Scaffolded controller hides CRUD operations
  • 33. Explicit controller ‣ It is possible to generate scaffold controller code generate-controller eop.lec11.twitter.Person
  • 34. Explicit controller ‣ It is possible to generate scaffold controller code generate-controller eop.lec11.twitter.Person ‣ PersonController.groovy write operation & test
  • 35. Explicit controller ‣ It is possible to generate scaffold controller code generate-controller eop.lec11.twitter.Person ‣ PersonController.groovy write operation & test ‣ For example, read: def show = { def personInstance = Person.get(params.id) if (!personInstance) { flash.message = "${message(code: 'default.not.found.message', .....)}" redirect(action: "list") } else { [personInstance: personInstance] } }
  • 36. Time to go back to test!
  • 37. Unit testing ↔ no dependency
  • 38. Integration testing ↔ more complex biotope
  • 39. Integration tests ‣ Resides under test/integration/ PersonIntegrationTests.groovy
  • 40. Integration tests ‣ Resides under test/integration/ PersonIntegrationTests.groovy ‣ Launched with test-app -integration
  • 41. Integration tests ‣ Resides under test/integration/ PersonIntegrationTests.groovy ‣ Launched with test-app -integration ‣ Results: - summary on the console output (count success/failures) - html files under target/tests-reports/html - plain text files under target/tests-reports/html - failure summary available - stdout/stderr accessible for each test case
  • 42. Faster grails command ‣ Launch command (<alt><ctrl>G) interactive
  • 43. Faster grails command ‣ Launch command (<alt><ctrl>G) interactive ‣ On the console, enter command test-app -integration
  • 44. Faster grails command ‣ Launch command (<alt><ctrl>G) interactive ‣ On the console, enter command test-app -integration ‣ Hit enter to relaunch last command
  • 45. Faster grails command ‣ Launch command (<alt><ctrl>G) interactive ‣ On the console, enter command test-app -integration ‣ Hit enter to relaunch last command ‣ After several commands, PermGenException can occur - terminate - relaunch interactive
  • 46. Grails integration testing cons ‣ Slower to execute than unit
  • 47. Grails integration testing cons ‣ Slower to execute than unit ‣ Test report is not integrated into eclipse
  • 48. Grails integration testing cons ‣ Slower to execute than unit ‣ Test report is not integrated into eclipse ‣ Use only when unit test not possible
  • 49. mockDomain: unit testing with domain class
  • 50. mockDomain ‣ It is possible to make some unit testing with domain
  • 51. mockDomain ‣ It is possible to make some unit testing with domain ‣ No real database is connected, but a fake layer
  • 52. mockDomain ‣ It is possible to make some unit testing with domain ‣ No real database is connected, but a fake layer ‣ In each method (not setup()) mockDomain(Person) mockDomain(Person, initialBeanList)
  • 53. mockDomain ‣ It is possible to make some unit testing with domain ‣ No real database is connected, but a fake layer ‣ In each method (not setup()) mockDomain(Person) mockDomain(Person, initialBeanList) ‣ All single domain CRUD (and more) operations possible
  • 54. mockDomain example void testDelete(){ //buildDaltonFamily() return a list of 4 Person mockDomain(Person, buildDaltonFamily()) assert Person.count() == 4 Person p=Person.findByUsername('joe_dalton') assertNotNull p p.delete() // we should only have 3 members left assert Person.count() == 3 p=Person.findByUsername('joe_dalton') assertNull p }
  • 55. mockDomain limits ‣ No explicit database operation (hibernate criteria, HQL) are possible
  • 56. mockDomain limits ‣ No explicit database operation (hibernate criteria, HQL) are possible ‣ Multiple domain class interaction are fully possible (cf. relationships)
  • 57. mockDomain limits ‣ No explicit database operation (hibernate criteria, HQL) are possible ‣ Multiple domain class interaction are fully possible (cf. relationships) ‣ Connection with data already entered in a database
  • 58. Hermit domain not very useful
  • 59. Need for relationships Twitter: Person ↔ Message
  • 61. Message domain create-domain-class Domain ‣ Just a text (String) and a commiter (Person) class Message { String text Person commiter static constraints = { text(size:1..140, blank:false) commiter(nullable:false) } }
  • 62. Message + Person ‣ Attach two messages to a user Person joe=Person.findByUsername('joe_dalton') new Message(text:'hello', commiter:joe).save() new Message(text:'world', commiter:joe).save()
  • 63. Message + Person ‣ Attach two messages to a user Person joe=Person.findByUsername('joe_dalton') new Message(text:'hello', commiter:joe).save() new Message(text:'world', commiter:joe).save() ‣ Look for message from joe Message.findAllByCommiter(joe)
  • 64. Message + Person ‣ Attach two messages to a user Person joe=Person.findByUsername('joe_dalton') new Message(text:'hello', commiter:joe).save() new Message(text:'world', commiter:joe).save() ‣ Look for message from joe Message.findAllByCommiter(joe) ‣ Not possible to access to message directly from joe bean - one solution: explicitly declare setCommiter(Person p) in Message.groovy that would add the message to a list in joe; - problem for deletion, save inconsistency...
  • 65. Define a one-to-many relationship
  • 67. One-to-many relationship ‣Message.groovy //Person commiter static belongsTo = [commiter:Person] ‣Person.groovy static hasMany = [messages: Message]
  • 68. One-to-many relationship (cont’d) ‣ Add a message: joe.addToMessages(new Message(text:‘hello world’)).save()
  • 69. One-to-many relationship (cont’d) ‣ Add a message: joe.addToMessages(new Message(text:‘hello world’)).save() ‣ Will execute the following actions - create a message with joe as commiter - save the message - add the message to joe’s list
  • 70. One-to-many relationship (cont’d) ‣ Access to the list joe.messages
  • 71. One-to-many relationship (cont’d) ‣ Access to the list joe.messages ‣ Deleting will cascade joe.delete() - all messages with joe as commiter will also be deleted
  • 72. Testing ‣ Test database consistency with two domain: integration testing // taken from MessageIntegrationTests.groovy // 4 Person are added in the setup() method public void testListMessagesUserDeletion(){ Person joe=Person.findByUsername('joe_dalton') Person averell=Person.findByUsername('averell_dalton') joe.addToMessages(new Message(text:'hello world')).save() joe.addToMessages(new Message(text:'i'm running')).save() averell.addToMessages(new Message(text:'i'm eating')).save() assert Message.count() == 3 assert Person.count() == 4 joe.delete() assert Person.count() == 3 //having deleted joe should delete all message related to joe assert Message.count() == 1 }
  • 73. Back to the web: 2 scaffolded controllers

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. run-app generate the database\n
  5. Domain bean class generate a table from the member fields\n
  6. map one object &lt;-&gt; SQL statements\n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. id property is added by default to domain beans\nsetting the bean joe.id=123 is dangerous\n
  24. \n
  25. necessitate to know the beanId value\ntypically used with url show/id\n
  26. \n
  27. possible to configure sort on other condition in domain class definition\nunique:true =&gt; table index\n
  28. possible to configure sort on other condition in domain class definition\nunique:true =&gt; table index\n
  29. possible to configure sort on other condition in domain class definition\nunique:true =&gt; table index\n
  30. if not valid =&gt; bean remains the same in the database\n
  31. if not valid =&gt; bean remains the same in the database\n
  32. if not valid =&gt; bean remains the same in the database\n
  33. \n
  34. \n
  35. do not call generate-controller too early in development phase\n
  36. do not call generate-controller too early in development phase\n
  37. do not call generate-controller too early in development phase\n
  38. \n
  39. \n
  40. database\nsame situation ~ than with run-app\n
  41. PersonIntegrationTests instead PersonTests to avoid class name conflict\n
  42. PersonIntegrationTests instead PersonTests to avoid class name conflict\n
  43. PersonIntegrationTests instead PersonTests to avoid class name conflict\n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. see error groovy 1.6 on the storyboard\n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. This is not the correct way!\n
  63. This is not the correct way!\n
  64. \n
  65. \n
  66. \n
  67. grails will provide the mechanism for consistency\n
  68. \n
  69. \n
  70. addToMessages is implicitely created\n
  71. addToMessages is implicitely created\n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n