groovy & grails - lecture 10
TRANSCRIPT
Groovy: Efficiency Oriented ProgrammingLecture 10
Master Proteomics & Bioinformatics - University of GenevaAlexandre Masselot - summer 2011
Agenda
‣SVN & google code hosting
‣More on GSP
‣ Including third parties libraries
‣Ajax
‣Runtime environment
‣Domains
SCM
‣Code evolve in time
SCM
‣Code evolve in time
‣Source code is shared
SCM
‣Code evolve in time
‣Source code is shared
‣Source Code Management system host code + versioning
SCM
‣Code evolve in time
‣Source code is shared
‣Source Code Management system host code + versioning
‣Many solutions exist: CVS, SVN, GIT, SourceSafe...
SCM
‣Code evolve in time
‣Source code is shared
‣Source Code Management system host code + versioning
‣Many solutions exist: CVS, SVN, GIT, SourceSafe...
‣SVN is a client/server solution
SCM
‣Code evolve in time
‣Source code is shared
‣Source Code Management system host code + versioning
‣Many solutions exist: CVS, SVN, GIT, SourceSafe...
‣SVN is a client/server solution
‣Server can be in-house
SCM
‣Code evolve in time
‣Source code is shared
‣Source Code Management system host code + versioning
‣Many solutions exist: CVS, SVN, GIT, SourceSafe...
‣SVN is a client/server solution
‣Server can be in-house
‣Free solution for open source
http://code.google.com/hosting/
make an google account
Create ProjectProject name: geop-demo
Project summary: A demo project for GEOP course
Project description: geop demo code Version control system: Subversion Source code license: New BSD License Use a separate content license:license...
Project labels:
Create project...
Project name must start with a lowercase letter, followed by lowercase letters, digits, and dashes, with no spaces. This will be part of your project's URL and cannot be changed later.Project summary will be shown whenever the project's name is displayed.Project description is the main content of your project's home page. You may use wiki markup.Version control system selects the type of your project's repository. Learn more.Licenses determine how others may build upon your work. Code and documentation may be distributed under separate licenses.Project labels help classify your project so others can easily find it or browse projects by label.
Google proposes command line commandsWe’ll see how to integrate svn into eclipse
Command-line access
If you plan to make changes, use this command to check out the code as yourself using HTTPS:
# Project members authenticate over HTTPS to allow committing changes.svn checkout https://geop-demo.googlecode.com/svn/trunk/ geop-demo --username alexandre.masselot
When prompted, enter your generated googlecode.com password.
Use this command to anonymously check out the latest project source code:
# Non-members may check out a read-only working copy anonymously over HTTP.svn checkout http://geop-demo.googlecode.com/svn/trunk/ geop-demo-read-only
GUI and IDE access
This project's Subversion repository may be accessed using many different client programs and plug-ins. See your client's documentation for more information.
Google code offers for “free”
‣SVN repository
Google code offers for “free”
‣SVN repository
‣Managing contributors to a project
Google code offers for “free”
‣SVN repository
‣Managing contributors to a project
‣Wiki
Google code offers for “free”
‣SVN repository
‣Managing contributors to a project
‣Wiki
‣Ticketing system
Google code offers for “free”
‣SVN repository
‣Managing contributors to a project
‣Wiki
‣Ticketing system
‣Bug reporting
Google code offers for “free”
‣SVN repository
‣Managing contributors to a project
‣Wiki
‣Ticketing system
‣Bug reporting
‣Visibility
Google code hosting⇒
your code is open source
SVN: eclipse or command line
Installing svn in Eclipse
‣Help > dashboard > extension- Subversion (subclipse)
Installing svn in Eclipse
‣Help > dashboard > extension- Subversion (subclipse)
‣Or command line: installed by default or- sudo apt-get install subversion
Eclipse: connecting to the SVN repository
‣menu Window - > open perspective
- > SVN repository exploring
Eclipse: connecting to the SVN repository
‣menu Window - > open perspective
- > SVN repository exploring
‣view SVN repositories- > right click
- > new repository location
- https://geop-demo.googlecode.com/svn
Sharing an existing project to your google code account
Sharing an existing project to your google code account
‣Perspective java
Sharing an existing project to your google code account
‣Perspective java
‣project right-click- > team
- > share project- use specifier folder name
trunk/your.project.name
‣username & password
from google page
‣save password
check box
Commit the project
‣At this stage, the project is only created on the remote server- check with SVN repository exploring perspective- or browse source code from google page
Commit the project
‣At this stage, the project is only created on the remote server- check with SVN repository exploring perspective- or browse source code from google page
‣Mark generated file & folder to be ignored from svn- e.g. target/
Commit the project
‣At this stage, the project is only created on the remote server- check with SVN repository exploring perspective- or browse source code from google page
‣Mark generated file & folder to be ignored from svn- e.g. target/
‣Right-click > team > add to svn:ignore
All eclipse functionalitiescan be replaced by shell commands
SVN command line: share project
‣ Import original project demo.svn to the repository
‣cd workspace directorysvn import -m “initial import” --non-recursive demo.svn https://geop-demo.googlecode.com/svn/trunk/demo.svn
‣Directory itself is not imported, so checkout (with force)svn checkout --force https://geop-demo.googlecode.com/svn/trunk/demo.svn
SVN command line: share project (cont’d)
cd demo.svn
‣Add target/ directory to svn:ignoresvn propset svn:ignore target .
‣Add other directories to svnsvn add $(ls | grep -v target)
‣Commit filessvn commit -m "adding all initial files"
‣Back to eclipse, F5 (refresh in package explorer view)
Browse your project
From google code source page
25
SVN for a daily use
SVN for a daily useSVN for a daily useminutely
SVN: flow use
‣Checkout out or share an existing project to contribute
SVN: flow use
‣Checkout out or share an existing project to contribute
‣Commit changes to the repository
SVN: flow use
‣Checkout out or share an existing project to contribute
‣Commit changes to the repository
‣Update changes from repository
SVN: flow use
‣Checkout out or share an existing project to contribute
‣Commit changes to the repository
‣Update changes from repository
‣Eclipse: - select project- > right-click - > team- > Synchronize with repository- commit/update/manage conflict
SVN: flow use (cont’d)
‣Command linesvn statussvn updatesvn commit -m “my message to describe changes”
Commit/update often
SVN is more
‣History
SVN is more
‣History
‣See contribution from others
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
‣Conflict resolution
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
‣Conflict resolution
‣Continuous integration / testing on dedicated server
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
‣Conflict resolution
‣Continuous integration / testing on dedicated server
‣File locking :(
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
‣Conflict resolution
‣Continuous integration / testing on dedicated server
‣File locking :(
‣ Integration with tickets
SVN is more
‣History
‣See contribution from others
‣Tag / branch versions
‣Conflict resolution
‣Continuous integration / testing on dedicated server
‣File locking :(
‣ Integration with tickets
‣Windows integration: http://tortoisesvn.tigris.org/
Back to grails... and proteins isoforms
Problem: uniprot AC ➙ isoform listin a web application
Grails: including a third parties libraries
‣Library is available as a jar (export ➙ .jar)
Grails: including a third parties libraries
‣Library is available as a jar (export ➙ .jar)
‣Copy jar in lib/
Grails: including a third parties libraries
‣Library is available as a jar (export ➙ .jar)
‣Copy jar in lib/
‣For eclipse completion- right-click- build path- add to build path
Get is forms for ac (00:44:01.975)Q70Z44List
>Q70Z44-1MQKHSPGPPALALLSQSLLTTGNGDTLIINCPGFGQHRVDPAAFQAVFDRKAIGPVTNYSVATHVNISFTLSAIWNCYSRIHTFNCHHARPWHNQFVQWNPDECGGIKKSGMATENLWLSDVFIEESVDQTPAGLMASMSIVKATSNTISQCGWSASANWTPSISPSMDRARAWRRMSRSFQIHHRTSFRTRREWVLLGIQKRTIKVTVATNQYEQAIFHVAIRRRCRPSPYVVNFLVPSGILIAIDALSFYLPLESGNCAPFKMTVLLGYSVFLLMMNDLLPATSTSSHASLVAPLALMQTPLPAGVYFALCLSLMVGSLLETIFITHLLHVATTQPLPLPRWLHSLLLHCTGQGRCCPTAPQKGNKGPGLTPTHLPGVKEPEVSAGQMPGPGEAELTGGSEWTRAQREHEAQKQHSVELWVQFSHAMDALLFRLYLLFMASSIITVICLWNT
>Q70Z44-2MASMSIVKATSNTISQCGWSASANWTPSISPSMDRAERSPSALSPTQVAIRRRCRPSPYVVNFLVPSGILIAIDALSFYLPLESGNCAPFKMTVLLGYSVFLLMMNDLLPATSTSSHASLVRPHPSRDQKRGVYFALCLSLMVGSLLETIFITHLLHVATTQPLPLPRWLHSLLLHCTGQGRCCPTAPQKGNKGPGLTPTHLPGVKEPEVSAGQMPGPGEAELTGGSEWTRAQREHEAQKQHSVELWVQFSHAMDALLFRLYLLFMASSIITVICLWNT
Isoforms_v1 -> v5 same controllerdifferent views (gsp)
for different rendering interaction
Isoforms_v1 -> v5 same controllerdifferent views (gsp)
for different rendering interaction
Isoforms_vXController⇒
views/isoforms_vX/ direcgtory with gsp’s
IsoformController_v?.groovy
def list = { def ac=params.ac def xml=new XmlSlurper() .parseText("http://pir.uniprot.org/uniprot/${ac}.xml".toURL().text).entry UniprotEntrySplicer splicer=[entryXml:xml] def proteins=splicer.buildAllIsoforms().values() as List
[proteins: proteins] }
v1
isoforms_v1/list.gsp
<html> <body> <h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2> <g:form action="list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /> </g:form> <h3>List</h3> <g:each in="${proteins}" var="prot"> <pre> ${prot} </pre> </g:each> </body></html>
Problem: direct access to /list only
v2
v2
isoforms_v2: add index.gsp
<html> <body> <h1>Isoform list application</h1> <h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2> <g:form action="list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /> </g:form> </body></html>
Problem: <g:form> is duplicated (DRY!)
isoform_v3: use template
‣_form.gsp<h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2><g:form action="list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /></g:form>
isoform_v3: use template
‣_form.gsp<h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2><g:form action="list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /></g:form>
‣ In index.gsp and list.gsp <g:render template="form" />
isoform_v3: use template
‣_form.gsp<h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2><g:form action="list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /></g:form>
‣ In index.gsp and list.gsp <g:render template="form" />
Problem: all the page is reloaded totally
v4
Ajax: asynchronous load
47
Q70Z44
web browser
submit
isoform/list
server
Ajax: asynchronous load
47
Q70Z44
web browser
submit
isoform/list
server
Ajax: asynchronous load
47
Q70Z44
List
>Q70Z44-1MQKHSPGPPALALLSQSLLTTGNGDTLIINCPGFGQHRVDPAAFQAVFDRKAIGPVTNYSVATHVNISFTLSAIWNCYSRIHTFNCHHARPWHNQFVQWNPDECGGIKKSGMATENLWLSDVFIEESVDQTPAGLMASMSIVKATSNTISQCGWSASANWTPSISPSMDRARAWRRMSRSFQIHHRTSFRTRREWVLLGIQKRTIKVTVATNQYEQAIFHVAIRRRCRPSPYVVNFLVPSGILIAIDALSFYLPLESGNCAPFKMTVLLGYSVFLLMMNDLLPATSTSSHASLVAPLALMQTPLPAGVYFALCLSLMVGSLLETIFITHLLHVATTQPLPLPRWLHSLLLHCTGQGRCCPTAPQKGNKGPGLTPTHLPGVKEPEVSAGQMPGPGEAELTGGSEWTRAQREHEAQKQHSVELWVQFSHAMDALLFRLYLLFMASSIITVICLWNT >Q70Z44-2MASMSIVKATSNTISQCGWSASANWTPSISPSMDRAERSPSALSPTQVAIRRRCRPSPYVVNFLVPSGILIAIDALSFYLPLESGNCAPFKMTVLLGYSVFLLMMNDLLPATSTSSHASLVRPHPSRDQKRGVYFALCLSLMVGSLLETIFITHLLHVATTQPLPLPRWLHSLLLHCTGQGRCCPTAPQKGNKGPGLTPTHLPGVKEPEVSAGQMPGPGEAELTGGSEWTRAQREHEAQKQHSVELWVQFSHAMDALLFRLYLLFMASSIITVICLWNT
web browser
submit
isoform/list
server
isoform_v4/index.gsp
<html> <head> <g:javascript library="prototype" /> </head> <body> <h2>Get is forms for ac (${String.format('%tH:%<tM:%<tS.%<tL', new Date())})</h2> <!-- g:formRemote stands for an ajax form --> <g:formRemote name="listForm" url="[action:'list']" update="isoforms-list"> <g:textField name="ac" value="${params.ac}" /> <g:submitButton name="submit" /> </g:formRemote> <!-- the target element of the form --> <div id="isoforms-list"/> </body></html>
isoform_v4/list.gsp
<h3>List</h3><g:each in="${proteins}" var="prot"> <pre>${prot} </pre></g:each>
Twitter 1
People post messages and follow others
database (domain)+ controller (actions)
+ views (web)
Domain: Person & Message
Domain: bean definition + database storage
Person domain
‣Create the database entry + bean class grails create-domain-class Personproject > right-click > grails > create-domain-class Person
Person domain
‣Create the database entry + bean class grails create-domain-class Personproject > right-click > grails > create-domain-class Person
‣Files created:./grails-app/domain/eop/lec10/twitter/Person.groovy./test/unit/eop/lec10/twitter/PersonTests.groovy
Person.groovy
‣Created classpackage eop.lec10.twitter
class Person {
static constraints = { }}
Person.groovy
Person.groovy
‣Enriched with fieldspackage eop.lec10.twitter
class Person { String username String firstName String lastName String email Date dateCreated
static constraints = { }}
run-app ⇒ database + table created
Web access: need controller + views
Scaffolding is pure magic
PersonController.groovy
create-controller Person
PersonController.groovy
create-controller Person
‣grails-app/controller/PersonController.groovy:package eop.lec10.twitter
class PersonController { def scaffold = true}
PersonController.groovy
create-controller Person
‣grails-app/controller/PersonController.groovy:package eop.lec10.twitter
class PersonController { def scaffold = true}
‣scaffold generate all default action & view implicitely
PersonController.groovy
create-controller Person
‣grails-app/controller/PersonController.groovy:package eop.lec10.twitter
class PersonController { def scaffold = true}
‣scaffold generate all default action & view implicitely
http://localhost:8080/eop.lec10.twitter/person
‣Default url is redirected on the list page
http://localhost:8080/eop.lec10.twitter/person
‣Default url is redirected on the list page
http://localhost:8080/eop.lec10.twitter/person
‣Entering a new Person lucky luke
http://localhost:8080/eop.lec10.twitter/person
‣Entering a new Person lucky luke
http://localhost:8080/eop.lec10.twitter/person
‣Entering a new Person lucky luke
http://localhost:8080/eop.lec10.twitter/person
http://localhost:8080/eop.lec10.twitter/person
‣Back to list- view all- edit- delete- sort
Domain constraints
Person.groovy
class Person { String username String firstName String lastName String email Date dateCreated
//firstName is compulsory //email field has an email format //username cannot be null, is unique and is between 6 and 20 characters static constraints = { firstName(blank:false) email(email:true, blank:false) username(blank:false, unique:true, matches:/\w{6,20}/) }}