SlideShare ist ein Scribd-Unternehmen logo
1 von 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

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Mehr von 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
 

Mehr von 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
 

Kürzlich hochgeladen

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 

Kürzlich hochgeladen (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 

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

Hinweis der Redaktion

  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