Groovy og Grails  for Javaudviklere
Søren Berg Glasius <ul><li>100%  Nørd!
Javaudvikler siden 2000
Ansat hos  Gennemtænkt IT </li><ul><li>Konsulenter med  Groovy  og  Grails  som speciale
Benytter  Grails  som platform til produkt </li></ul><li>Formand for Javagruppen
Stifter af  GR8Conf  – en konference for Groovy et al.
Passioneret  bruger af Groovy og Grails
Twitter: @sbglasius </li></ul>
Agenda <ul><li>Groovy  </li><ul><li>Overblik
Obligatoriske ”Hello World”
Syntax og syntaktisk sukker
Groovy API (GDK) </li></ul><li>Groovy og testing </li><ul><li>Mocking af interfaces
Spock </li></ul><li>Grails </li><ul><li>Kort introduktion
Live coding! </li></ul><li>Afrunding </li></ul>10 min. pause
Groovy - Overblik <ul><li>Groovy startet august 2003 af  James Strachan
Open Source (BSD / Apache licens)
Dynamisk sprog på JVM'en
Grammatik videreudviklet fra Java
Inspireret af Python, Ruby og Smalltalk
Flad indlæringkurve for Java-udviklere </li></ul>Java på Steroider!
Et dynamisk sprog <ul><li>Ingen compile time check </li><ul><li>int i = 'Hello'  -> throws RuntimeException </li></ul><li>...
def i = 0 // Tildel integer i = ”streng” // skift til streng </li></ul></ul>
Et Java-eksempel public class UsingJava { private String name; public String getName() { return name; } public void setNam...
Et Java-eksempel
Et Java-eksempel Groovyfied class GettingGroovy { String name @Override String toString() { &quot;Get Groovy $name&quot; }...
public class HelloWorld { private String name; public String getName() { return name; } public void setName(String name) {...
Collections <ul><li>Java Lists
Groovy Lists </li></ul>def list = [ &quot;String 1&quot;,&quot;String 2&quot; ]  assert list[0] == &quot;String 1&quot;  a...
Collections <ul><li>Java Maps
Groovy Maps </li></ul>def map = [key1:&quot;Value 1&quot;,key2: &quot;Value 2&quot;] assert !map.containsKey(&quot;key3&qu...
Lists <ul><li>Del-elementer af en liste </li></ul>def list = [&quot;s1&quot;,&quot;s2&quot;,&quot;s3&quot;,&quot;s4&quot;,...
Unificering <ul><li>Længden på et objekt, med Java:
Med Groovy: </li></ul>public static void main(String[] args) { String string = &quot;String&quot;; String[] array = new St...
Gotchas <ul><li>==  er ikke sammenligning af objekt-referencer, men kalder Java's  equals()
is()  er sammenligning af objekt-referencer
return  behøves ikke. Retur er resultatet af sidste evaluererede udtryk.
Metoder og klasser er  public
Alle exceptions er unchecked og runtime!
Der er ingen primitiver – alt box'es
Decimal udregninger foregår i  BigDecimal </li></ul>
Metoder <ul><li>Det er muligt at angive default værdier i metoder </li></ul>def m(a, b = &quot;ukendt&quot;) {  println &q...
Metoder (2) <ul><li>Det er muligt at have flere returværdier </li></ul>def metode() { [&quot;my string&quot;, 1] } def (st...
Groovy Closures <ul><li>Kodeblokke  </li><ul><li>Kan tildeles variable
Kan sendes med som parametre
Tænk: ”Annonymous Inner Classes” simplificeret!  </li></ul></ul>def c = { a, b = &quot;ukendt&quot; -> println &quot;$a og...
Sandheden i Groovy <ul><li>Java boolean evaluering
Groovy boolean evaluering </li></ul>assert !null assert new Object() assert !&quot;&quot; assert &quot;Indhold&quot; asser...
Syntaktisk sukker <ul><li>Sikker variabel reference
Elvis operator </li></ul>a?.b?.doSomething() if(getA() != null && getA().getB() != null) { getA().getB().doSomething(); } ...
Strings <ul><li>'Dette er en String'
” Dette er en GString” </li><ul><li>GStrings kan benytte variabel substitution </li></ul><li>'C' as Char  // er en char
” Dette er en GString”.size()   // Længden på en streng
Multiline Strings </li></ul>def name = 'Nørder' println &quot;Hej $name&quot; def name=&quot;Nørder&quot; def xml = &quot;...
Upcoming SlideShare
Loading in …5
×

Groovy og Grails for Javaudviklere

1,162 views
1,073 views

Published on

Slides fra mine "Groovy og Grails for Javaudviklere" foredrag hos DIT og GeekNight

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,162
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Husk: Fjern ”private” Lav et eksempel med void setName(name) { this.name = name.reverse() } Vis AST transformation
  • Både enkelt-ping, dobbelt-ping og trippel-ping er en java.lang.String, men det øjeblik man bruger ${} bliver det til en Gstring Husk at forklare, size()
  • Husk at forklare, at Groovy håndtere resourcer (open/close og fejl) automatisk.
  • Vis indhold af http://oiorest.dk/danmark/kommuner/746/skoler I en browser!
  • Vis indhold af http://oiorest.dk/danmark/kommuner/746/skoler I en browser!
  • Vis del et af koden og vent med resten....
  • Vis del to, hvor der testes mellem Groovy og Java
  • Fortæl, at Spock er en DSL og er en yderligere udvidelse af Groovy, hvor man har lavet en syntaks som er specialiseret til at ”fortælle historier”
  • Vis del tre, hvor der testes med Spock
  • grails create-app Tieto cd Tieto grails run-app (Åben browser) grails create-domain-class dk.demo.Person nano grails-app/domain/dk/demo/Person String name int age grails create-controller dk.demo.Person nano grails-app/controller/dk/demo/Person static scaffold = true grails run-app grails install-plugin iwebkit grails install-iwebkit-templates grails run-app
  • Groovy og Grails for Javaudviklere

    1. 1. Groovy og Grails for Javaudviklere
    2. 2. Søren Berg Glasius <ul><li>100% Nørd!
    3. 3. Javaudvikler siden 2000
    4. 4. Ansat hos Gennemtænkt IT </li><ul><li>Konsulenter med Groovy og Grails som speciale
    5. 5. Benytter Grails som platform til produkt </li></ul><li>Formand for Javagruppen
    6. 6. Stifter af GR8Conf – en konference for Groovy et al.
    7. 7. Passioneret bruger af Groovy og Grails
    8. 8. Twitter: @sbglasius </li></ul>
    9. 9. Agenda <ul><li>Groovy </li><ul><li>Overblik
    10. 10. Obligatoriske ”Hello World”
    11. 11. Syntax og syntaktisk sukker
    12. 12. Groovy API (GDK) </li></ul><li>Groovy og testing </li><ul><li>Mocking af interfaces
    13. 13. Spock </li></ul><li>Grails </li><ul><li>Kort introduktion
    14. 14. Live coding! </li></ul><li>Afrunding </li></ul>10 min. pause
    15. 15. Groovy - Overblik <ul><li>Groovy startet august 2003 af James Strachan
    16. 16. Open Source (BSD / Apache licens)
    17. 17. Dynamisk sprog på JVM'en
    18. 18. Grammatik videreudviklet fra Java
    19. 19. Inspireret af Python, Ruby og Smalltalk
    20. 20. Flad indlæringkurve for Java-udviklere </li></ul>Java på Steroider!
    21. 21. Et dynamisk sprog <ul><li>Ingen compile time check </li><ul><li>int i = 'Hello' -> throws RuntimeException </li></ul><li>Ducktyping </li><ul><li>def keyword med fokus på, hvad et objekt kan gøre, ikke hvilken type det er
    22. 22. def i = 0 // Tildel integer i = ”streng” // skift til streng </li></ul></ul>
    23. 23. Et Java-eksempel public class UsingJava { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return &quot;Using Java &quot; + getName(); } public static void main(String[] args) { UsingJava usingJava = new UsingJava(); usingJava.setName(&quot;Geeks&quot;); System.out.println(usingJava); } }
    24. 24. Et Java-eksempel
    25. 25. Et Java-eksempel Groovyfied class GettingGroovy { String name @Override String toString() { &quot;Get Groovy $name&quot; } } println new GettingGroovy(name: &quot;Geeks&quot;)
    26. 26. public class HelloWorld { private String name; public String getName() { return name; } public void setName(String name) { this.name=name; } @Override public String toString() { return &quot;Hello &quot;+getName(); } public static void main(String[] args) { HelloWorld helloWorld = new HelloWorld(); helloWorld.setName(&quot;Geeks&quot;); System.out.println(helloWorld); } } Java vs. Groovy class GettingGroovy { String name String toString() { &quot;Get Groovy $name&quot; } } println new GettingGroovy(name: &quot;Geeks&quot;) Færre linier kode Færre mulighed for fejl! 18 linier kode 7 linier kode 60% mindre Kode!
    27. 27. Collections <ul><li>Java Lists
    28. 28. Groovy Lists </li></ul>def list = [ &quot;String 1&quot;,&quot;String 2&quot; ] assert list[0] == &quot;String 1&quot; assert list.get(0) == &quot;String 1&quot; assert list.size == 2 List list = Arrays.asList(&quot;String 1&quot;, &quot;String 2&quot;); assert(list.get(0).equals(&quot;String 1&quot;)); assert(list.size()==2);
    29. 29. Collections <ul><li>Java Maps
    30. 30. Groovy Maps </li></ul>def map = [key1:&quot;Value 1&quot;,key2: &quot;Value 2&quot;] assert !map.containsKey(&quot;key3&quot;) && !map[&quot;key3&quot;] && !map.key3 assert map.key1 assert map.key1==&quot;Value 1&quot; assert map.size() == 2 Map map = new HashMap(); map.put(&quot;Key 1&quot;,&quot;Value 1&quot;); map.put(&quot;Key 2&quot;,&quot;Value 2&quot;); assert(!map.containsKey(&quot;Key 3&quot;)); assert(map.containsKey(&quot;Key 1&quot;)); assert(map.get(&quot;Key 1&quot;).equals(&quot;Value 1&quot;)); assert(map.size() == 2);
    31. 31. Lists <ul><li>Del-elementer af en liste </li></ul>def list = [&quot;s1&quot;,&quot;s2&quot;,&quot;s3&quot;,&quot;s4&quot;,&quot;s5&quot;] assert list[2..3] == ['s3','s4'] assert list[3..2] == ['s4','s3'] assert list[-1] == 's5' assert list[-2] == 's4' assert list[3..-1] == ['s4','s5'] List list = Arrays.asList(&quot;s1&quot;,&quot;s2&quot;,&quot;s3&quot;,&quot;s4&quot;,&quot;s5&quot;); assert list.subList(2,4).equals(Arrays.asList(&quot;s3&quot;,&quot;s4&quot;)); List<String> reversed = list.subList(2,4); Collections.reverse(reversed); assert reversed.equals(Arrays.asList(&quot;s4&quot;,&quot;s3&quot;)); assert list.get(list.size())==&quot;s5&quot;; assert list.subList(3,list.size())==Arrays.asList(&quot;s4&quot;,&quot;s5&quot;);
    32. 32. Unificering <ul><li>Længden på et objekt, med Java:
    33. 33. Med Groovy: </li></ul>public static void main(String[] args) { String string = &quot;String&quot;; String[] array = new String[] {&quot;String1&quot;,&quot;String2&quot;}; Map<String,String> map = new HashMap<String,String>(); map.put(&quot;Key1&quot;,&quot;Val1&quot;); List<String> list = new ArrayList<String>(); list.add(&quot;String1&quot;); assert string. length() ==6; assert array. length == 2; assert map. size() ==1; assert list. size() ==1; } def string = &quot;String&quot;, array = [&quot;String1&quot;,&quot;String2&quot;] def map = [Key1:&quot;Val1&quot;], list = [&quot;String1&quot;] assert string. size() == 6 assert array. size() == 2 assert map. size() == 1 assert list. size() == 1
    34. 34. Gotchas <ul><li>== er ikke sammenligning af objekt-referencer, men kalder Java's equals()
    35. 35. is() er sammenligning af objekt-referencer
    36. 36. return behøves ikke. Retur er resultatet af sidste evaluererede udtryk.
    37. 37. Metoder og klasser er public
    38. 38. Alle exceptions er unchecked og runtime!
    39. 39. Der er ingen primitiver – alt box'es
    40. 40. Decimal udregninger foregår i BigDecimal </li></ul>
    41. 41. Metoder <ul><li>Det er muligt at angive default værdier i metoder </li></ul>def m(a, b = &quot;ukendt&quot;) { println &quot;$a og $b&quot; } m('a') m('a','b') a og ukendt a og b
    42. 42. Metoder (2) <ul><li>Det er muligt at have flere returværdier </li></ul>def metode() { [&quot;my string&quot;, 1] } def (string,value) = metode() assert string == &quot;my string&quot; assert value == 1
    43. 43. Groovy Closures <ul><li>Kodeblokke </li><ul><li>Kan tildeles variable
    44. 44. Kan sendes med som parametre
    45. 45. Tænk: ”Annonymous Inner Classes” simplificeret! </li></ul></ul>def c = { a, b = &quot;ukendt&quot; -> println &quot;$a og $b&quot; } c('a','b') [key1:'value1',key2:'value2'].each(c) ['value1','value2'].each(c) c.call('1','2') Kommer i Java 8 (men hvornår) Groovy har haft dem fra starten! a og b key1 og value1 key2 og value2 value1 og ukendt value2 og ukendt 1 og 2
    46. 46. Sandheden i Groovy <ul><li>Java boolean evaluering
    47. 47. Groovy boolean evaluering </li></ul>assert !null assert new Object() assert !&quot;&quot; assert &quot;Indhold&quot; assert ![] // List assert [&quot;Indhold&quot;] Object o = null; assert(o == null); o = new Object(); assert(o != null); assert(&quot;&quot;.length() == 0); assert(&quot;Indhold&quot;.length() > 0); List l = new ArrayList(); assert(l.size() != null); l.add(&quot;Element&quot;); assert(l.size() > 0);
    48. 48. Syntaktisk sukker <ul><li>Sikker variabel reference
    49. 49. Elvis operator </li></ul>a?.b?.doSomething() if(getA() != null && getA().getB() != null) { getA().getB().doSomething(); } String x = b ?: ”default” String x = getB() != null ? getB() : ”default”
    50. 50. Strings <ul><li>'Dette er en String'
    51. 51. ” Dette er en GString” </li><ul><li>GStrings kan benytte variabel substitution </li></ul><li>'C' as Char // er en char
    52. 52. ” Dette er en GString”.size() // Længden på en streng
    53. 53. Multiline Strings </li></ul>def name = 'Nørder' println &quot;Hej $name&quot; def name=&quot;Nørder&quot; def xml = &quot;&quot;&quot; <xml> <element>Hej &quot;$name&quot;</element> </xml>&quot;&quot;&quot;
    54. 54. Meta programmering – meget kort! <ul><li>En måde at tilføje funktionalitet til eksisterende klasser
    55. 55. Brugt meget i Groovys API'er
    56. 56. Eksempel: </li></ul>String.metaClass.toCamelCase = { delegate.toLowerCase().replaceAll( /(_)([a-z0-9])/, { Object[] part -> part[2].toUpperCase() }) } String.metaClass.toSnakeCase = { capitalize = false -> def res = delegate.replaceAll( /([A-Z])/, /_$1/ ) .replaceAll( /^_/, '' ) capitalize ? res.toUpperCase() : res.toLowerCase() } println &quot;THIS_IS_A_CASE_FOR_THE_CAMEL&quot;.toCamelCase() println &quot;AndNowForSomeSnakeOil&quot;.toSnakeCase() println &quot;LoudYellingExample&quot;.toSnakeCase(true)
    57. 57. Groovy API guf! <ul><li>Indlæs en fil
    58. 58. Indlæs en url </li></ul>def path = '.', file = &quot;Groovy.txt&quot; println new File(path,file).text println new File(path,file).readLines().join(' ') new File(path,file).eachLine { line,i -> println &quot;${&quot;${i}&quot;.padLeft(2)}: ${line}&quot; } def url = &quot;http://oiorest.dk/danmark/kommuner/746/skoler&quot;.toURL() println url.text url.eachLine { line,i -> println &quot;${&quot;${i}&quot;.padLeft(3)}: ${line}&quot; }
    59. 59. Groovy API guf! <ul><li>Parse en XML fil </li></ul>def url = &quot;http://oiorest.dk/danmark/kommuner/746/skoler&quot; def skoler = new XmlSlurper().parse(url) skoler.skole.each { println &quot;$it.navn ($it.type)&quot; } <skoler xmlns=&quot;http://itst.dk/schemas/danmarkservice&quot;> <skole ref=&quot;http://oiorest.dk/danmark/skoler/715001&quot;> <institutionsnr>715001</institutionsnr> <navn>Bakkeskolen</navn> <type>Folkeskole</type> <kommune ref=&quot;http://oiorest.dk/danmark/kommuner/746&quot; /> <skoledistrikt ref=&quot;http://oiorest.dk/danmark/kommuner/746/skoledistrikter/6&quot; /> <adresse ref=&quot;http://oiorest.dk/danmark/adresser/1824787&quot;> <vej> <navn> Skolevej </navn> </vej> <husnr>2</husnr> <postdistrikt ref=&quot;http://oiorest.dk/danmark/postdistrikter/8362&quot;> <nr>8362</nr> <navn>Hørning</navn> </postdistrikt> </adresse> </skole> <skole ref=&quot;http://oiorest.dk/danmark/skoler/737002&quot;> <institutionsnr>737002</institutionsnr> <navn>Bjedstrup Skole</navn> <type>Folkeskole</type> <kommune ref=&quot;http://oiorest.dk/danmark/kommuner/746&quot; /> <skoledistrikt ref=&quot;http://oiorest.dk/danmark/kommuner/746/skoledistrikter/13&quot; /> <adresse ref=&quot;http://oiorest.dk/danmark/adresser/1961043&quot;> <vej> <navn> Bjedstrupvej </navn> </vej> <husnr>1</husnr> <postdistrikt ref=&quot;http://oiorest.dk/danmark/postdistrikter/8660&quot;> <nr>8660</nr> <navn>Skanderborg</navn> </postdistrikt> </adresse> </skole>
    60. 60. Groovy API guf! <ul><li>Parse en XML fil + lidt mere </li></ul>def url = &quot;http://oiorest.dk/danmark/kommuner/746/skoler&quot; def skoler = new XmlSlurper().parse(url) skoler.skole.inject([:]) { map,item -> map[item.navn] = item.type map }.groupBy { it.value.toString() }.each { println &quot;$it.key&quot; it.value.each { println &quot; $it.key&quot; } }
    61. 61. Groovy API guf! <ul><li>Generer en XML fil </li></ul>def writer = new StringWriter() def xml = new groovy.xml.MarkupBuilder(writer) xml.rows() { 5.times { i -> row(id: i, href: &quot;http://localhost/$i&quot;) { if(i in [2,4]) { info &quot;Dette er info for række $i&quot; } } } } writer.toString()
    62. 62. Groovy API guf! <ul><li>Parse et JSON response </li></ul>def url = &quot;http://oiorest.dk/danmark/kommuner/746/skoler.json&quot; def json = url.toURL().getText(&quot;utf-8&quot;) def slurper = new groovy.json.JsonSlurper() def skoler = slurper.parseText(json) skoler.each { println &quot;$it.navn $it.type&quot; }
    63. 63. Groovy API guf! <ul><li>Generer en JSON fil </li></ul>def json = new groovy.json.JsonBuilder() def list = json.event { name &quot;Getting Groovy&quot; time new Date() speaker { name &quot;Søren B. Glasius&quot; company &quot;Gennemtænkt IT&quot; } } json.toString()
    64. 64. Groovy API guf! <ul><li>SQL – nemmere end aldrig før </li></ul>@Grapes([ @Grab('mysql:mysql-connector-java:5.1.6'), @GrabConfig(systemClassLoader=true) ]) import groovy.sql.Sql def sql = Sql.newInstance(&quot;jdbc:mysql://localhost:3306/demo&quot;, &quot;demo&quot;, &quot;demo&quot;, &quot;com.mysql.jdbc.Driver&quot;) sql.eachRow(&quot;select * from person&quot;) { println &quot;${it.name} comes from ${it.country}&quot; }
    65. 65. AST Transformationer <ul><li>Metaprogrammering på compile-time niveau </li><ul><li>Egne udvidelser af Groovy </li></ul><li>Eksempler </li><ul><li>@Bindable og @Vetoable
    66. 66. @Imutable
    67. 67. @Singleton
    68. 68. @Lazy </li></ul></ul>
    69. 69. @Bindable <ul><li>Javakode for at lave property change listener </li></ul>import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeListener; public class MyBean { private String prop; PropertyChangeSupport pcs = new PropertyChangeSupport(this); public void addPropertyChangeListener(PropertyChangeListener l) { pcs.add(l); } public void removePropertyChangeListener(PropertyChangeListener l) { pcs.remove(l); } public String getProp() { return prop; } public void setProp(String prop) { pcs.firePropertyChanged(&quot;prop&quot;, this.prop, this.prop = prop); } } class MyBean { @Bindable String prop }
    70. 70. @Delegate <ul><li>Delegation </li></ul>class Event extends Date { @Delegate Date when String title, url } def df = new java.text.SimpleDateFormat(&quot;yyyy/MM/dd&quot;) def gr8conf_eu = new Event(title: &quot;GR8Conf Europe&quot;, url: &quot;http://www.gr8conf.eu&quot;, when: df.parse(&quot;2011/05/17&quot;)) def gr8conf_us = new Event(title: &quot;GR8Conf Europe&quot;, url: &quot;http://www.gr8conf.us&quot;, when: df.parse(&quot;2011/06/24&quot;)) assert gr8conf_eu.before(gr8conf_us)
    71. 71. @Imutable <ul><li>Javakode for at lave en imutable klasse </li></ul>public final class Punter { private final String first; private final String last; public Punter(String first, String last) { this.first = first; this.last = last; } public String getFirst() { return first; } public String getLast() { return last; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; }
    72. 72. @Imutable (fortsat) @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Punter other = (Punter) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; return true; } @Override public String toString() { return &quot;Punter(first:&quot; + first + &quot;, last:&quot; + last + &quot;)&quot;; } } @Immutable final class Punter { String first, last }
    73. 73. Java og Groovy – en kærlighedshistorie Hvordan bruges Groovy og Java sammen DEMO!
    74. 74. Groovy til test <ul><li>Simpel mocking af interfaces
    75. 75. Testing vha. Spock (www.spockframework.org) </li></ul>
    76. 76. Spock <ul><li>Test og specifikations framework
    77. 77. Beskriv testscenarier som historier </li></ul><ul><li>Et eksempel </li></ul>
    78. 78. class APublisher extends Specification { def &quot; send besked til alle subscribers &quot;() { setup: &quot; før kørsel skal der være en publisher og to subscribers &quot; def pub = new Publisher() def sub1 = Mock(Subscriber) def sub2 = Mock(Subscriber) pub.subscribers << sub1 << sub2 when: &quot; Når en publisher sender en besked &quot; pub.send(&quot;event&quot;) then: &quot; Skal hver receiver modtage den én gang &quot; 1 * sub1.receive(&quot;event&quot;) 1 * sub2.receive(&quot;event&quot;) } } Spock – fortæl en historie
    79. 79. Testing.. testing... en - to
    80. 80. PAUSE! Hils på din sidemand Stræk benene Vi starter igen om 10 minutter.
    81. 81. Web udvikling På den fede måde....
    82. 82. Grails – en komplet stak + + +
    83. 83. Værd at bemærke ved Grails <ul><li>Convention over configuration </li><ul><li>Minimal konfiguration </li></ul><li>Projektstruktur er prædefineret
    84. 84. Kommandolinie værktøjet kan udføre de fleste kommandoer til Grails
    85. 85. Unit og integrationstest er en naturlig del af udviklingsfasen
    86. 86. Kan deployes til de fleste App-servere som en war fil </li></ul>
    87. 87. GORM <ul><li>Hibernate under hjelmen
    88. 88. Med Groovy elimineres det meste boilerplate kode
    89. 89. Med mappings kan legacy systemer adresseres
    90. 90. Har Event handlers til save/update/delete etc...
    91. 91. Validering af data slår igennem i alle lag (model -> view) </li></ul>
    92. 92. Basal CRUD def person = new Person(navn: 'Kurt', alder: 42) Person.save() def person = Person.get(1) assert person.id == 1 def person = Person.get(1) person.navn = 'Svend' person.save() def person = Person.get(1) person.delete() C R U D
    93. 93. Dynamic finders def personer = Person.list() def personer = Person.list(sort: 'navn', order: 'desc') def personer = Person.findAllByNavnLike('%Jensen%') def person = Person.findByNavnLike('%Jensen%') def person = Person.findByNavnAndAlder('Svend', 42) def c = Konto.createCriteria() def konti = c.list { between(dato, igår, nu) ilike(navn, '%Jensen%') }
    94. 94. Andre fordele <ul><li>RESTfull development er meget nemt
    95. 95. Output af json og XML med få linier kode
    96. 96. Web sider laves ud fra templates
    97. 97. Det er meget nemt at lave urlMappings
    98. 98. Forms og webflows – ingen problem.
    99. 99. Interceptors og filters – super nemt! </li></ul>
    100. 100. Grails – plugins 575 plugins http://www.wordle.net
    101. 101. Grails
    102. 102. Andre frameworks med Groovy <ul><li>Gradle (Næste generations build)
    103. 103. Spock
    104. 104. EasyB
    105. 105. Griffon (Swing udvikling – der virker!)
    106. 106. GMaven
    107. 107. Gant
    108. 108. GAELYK (Google App Engine møder Groovy)
    109. 109. Se flere på http://groovy.codehaus.org </li></ul>
    110. 110. Resourcer Gratis download!
    111. 111. Web-links <ul><li>http://groovy.codehaus.org
    112. 112. http://www.grails.org
    113. 113. http://code.google.com/p/spock/
    114. 114. http://www.groovymag.com
    115. 115. http://www.infoq.com/minibooks/grails-getting-started </li></ul>
    116. 116. Reklame!
    117. 117. Tak! Stil endelig spørgsmål!

    ×