Groovy reactor grails realtime web devoxx 2013

445
Guillaume Laforge @glaforge ! Groovy, Reactor, Grails & the realtime web Stéphane Maldini @smaldini !

Transcript of Groovy reactor grails realtime web devoxx 2013

Page 1: Groovy reactor grails realtime web   devoxx 2013

Guillaume Laforge @glaforge !

Groovy, Reactor, Grails & the realtime web

Stéphane Maldini@smaldini !

Page 2: Groovy reactor grails realtime web   devoxx 2013

Stéphane Maldini

Consultant and Reactor committer at .

!

@smaldini

Page 3: Groovy reactor grails realtime web   devoxx 2013

Guillaume Laforge

Groovy project lead at .

!

@glaforge http://glaforge.appspot.com

Page 4: Groovy reactor grails realtime web   devoxx 2013

Les Cast Codeurs

Page 5: Groovy reactor grails realtime web   devoxx 2013
Page 6: Groovy reactor grails realtime web   devoxx 2013

Introduction

Part 0

Page 7: Groovy reactor grails realtime web   devoxx 2013
Page 8: Groovy reactor grails realtime web   devoxx 2013

Valuable usersdon’t like to wait

Page 9: Groovy reactor grails realtime web   devoxx 2013
Page 10: Groovy reactor grails realtime web   devoxx 2013

Realtime webapplications are about

the « now »

Page 11: Groovy reactor grails realtime web   devoxx 2013
Page 12: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Page 13: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

A « push » approach vs a« pull » approach

Page 14: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Handle a bigvolume of events

A « push » approach vs a« pull » approach

Page 15: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Handle a bigvolume of events React fast to

new events

A « push » approach vs a« pull » approach

Page 16: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Handle a bigvolume of events React fast to

new events

A « push » approach vs a« pull » approach

Use promises, events,streams to react fast and

stream updates to users asthey are ready

Page 17: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Handle a bigvolume of events React fast to

new events

A « push » approach vs a« pull » approach

Use promises, events,streams to react fast and

stream updates to users asthey are ready

Avoid blockingand state

Page 18: Groovy reactor grails realtime web   devoxx 2013

Show users liveupdates as they come

Handle a bigvolume of events React fast to

new events

Fail gracefully

A « push » approach vs a« pull » approach

Use promises, events,streams to react fast and

stream updates to users asthey are ready

Avoid blockingand state

Page 19: Groovy reactor grails realtime web   devoxx 2013
Page 20: Groovy reactor grails realtime web   devoxx 2013

Sharp tools:Groovy, Reactor &

Grails

Page 21: Groovy reactor grails realtime web   devoxx 2013

Groovy

Part 1

Page 22: Groovy reactor grails realtime web   devoxx 2013

Groovy…

an Open Source alternative language

for the JVM

Page 23: Groovy reactor grails realtime web   devoxx 2013

Groovy…

Object-oriented, dynamic, with a functional flavor

Page 24: Groovy reactor grails realtime web   devoxx 2013

Groovy…

But also supports static type checking &

static compilation

Page 25: Groovy reactor grails realtime web   devoxx 2013

million downloadsper year1.7

Page 26: Groovy reactor grails realtime web   devoxx 2013
Page 27: Groovy reactor grails realtime web   devoxx 2013
Page 28: Groovy reactor grails realtime web   devoxx 2013

Yup, we’re allusing Groovy!

Page 29: Groovy reactor grails realtime web   devoxx 2013
Page 30: Groovy reactor grails realtime web   devoxx 2013

Simplify the life of(Java) developers

Page 31: Groovy reactor grails realtime web   devoxx 2013
Page 32: Groovy reactor grails realtime web   devoxx 2013

Groovy as a Javasuperset

Page 33: Groovy reactor grails realtime web   devoxx 2013

It’s so easy tolearn!

Groovy as a Javasuperset

Page 34: Groovy reactor grails realtime web   devoxx 2013
Page 35: Groovy reactor grails realtime web   devoxx 2013
Page 36: Groovy reactor grails realtime web   devoxx 2013
Page 37: Groovy reactor grails realtime web   devoxx 2013

As safe and fast as Java withstatic type checking & compilation

Page 38: Groovy reactor grails realtime web   devoxx 2013

As safe and fast as Java withstatic type checking & compilation

Page 39: Groovy reactor grails realtime web   devoxx 2013
Page 40: Groovy reactor grails realtime web   devoxx 2013

new  MarkupBuilder().html  {          head  {                  title  "The  Script  Bowl"          }  !

       body  {                  div(class:  "banner")  {                          p  "Groovy  rocks!"                  }          }  }

Page 41: Groovy reactor grails realtime web   devoxx 2013
Page 42: Groovy reactor grails realtime web   devoxx 2013

move  forward  at  3.km/h

Expressive,Concise,Readable

Page 43: Groovy reactor grails realtime web   devoxx 2013
Page 44: Groovy reactor grails realtime web   devoxx 2013
Page 45: Groovy reactor grails realtime web   devoxx 2013

@RestController  class  App  {          @RequestMapping("/")          String  home()  {  "Hello  World!"  }  }

Speaking of conciseness...A full Spring app in the span of a tweet!

Page 46: Groovy reactor grails realtime web   devoxx 2013
Page 47: Groovy reactor grails realtime web   devoxx 2013

Great forscripting

Page 48: Groovy reactor grails realtime web   devoxx 2013

Great forscripting

Fit for Domain-SpecificLanguages

Page 49: Groovy reactor grails realtime web   devoxx 2013

Great forscripting

Fit for Domain-SpecificLanguages

Most seamless integration &interoperability wih java!

Page 50: Groovy reactor grails realtime web   devoxx 2013

Great forscripting

Fit for Domain-SpecificLanguages

Most seamless integration &interoperability wih java!

Full-blown reactiveapplications too!

Page 51: Groovy reactor grails realtime web   devoxx 2013
Page 52: Groovy reactor grails realtime web   devoxx 2013

Most Java code is alsovalid Groovy code!

Page 53: Groovy reactor grails realtime web   devoxx 2013

Any Java developer is aGroovy developer!

Most Java code is alsovalid Groovy code!

Page 54: Groovy reactor grails realtime web   devoxx 2013
Page 55: Groovy reactor grails realtime web   devoxx 2013

Flat learningcurve

Page 56: Groovy reactor grails realtime web   devoxx 2013

Flat learningcurve

Easy to learn

Page 57: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Scripts versus Classes

!26

public  class  Main  {          public  static  void  main(String[]  args)  {                  System.out.println("Hello");          }  }

vs

Page 58: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Scripts versus Classes

!26

public  class  Main  {          public  static  void  main(String[]  args)  {                  System.out.println("Hello");          }  }

println  "Hello"

vs

Page 59: Groovy reactor grails realtime web   devoxx 2013

Optional

Page 60: Groovy reactor grails realtime web   devoxx 2013

Optional

Semicolons

Page 61: Groovy reactor grails realtime web   devoxx 2013

Optional

SemicolonsParentheses

Page 62: Groovy reactor grails realtime web   devoxx 2013

Optional

SemicolonsParentheses

return keyword

Page 63: Groovy reactor grails realtime web   devoxx 2013

Optional

SemicolonsParentheses

return keyword public keyword

Page 64: Groovy reactor grails realtime web   devoxx 2013

Optional

SemicolonsParentheses

return keyword public keyword

Typing!

Page 65: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!28

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Page 66: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!28

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Semicolons

Page 67: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

!29

Page 68: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

!30

Page 69: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner("Guillaume")  !System.out.println(greeter.greet("Marion"))

Parentheses

!30

Page 70: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!31

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 71: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!31

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                  return  owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

return keyword

Page 72: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!32

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                                owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 73: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!32

public  class  Greeter  {          private  String  owner  !        public  String  getOwner()  {                                owner          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner          }  !        public  String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

public keyword

Page 74: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!33

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 75: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!33

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !Greeter  greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

optional typing

Page 76: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!34

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

Page 77: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!34

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !System.out.println  greeter.greet("Marion")

handy println shortcut

Page 78: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!35

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Page 79: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!35

             class  Greeter  {          private  String  owner  !                      String  getOwner()  {                                owner          }  !                      void  setOwner(String  owner)  {                  this.owner  =  owner          }  !                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

verbose Java properties!

Page 80: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!36

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Page 81: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!36

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.setOwner  "Guillaume"  !                      println  greeter.greet("Marion")

Property notation

Page 82: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!37

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.owner  =    "Guillaume"  !                      println  greeter.greet("Marion")

Page 83: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!37

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter()  greeter.owner  =    "Guillaume"  !                      println  greeter.greet("Marion")

Named argumentconstructor

Page 84: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!38

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Page 85: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!38

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  "  +  name  +  ",  I  am  "  +  owner          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Interpolated strings!(aka GStrings)

Page 86: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!39

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  ${name},  I  am  ${owner}"          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Page 87: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!39

             class  Greeter  {                          String  owner  !!!!!!!!!                      String  greet(String  name)  {                                "Hello  ${name},  I  am  ${owner}"          }  }  !def          greeter  =  new  Greeter(owner:  "Guillaume")  !!                      println  greeter.greet("Marion")

Let’s reformat that messof whitespace!

Page 88: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!40

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

Page 89: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!40

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

public  class  Greeter  {          private  String  owner;  !        public  String  getOwner()  {                  return  owner;          }  !        public  void  setOwner(String  owner)  {                  this.owner  =  owner;          }  !        public  String  greet(String  name)  {                  return  "Hello  "  +  name  +  ",  I  am  "  +  owner;          }  }  !Greeter  greeter  =  new  Greeter();  greeter.setOwner("Guillaume");  !System.out.println(greeter.greet("Marion"));

Page 90: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Optional...

!40

class  Greeter  {          String  owner  !        String  greet(String  name)  {                "Hello  ${name},  I  am  ${owner}"          }  }  !def  greeter  =  new  Greeter(owner:  "Guillaume")  !println  greeter.greet("Marion")

Page 91: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Native syntax constructs

!41

//  closures  def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

//  lists  def  list  =  [1,  2,  3,  4,  5]  !

//  maps  def  map  =  [a:  1,  b:  2,  c:  3]  !

//  regular  expressions  def  regex  =  ~/.*foo.*/  !

//  ranges  def  range  128..255

Page 92: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — the basics

• Functions as first-class citizen of the language

!42

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Page 93: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — the basics

• Functions as first-class citizen of the language

!42

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Closureparameters

Page 94: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — the basics

• Functions as first-class citizen of the language

!42

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Assign a functioninto a variable

Closureparameters

Page 95: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — the basics

• Functions as first-class citizen of the language

!42

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Short form of:adder.call(‘a’, ‘b’)

Assign a functioninto a variable

Closureparameters

Page 96: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — the basics

• Functions as first-class citizen of the language

!42

def  adder  =  {  a,  b  -­‐>  a  +  b  }  !

assert  adder(1,  2)  ==  3  assert  adder('a',  'b')  ==  'ab'

Short form of:adder.call(‘a’, ‘b’)

Genericity withduck typing & operator

overloading

Assign a functioninto a variable

Closureparameters

Page 97: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — explicit type

!43

!

def  intAdder  =  {  int  a,  int  b  -­‐>  a  +  b  }

Page 98: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — explicit type

!43

!

def  intAdder  =  {  int  a,  int  b  -­‐>  a  +  b  }

Be explicit aboutthe types

Page 99: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — implicit parameter

!44

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Page 100: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — implicit parameter

!44

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Implicitparameter

Page 101: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — implicit parameter

!44

def  doubler  =  {  it  *  2  }  !

assert  doubler(3)  ==  6  assert  doubler('a')  ==  'aa'

Implicitparameter

Multiply also definedon strings

Page 102: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — variable arguments

!45

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

Page 103: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — variable arguments

!45

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

Variable number ofarguments

Page 104: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — variable arguments

!45

def  sum  =  {  ...  elements  -­‐>                                  elements.sum()  }  !

assert  sum(1,  2)  ==  3  assert  sum('a',  'b',  'c')  ==  'abc'

You can specify thetype: int...

Variable number ofarguments

Page 105: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — default values

!46

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Page 106: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — default values

!46

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Page 107: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — default values

!46

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Provided valuefor b

Page 108: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — default values

!46

def  mult  =  {  int  a,  int  b  =  10  -­‐>  a  *  b  }  !

assert  mult(2,  3)  ==  6  assert  mult(5)  ==  50

Default value

Provided valuefor b

Default valueused for b

Page 109: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — methods as functions

!47

def  logBase10  =  Math.&log10  def  printer  =  System.out.&println  !

assert  logBase10(10)  ==  1  printer  'abc'

Page 110: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — methods as functions

!47

def  logBase10  =  Math.&log10  def  printer  =  System.out.&println  !

assert  logBase10(10)  ==  1  printer  'abc'

Turn a method into a closure function

Page 111: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

Page 112: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

Page 113: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

Page 114: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

Page 115: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

Page 116: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

Page 117: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

Page 118: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

assert  names  ==  "ERINE,  MARION"

Page 119: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — map / filter / reduce

!48

@groovy.transform.Immutableclass  Person  {        String  name        int  age}

def  persons  =  [        new  Person('Guillaume',  36),        new  Person('Marion',  5),        new  Person('Erine',  1)]

def  names  =        persons.findAll  {  it.age  <  18  }                      .collect  {  it.name.toUpperCase()  }                      .sort()                      .join(',  ')

assert  names  ==  "ERINE,  MARION"

find/findAll, inject, collect, flatten, min/max, unique, reverse, collate, groupBy, any/every, head/tail/last,

count/countBy, combinations/permutations/subsequences/

transpose, withDefault/withLazyDefault

Page 120: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — resource handling

!49

new  File('bible.txt').withReader  {  r  -­‐>          new  File('out.txt').withWriter  {  w  -­‐>                  r.eachLine  {  line  -­‐>                          if  (line.contains('Groovy'))                                  w  <<  line.toUpperCase()                  }          }  }

Page 121: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — resource handling

!49

new  File('bible.txt').withReader  {  r  -­‐>          new  File('out.txt').withWriter  {  w  -­‐>                  r.eachLine  {  line  -­‐>                          if  (line.contains('Groovy'))                                  w  <<  line.toUpperCase()                  }          }  }

Take care of properly opening /closing resources

Page 122: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — custom control structures

!50

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Page 123: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — custom control structures

!50

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Closure as last argument

Page 124: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — custom control structures

!50

void  unless(boolean  cond,  Closure  c)  {          if  (!cond)  c()  }  !

unless  (10  <  9)  {          println  "less"  }

Closure as last argument

Equivalent to:unless(10<9, {...})

Page 125: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — custom control structures

!51

class  Reactor  {            void  on(Selector  s,  Closure  c)  {  …  }  }  …  reactor.on(  $(‘abc')  )  {  Event<String>  ev  -­‐>          …  }

Page 126: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — builders leverage closures

!52

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Page 127: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — builders leverage closures

!52

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Page 128: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — builders leverage closures

!52

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Closure blocksdelimiting the

structure

Page 129: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closures — builders leverage closures

!52

import  groovy.json.*  !

def  json  =  new  JsonBuilder()  json.person  {          name  'Guillaume'          age  36          daughters  'Marion',  'Erine'          address  {                  street  '1  Main  Street'                  zip  75001                  city  'Paris'          }  }

Hierarchical datarepresentation

Closure blocksdelimiting the

structure

{          "person":  {                  "name":  "Guillaume",                  "age":  36,                  "daughters":  [                          "Marion",                          "Erine"                  ],                  "address":  {                          "street":  "1  Main  Street",                          "zip":  75001,                          "city":  "Paris"                  }          }  }

Page 130: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Page 131: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Page 132: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Page 133: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Page 134: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Page 135: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

Implement a builder extendingBuilderSupport or FactoryBuilderSupport…

or roll your own!

Page 136: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Closure — your own builders

!53

GroovyEnvironment.create  {          environment  {                  defaultDispatcher  =  "test"  !

               dispatcher('test')  {                          type  =  DispatcherType.SYNCHRONOUS                  }          }  }

abstract  class  BuilderSupport  {          abstract  void  setParent(Object  parent,  Object  child)          abstract  Object  createNode(Object  name)          abstract  Object  createNode(Object  name,  Object  value)          abstract  Object  createNode(Object  name,  Map  attributes)          abstract  Object  createNode(Object  name,  Map  attributes,  Object  value)  }  

Implement a builder extendingBuilderSupport or FactoryBuilderSupport…

or roll your own!

Page 137: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

GPath expressions

• GPath expressions are like XPath but for an object graph

!54

import  groovy.json.*  !

def  url  =  "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !

def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !

assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

Page 138: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

GPath expressions

• GPath expressions are like XPath but for an object graph

!54

import  groovy.json.*  !

def  url  =  "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !

def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !

assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression

Page 139: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

GPath expressions

• GPath expressions are like XPath but for an object graph

!54

import  groovy.json.*  !

def  url  =  "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !

def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !

assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression Add find / findAllinto the mix

Page 140: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

GPath expressions

• GPath expressions are like XPath but for an object graph

!54

import  groovy.json.*  !

def  url  =  "https://api.github.com/repos/groovy/groovy-­‐core/commits"  !

def  commits  =  new  JsonSlurper().parseText(url.toURL().text)  !

assert  commits[0].commit.author.name  ==  'Cedric  Champeau'

GPath expression Add find / findAllinto the mix

No (un)marshalling!

Page 141: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lists

!55

def  list  =  ['a',  'b',  'c']  !

list  <<  'd'  assert  list.contains('d')  !

assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

Page 142: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lists

!55

def  list  =  ['a',  'b',  'c']  !

list  <<  'd'  assert  list.contains('d')  !

assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definition

Page 143: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lists

!55

def  list  =  ['a',  'b',  'c']  !

list  <<  'd'  assert  list.contains('d')  !

assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definition

Append an element(operator overloading)

Page 144: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lists

!55

def  list  =  ['a',  'b',  'c']  !

list  <<  'd'  assert  list.contains('d')  !

assert  list.findAll  {  it.startsWith  'a'  }.size()  ==  1  assert  list.collect  {  it.toUpperCase()  }                                                                ==  ['A',  'B',  'C',  'D']  assert  list.inject('')  {  a,  b  -­‐>  a  +  b  }  ==  'abcd'

List definition

Append an element(operator overloading)

Functional-style map /filter / reduce with

closures

Page 145: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Maps

!56

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Page 146: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Maps

!56

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Page 147: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Maps

!56

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Indexed access

Page 148: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Maps

!56

def  map  =  [name:  'Guillaume',  age:  36]  !

map.daughters  =  ['Marion',  'Erine']  !

assert  map['daughters'].contains('Marion')

Map definition

Indexed accessProperty notationaccess

Page 149: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Regular expressions

!57

def  pattern  =  ~/.*foo.*/  !

assert  "Alibaba"  ==~  /.*(ba){2}/  !

def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !

'75001  Paris'.find(/(\d{5})\s(\w+)/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

Page 150: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Regular expressions

!57

def  pattern  =  ~/.*foo.*/  !

assert  "Alibaba"  ==~  /.*(ba){2}/  !

def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !

'75001  Paris'.find(/(\d{5})\s(\w+)/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

Pattern

Page 151: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Regular expressions

!57

def  pattern  =  ~/.*foo.*/  !

assert  "Alibaba"  ==~  /.*(ba){2}/  !

def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !

'75001  Paris'.find(/(\d{5})\s(\w+)/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Page 152: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Regular expressions

!57

def  pattern  =  ~/.*foo.*/  !

assert  "Alibaba"  ==~  /.*(ba){2}/  !

def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !

'75001  Paris'.find(/(\d{5})\s(\w+)/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Find

Page 153: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Regular expressions

!57

def  pattern  =  ~/.*foo.*/  !

assert  "Alibaba"  ==~  /.*(ba){2}/  !

def  matcher  =  "Superman"  =~  /([A-­‐Z][a-­‐z]+)man/  assert  matcher[0][0]  ==  'Superman'  assert  matcher[0][1]  ==  'Super'  !

'75001  Paris'.find(/(\d{5})\s(\w+)/)  {  match,  zip,  town  -­‐>          println  "The  Zip  code  of  ${town}  is  ${zip}"  }

PatternMatch

Find

Nice way to decompose the matched regions

Page 154: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Ranges

!58

def  range  =  'a'..'z'  !

assert  range.contains('m')  assert  range.contains('z')  !

def  exclusive  =  1..<10  !

assert  !exclusive.contains(10)  !

def  reverse  =  10..0  !

assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Page 155: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Ranges

!58

def  range  =  'a'..'z'  !

assert  range.contains('m')  assert  range.contains('z')  !

def  exclusive  =  1..<10  !

assert  !exclusive.contains(10)  !

def  reverse  =  10..0  !

assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Page 156: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Ranges

!58

def  range  =  'a'..'z'  !

assert  range.contains('m')  assert  range.contains('z')  !

def  exclusive  =  1..<10  !

assert  !exclusive.contains(10)  !

def  reverse  =  10..0  !

assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Page 157: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Ranges

!58

def  range  =  'a'..'z'  !

assert  range.contains('m')  assert  range.contains('z')  !

def  exclusive  =  1..<10  !

assert  !exclusive.contains(10)  !

def  reverse  =  10..0  !

assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Reverse range

Page 158: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Ranges

!58

def  range  =  'a'..'z'  !

assert  range.contains('m')  assert  range.contains('z')  !

def  exclusive  =  1..<10  !

assert  !exclusive.contains(10)  !

def  reverse  =  10..0  !

assert  reverse[0]  ==  10  assert  reverse[-­‐1]  ==  0

Range

Excluded upper bound

Reverse range

Negative index countfrom the end

Page 159: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Strings, GStrings, multiline strings

!59

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !

assert  tmpl.toString().contains('Groovy')

Page 160: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Strings, GStrings, multiline strings

!59

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !

assert  tmpl.toString().contains('Groovy')

Plain java.lang.String

Page 161: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Strings, GStrings, multiline strings

!59

def  name  =  'Groovy'  def  tmpl  =  """          Dear  Mr  ${name},          You're  the  winner  of  the  lottery!          Yours  sincerly,          Dave  """  !

assert  tmpl.toString().contains('Groovy')

Plain java.lang.String

Multiline string withexpression interpolation

Page 162: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!60

System.out.println(  2.0  -­‐  1.1  );

Page 163: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!60

System.out.println(  2.0  -­‐  1.1  );

0.8999999999999999

Page 164: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!60

System.out.println(  2.0  -­‐  1.1  );

0.8999999999999999

Page 165: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!61

System.out.println(  3  /  2  );

Page 166: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!61

System.out.println(  3  /  2  );

1

Page 167: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Surprising numbers...

!61

System.out.println(  3  /  2  );

1

Page 168: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

BigDecimal by default!

!62

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

Page 169: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

BigDecimal by default!

!62

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

One of the reasons why micro-benchmarks sometimes showed

Groovy to be slow...

Page 170: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

BigDecimal by default!

!62

assert  2.0  -­‐  1.1  ==  0.9

assert  3  /  2  ==  1.5

One of the reasons why micro-benchmarks sometimes showed

Groovy to be slow...

But you can use doubles & floats forperformance, with ‘d’ or ‘f ’ suffixes

or with explicit type

Page 171: Groovy reactor grails realtime web   devoxx 2013
Page 172: Groovy reactor grails realtime web   devoxx 2013

Powerful switch /case on steroids

Page 173: Groovy reactor grails realtime web   devoxx 2013

Powerful switch /case on steroids

switch(obj)  {          case  123:                  "number  123";              break          case  "abc":              "string  abc";              break          case  String:            "is  a  string";            break          case  [1,  2,  3]:      "in  list";                    break          case  ~/.*o+.*/:      "regex  match";            break          case  {  it  <  3  }:    "closure  criteria";  break          default:                    "unknown"  }

Page 174: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments

!64

move  obj,  x:  3,  y:  4

Page 175: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments

!64

move  obj,  x:  3,  y:  4

Normal argument

Page 176: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments

!64

move  obj,  x:  3,  y:  4

Normal argument Named argument

Page 177: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments

!64

move  obj,  x:  3,  y:  4

Normal argument Named argument

Calls:move(Map m, Object)

Page 178: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Command chains

• Ability to chain method calls without parentheses and dots

!65

move  forward  at  3.km/h

Page 179: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Command chains

• Ability to chain method calls without parentheses and dots

!65

move  forward  at  3.km/h

Actually equivalent to:move(forward).at(3.getKm().div(h))

Page 180: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments & command chains

!66

check  that:  vodka  tastes  good

Page 181: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Named arguments & command chains

!66

check  that:  vodka  tastes  good

Will call:check(that: vodka).tastes(good)

Page 182: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!67

def  (a,  b)  =  ['A',  'B']  !

(a,  b)  =  [b,  a]  !

def  (int  i,  int  j)  =  [1,  2]  !

def  geocode(String  place)  {          return  [45.4,  2.3]  }  !

def  (la,  lo)  =  geocode("Paris")  !

assert  la  ==  45.4  &&  lo  ==  2.3

Page 183: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!67

def  (a,  b)  =  ['A',  'B']  !

(a,  b)  =  [b,  a]  !

def  (int  i,  int  j)  =  [1,  2]  !

def  geocode(String  place)  {          return  [45.4,  2.3]  }  !

def  (la,  lo)  =  geocode("Paris")  !

assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »

Page 184: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!67

def  (a,  b)  =  ['A',  'B']  !

(a,  b)  =  [b,  a]  !

def  (int  i,  int  j)  =  [1,  2]  !

def  geocode(String  place)  {          return  [45.4,  2.3]  }  !

def  (la,  lo)  =  geocode("Paris")  !

assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Page 185: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!67

def  (a,  b)  =  ['A',  'B']  !

(a,  b)  =  [b,  a]  !

def  (int  i,  int  j)  =  [1,  2]  !

def  geocode(String  place)  {          return  [45.4,  2.3]  }  !

def  (la,  lo)  =  geocode("Paris")  !

assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Methodreturning a list

Page 186: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!67

def  (a,  b)  =  ['A',  'B']  !

(a,  b)  =  [b,  a]  !

def  (int  i,  int  j)  =  [1,  2]  !

def  geocode(String  place)  {          return  [45.4,  2.3]  }  !

def  (la,  lo)  =  geocode("Paris")  !

assert  la  ==  45.4  &&  lo  ==  2.3

Classic « swap »With types

Methodreturning a list

Destructuring

Page 187: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!68

class  Point  {          double  x,  y  !

       double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !

def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !

assert  x  ==  48.3  &&  y  ==  3.5

Page 188: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!68

class  Point  {          double  x,  y  !

       double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !

def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !

assert  x  ==  48.3  &&  y  ==  3.5

Method signatureconvention: getAt(int)

Page 189: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Multiple assignment and destructuring

!68

class  Point  {          double  x,  y  !

       double  getAt(int  idx)  {                  if  (idx  ==  0)  x                  else  if  (idx  ==  1)  y                  else  throw  new  Exception("Wrong  index")          }  }  !

def  (x,  y)  =  new  Point(x:  48.3,  y:  3.5)  !

assert  x  ==  48.3  &&  y  ==  3.5

Method signatureconvention: getAt(int)

Transparent destructuring

Page 190: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!69

import  static  Unit.*  !enum  Unit  {      M(1),  KM(1000)  !    double  mult      Unit(double  mult)  {          this.mult  =  mult      }  }

Page 191: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!69

import  static  Unit.*  !enum  Unit  {      M(1),  KM(1000)  !    double  mult      Unit(double  mult)  {          this.mult  =  mult      }  }

import  groovy.transform.Immutable  import  static  Unit.*  !@Immutable  class  Distance  {      double  q      Unit  u  !    Distance  plus(Distance  d)  {          new  Distance(    q  *      u.mult  +                                    d.q  *  d.u.mult,  M)      }  }

Page 192: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!69

import  static  Unit.*  !enum  Unit  {      M(1),  KM(1000)  !    double  mult      Unit(double  mult)  {          this.mult  =  mult      }  }

import  groovy.transform.Immutable  import  static  Unit.*  !@Immutable  class  Distance  {      double  q      Unit  u  !    Distance  plus(Distance  d)  {          new  Distance(    q  *      u.mult  +                                    d.q  *  d.u.mult,  M)      }  }

import  static  Unit.*  !def  d10  =  new  Distance(10,  M)  def  d15  =  new  Distance(15,  M)  !def  d25  =  d10  +  d15  !assert  d25.q  ==  25  &&  d25.u  ==  M

Page 193: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!69

import  static  Unit.*  !enum  Unit  {      M(1),  KM(1000)  !    double  mult      Unit(double  mult)  {          this.mult  =  mult      }  }

import  groovy.transform.Immutable  import  static  Unit.*  !@Immutable  class  Distance  {      double  q      Unit  u  !    Distance  plus(Distance  d)  {          new  Distance(    q  *      u.mult  +                                    d.q  *  d.u.mult,  M)      }  }

import  static  Unit.*  !def  d10  =  new  Distance(10,  M)  def  d15  =  new  Distance(15,  M)  !def  d25  =  d10  +  d15  !assert  d25.q  ==  25  &&  d25.u  ==  M

Overload the ‘+’operator

Page 194: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!69

import  static  Unit.*  !enum  Unit  {      M(1),  KM(1000)  !    double  mult      Unit(double  mult)  {          this.mult  =  mult      }  }

import  groovy.transform.Immutable  import  static  Unit.*  !@Immutable  class  Distance  {      double  q      Unit  u  !    Distance  plus(Distance  d)  {          new  Distance(    q  *      u.mult  +                                    d.q  *  d.u.mult,  M)      }  }

import  static  Unit.*  !def  d10  =  new  Distance(10,  M)  def  d15  =  new  Distance(15,  M)  !def  d25  =  d10  +  d15  !assert  d25.q  ==  25  &&  d25.u  ==  M

Overload the ‘+’operator

Use ‘+’

Page 195: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!70

a  +  b      //  a.plus(b)  a  -­‐  b      //  a.minus(b)  a  *  b      //  a.multiply(b)  a  /  b      //  a.div(b)  a  %  b      //  a.modulo(b)  a  **  b    //  a.power(b)  a  |  b      //  a.or(b)  a  &  b      //  a.and(b)  a  ^  b      //  a.xor(b)  a[b]        //  a.getAt(b)  a  <<  b    //  a.leftShift(b)  a  >>  b    //  a.rightShift(b)  a  >>>  b  //  a.rightShiftUnsigned(b)  +a            //  a.unaryPlus()  -­‐a            //  a.unaryMinus()  ~a            //  a.bitwiseNegate()

Page 196: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Operator overloading

!70

a  +  b      //  a.plus(b)  a  -­‐  b      //  a.minus(b)  a  *  b      //  a.multiply(b)  a  /  b      //  a.div(b)  a  %  b      //  a.modulo(b)  a  **  b    //  a.power(b)  a  |  b      //  a.or(b)  a  &  b      //  a.and(b)  a  ^  b      //  a.xor(b)  a[b]        //  a.getAt(b)  a  <<  b    //  a.leftShift(b)  a  >>  b    //  a.rightShift(b)  a  >>>  b  //  a.rightShiftUnsigned(b)  +a            //  a.unaryPlus()  -­‐a            //  a.unaryMinus()  ~a            //  a.bitwiseNegate()

Operator overloading isjust a convention on

method names

Page 197: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Power asserts

!71

def  (a,  b,  c)  =  [20,  30,  40]  !

assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Page 198: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Power asserts

!71

def  (a,  b,  c)  =  [20,  30,  40]  !

assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Assertion  failed:    !

assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1                |  |    |  |        |        |        |  |  |      |                |  580|  29      58      false|  |  60    61                20      30                              |  40                                                            120  !

  at  script1.run(script1.groovy:3)

Page 199: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Power asserts

!71

def  (a,  b,  c)  =  [20,  30,  40]  !

assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1

Assertion  failed:    !

assert  a  *  (b  -­‐  1)  /  10  ==  3  *  c  /  2  +  1                |  |    |  |        |        |        |  |  |      |                |  580|  29      58      false|  |  60    61                20      30                              |  40                                                            120  !

  at  script1.run(script1.groovy:3)Invented by the Spock testing framework

Page 200: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

Page 201: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

With Java, you only get an NPE. No idea where it came from!

Page 202: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

With Java, you only get an NPE. No idea where it came from!

Groovy will say: Cannot get property ‘name’ on null object

Page 203: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

Page 204: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

o?.line?.item?.name

Page 205: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Null handling

!72

class  Order  {          LineItem  line  }  class  LineItem  {          int  quantity          Item  item  }  class  Item  {          String  name  }  !

def  o  =  new  Order(          line:  new  LineItem(                  quantity:  2,                  item:  null))  !

println  o.line.item.name

o?.line?.item?.name

Safe navigation:will just return

null; No NPE

Page 206: Groovy reactor grails realtime web   devoxx 2013
Page 207: Groovy reactor grails realtime web   devoxx 2013

The Truth,the Groovy Truth!

Page 208: Groovy reactor grails realtime web   devoxx 2013

The Truth,the Groovy Truth!

And what if I couldcustomize the truth?

Page 209: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

The Groovy Truth

!74

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

Page 210: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

The Groovy Truth

!74

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

null, empty, 0-sized, zeroare coerced to false

Page 211: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

The Groovy Truth

!74

assert  !(  null  )  assert  !(    ""    )  assert  !(    []    )  assert  !(      0    )

assert  new  Object()  assert  "string"  assert  [1,  2,  3]  assert  1234

null, empty, 0-sized, zeroare coerced to false

true otherwise

Page 212: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Customizing the truth!

!75

class  Account  {          String  name          boolean  disabled  =  false  !

       boolean  asBoolean()  {  !disabled  }  }  !

assert    new  Account(name:  'current')  assert  !new  Account(name:  'old',  disabled:  true)

Page 213: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Customizing the truth!

!75

class  Account  {          String  name          boolean  disabled  =  false  !

       boolean  asBoolean()  {  !disabled  }  }  !

assert    new  Account(name:  'current')  assert  !new  Account(name:  'old',  disabled:  true)

while (account), if (account), etc…

Page 214: Groovy reactor grails realtime web   devoxx 2013

?:

Page 215: Groovy reactor grails realtime web   devoxx 2013

The Elvisoperator!

?:

Page 216: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

Page 217: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

Page 218: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

Page 219: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  y

Page 220: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  y

Page 221: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  y

Page 222: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  y

Page 223: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y

Page 224: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y

Null, empty, zero-sized... false,

otherwise true!

Page 225: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y

Null, empty, zero-sized... false,

otherwise true!

Good old ternaryoperator

Page 226: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Towards Elvis...

!77

def  (x,  y)  =  ['MacBook  Pro',  'unknown']

if  (x  !=  null  &&  x.size()  >  0)  x  else  yif  (x  &&  x.size())  x  else  yif  (x)  x  else  yx  ?  x  :  yx  ?:  y

Null, empty, zero-sized... false,

otherwise true!

Good old ternaryoperatorElvis!

Page 227: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

AST transformations

• Abstract Syntax Tree – in memory representation of your program

before being compiled into bytecode !

• AST transformation == process of transforming the AST of a program before it’s compiled !

• Macro-like compiler hook!

!78

Page 228: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lots of AST transformations...

• Code generation

– @ToString, @EqualsAndHashCode, @Canonical, @TupleConstructor, @InheritConstructors, @Category, @IndexedProperty, @Lazy, @Newify

• Class design

– @Delegate, @Immutable, @Memoized, @Singleton, @Mixin

• Logging

– @Log, @Log4j, @Log4j2, @Slf4j

!79

Page 229: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lots of AST transformations...

• Safer scripting

– @ConditionalInterrupt, @ThreadInterrupt, @TimedInterupt

• Compiler directives

– @Field, @PackageScope, @AnnotationCollector, @DelegatesTo, @TypeChecked, @CompileStatic, @CompileDynamic

• Swing patterns

– @Bindable, @ListenerList, @Vetoable

!80

Page 230: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Lots of AST transformations...

• Dependencies handling

– @Grab, @GrabConfig, @GrabExclude, @GrabResolver

• Test assistance

– @NotYetImplemented, @ASTTest

!81

Page 231: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Immutability

• Implement immutability by the book !

– final class – tuple-style constructor – private final backing fields – defensive copying of collections – equals() and hashCode() methods – toString() method – ...

!82

Page 232: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Immutability

• Implement immutability by the book !

– final class – tuple-style constructor – private final backing fields – defensive copying of collections – equals() and hashCode() methods – toString() method – ...

!82

Can be error-prone towrite immutableclasses oneself !

Page 233: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Immutability

• A Person class with – a String name – an int age

!83

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Page 234: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Immutability

• A Person class with – a String name – an int age

!83

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Damnverbose

Java!

Page 235: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Immutability

• A Person class with – a String name – an int age

!83

public final class Person {! private final String name;! private final int age;!! public Person(String name, int age) {! this.name = name;! this.age = age;! }!! public String getName() {! return name;! }!! public int getAge() {! return age;! }!! public int hashCode() {! return age + 31 * name.hashCode();! }!! public boolean equals(Object other) {! if (other == null) {! return false;! }! if (this == other) {! return true;! }! if (Person.class != other.getClass()) {! return false;! }! Person otherPerson = (Person)other;! if (!name.equals(otherPerson.getName()) {! return false;! }! if (age != otherPerson.getAge()) {! return false;! }! return true;! }!! public String toString() {! return "Person(" + name + ", " + age + ")";! }!}!

Damnverbose

Java!

Although it’s also avalid Groovy

program!

Page 236: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

@Immutable

!84

import  groovy.transform.*  !

@Immutable  class  Person  {          String  name          int  age  }

Page 237: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Memoization

• Cache the result of previous invocations of closures or methods with the same set of argument values

!85

import  groovy.transform.*  !

@Memoized  long  fib(long  n)  {          if  (n  ==  0)  0          else  if  (n  ==  1)  1          else  fib(n  -­‐  1)  +  fib(n  -­‐  2)  }  !

println  fib(40)

Page 238: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Memoization

• Cache the result of previous invocations of closures or methods with the same set of argument values

!85

import  groovy.transform.*  !

@Memoized  long  fib(long  n)  {          if  (n  ==  0)  0          else  if  (n  ==  1)  1          else  fib(n  -­‐  1)  +  fib(n  -­‐  2)  }  !

println  fib(40)

Best applied toside-effect free

functions

Page 239: Groovy reactor grails realtime web   devoxx 2013
Page 240: Groovy reactor grails realtime web   devoxx 2013

Groovy allows youto be lazy

Page 241: Groovy reactor grails realtime web   devoxx 2013

Groovy allows youto be lazy

The compiler will dothe job for you

Page 242: Groovy reactor grails realtime web   devoxx 2013

Groovy allows youto be lazy

The compiler will dothe job for you

More concise, morereadable code

Page 243: Groovy reactor grails realtime web   devoxx 2013

Groovy allows youto be lazy

The compiler will dothe job for you

More concise, morereadable code

Less stuff to maintainand worry about

Page 244: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments !

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!87

Page 245: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments !

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!87

You can even extend thestatic type checker!

Page 246: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

@TypeChecked & @CompileStatic

• Static type checking with @TypeChecked, throws compilation errors on... – typos in method and variable names – incompatible return types – wrong type assignments !

• Supports fine-grained type inference – « Least Upper Bound » – « Flow typing »

!87

You can even extend thestatic type checker!

Type check DSLs ordynamic features!

Page 247: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

@TypeChecked & @CompileStatic

!

• What is type checked can also be compiled statically with @CompileStatic

!

– generate the same bytecode as javac !

– same performance as Java

!88

Page 248: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Static compilation performance

!89

Fibonacci Pi (π) quadrature

Binarytrees

Java 191 ms 97 ms 3.6 s

Staticcompilation 197 ms 101 ms 4.3 s

Primitive optimizations 360 ms 111 ms 23.7 s

No prim.optimizations 2590 ms 3220 ms 50.0 s1.

71.

82.

x

Page 249: Groovy reactor grails realtime web   devoxx 2013

Reactor

Part 2

Page 250: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Housekeeping

!

• Tweet questions during the presentation – @ProjectReactor

!

• Stop us anywhere if you have a question – There are no stupid questions, only stupid answers!

!91

Page 251: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

Page 252: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

REACTIVE

Page 253: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

EVENT DRIVEN

REACTIVE

Page 254: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

EVENT DRIVENAGILE

REACTIVE

Page 255: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

EVENT DRIVENAGILE

REACTIVE

SCALABLE

Page 256: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

EVENT DRIVENAGILE

REACTIVE

SCALABLE

AVAILABLE

Page 257: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!92

EVENT DRIVENAGILE

REACTIVE

SCALABLE

AVAILABLE

Page 258: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Reactive Architecture ?

!93

• A good description is available on: http://www.reactivemanifesto.org/ !

• Functional Programming helps as it is stimulus based by nature !

• Groovy is a perfect candidate: Closures and DSL are first class citizen !

• Reactor completes the picture by providing abstractions

Page 259: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Threading model matters

!94

• Context switching hurts performances

• Locking hurts performances

• Message passing hurts performances

• Blocking for a thread hurts performances

• Creating Threads needs memory

Page 260: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Dealing with performances

!95

• Actors solve the locking and context switching issues by becoming state boxes • One thread assigned per consumer • One thread will ever access a property

• Non Blocking Programming solves thread creation and waiting issues by delaying logic • Callback will be executed when possible (Lazy) • Reallocate the blocking time to process something else

Page 261: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — LMAX Disruptor and Ring Buffer

!96

• LMAX Disruptor deals with message passing issues • Based on a Ring Buffer structure • “Mechanical Sympathy” in Disruptor

!

• http://lmax-exchange.github.com/disruptor/files/Disruptor-1.0.pdf

• http://mechanitis.blogspot.co.uk/2011/06/dissecting-disruptor-whats-so-special.html

Page 262: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Disruptor performances

!97

Page 263: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Trisha’s pretty picture of Disruptor

!98

http://mechanitis.blogspot.co.uk/2011/07/dissecting-disruptor-writing-to-ring.html

Page 264: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — In love with Disruptor

!99

• Reactor best performances are derived from LMAX Disruptor !

• LMAX Disruptor can be considered as an evolution of the Actor Model: !

• Still avoid locking and deals with context switching • Producer/Consumer decoupled • Add Pipelining, Batching and more

Page 265: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — A foundation part of Spring IO

!100

Page 266: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What is it?

!

• Reactor is a distillation of other libraries and best-practices – Elements of other patterns and libraries

surface throughout Reactor's abstractions !

• http://stackoverflow.com/questions/16595393/akka-or-reactor

!101

Page 267: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What can I build with it?

• Reactor applications are reactive – Reactive Extensions in .NET – Netflix RxJava – Observer pattern

!

• Reactor applications route events based on a Selector – Like a routing topic, but can be any object – Regex, URI template, Class.isAssingableFrom, custom logic

!102

Page 268: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Landscape

!103

Page 269: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What does it look like?

!104

def  env  =  new  Environment()  !def  reactor  =  Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()  !reactor.on($('topic')){  Event<String>  ev  -­‐>                  println  "Hello  $ev.data"  }  !reactor.notify('topic',  Event.wrap('John  Doe'))

Page 270: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What does it look like?

!104

def  env  =  new  Environment()  !def  reactor  =  Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()  !reactor.on($('topic')){  Event<String>  ev  -­‐>                  println  "Hello  $ev.data"  }  !reactor.notify('topic',  Event.wrap('John  Doe'))

Create a reactor context

Page 271: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What does it look like?

!104

def  env  =  new  Environment()  !def  reactor  =  Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()  !reactor.on($('topic')){  Event<String>  ev  -­‐>                  println  "Hello  $ev.data"  }  !reactor.notify('topic',  Event.wrap('John  Doe'))

Create a reactor contextBuild a reactor

parameter

Page 272: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What does it look like?

!104

def  env  =  new  Environment()  !def  reactor  =  Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()  !reactor.on($('topic')){  Event<String>  ev  -­‐>                  println  "Hello  $ev.data"  }  !reactor.notify('topic',  Event.wrap('John  Doe'))

Create a reactor context

Trigger reactor ‘topic’ key

Build a reactorparameter

Page 273: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — What does it look like?

!104

def  env  =  new  Environment()  !def  reactor  =  Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()  !reactor.on($('topic')){  Event<String>  ev  -­‐>                  println  "Hello  $ev.data"  }  !reactor.notify('topic',  Event.wrap('John  Doe'))

Create a reactor context

Trigger reactor ‘topic’ key

React on ‘topic’ events

Build a reactorparameter

Page 274: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Selectors

• Selectors are the left-hand side of an equality comparison !

– A Selector can be created from any object using $(obj) (or the long form: Selectors.object(obj)) !

– A Selector can extract data from the matched key !

– Predicate<T> Selectors can be created to match on domain-specific criteria like header values

!105

Page 275: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

• A RegexSelector will match a String by executing the regex over it – R(“some.(.*)”) – Selectors.regex(“some.(.*)”)

!106

Page 276: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

!

• A RegexSelector will match a String by executing the regex over it !

– R(“some.(.*)”) !

– Selectors.regex(“some.(.*)”)

!107

Page 277: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

!108

reactor.on(R('some.(.+)')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers.get('group1')  }                                !

reactor.notify('some.topic',  Event.wrap('John  Doe'))

Page 278: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

!108

reactor.on(R('some.(.+)')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers.get('group1')  }                                !

reactor.notify('some.topic',  Event.wrap('John  Doe'))

Use a Regex Selector and capture group

Page 279: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

!108

reactor.on(R('some.(.+)')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers.get('group1')  }                                !

reactor.notify('some.topic',  Event.wrap('John  Doe'))

Use a Regex Selector and capture group

Notify a simple Stringkey to be matched

Page 280: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — RegexSelector

!108

reactor.on(R('some.(.+)')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers.get('group1')  }                                !

reactor.notify('some.topic',  Event.wrap('John  Doe'))

Use a Regex Selector and capture group

Notify a simple Stringkey to be matched

s will be ‘topic’

Page 281: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — UriSelector

• A UriTemplateSelector will match a String by extracting bits from a URI !

– U(“/some/{path}”) – Selectors.uri(“/some/{path}”)

!109

Page 282: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — UriSelector

!110

reactor.on(U('/some/**/{topic}')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers['topic']  }                !

reactor.notify('/some/to/topic',  Event.wrap('John  Doe'))

Page 283: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — UriSelector

!110

reactor.on(U('/some/**/{topic}')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers['topic']  }                !

reactor.notify('/some/to/topic',  Event.wrap('John  Doe'))

Use a URI Selector and capture fragment

Page 284: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — UriSelector

!110

reactor.on(U('/some/**/{topic}')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers['topic']  }                !

reactor.notify('/some/to/topic',  Event.wrap('John  Doe'))

Use a URI Selector and capture fragment

Notify a simple StringURI key to be matched

Page 285: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — UriSelector

!110

reactor.on(U('/some/**/{topic}')){  Event<String>  ev  -­‐>                  def  s  =  ev.headers['topic']  }                !

reactor.notify('/some/to/topic',  Event.wrap('John  Doe'))

Use a URI Selector and capture fragment

Notify a simple StringURI key to be matched

s will be ‘topic’

Page 286: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Consumer, Function, Supplier, Predicate

!111

public  interface  Consumer<T>  {                  void  accept(T  t);    }                !

public  interface  Supplier<T>  {                    T  get();      }  !

public  interface  Function<T,  V>  {                  V  apply(T  t);  }                !

public  abstract  class  Predicate<T>  {                    boolean  test(T  t);    }      

Page 287: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Consumer, Function, Supplier, Predicate

!111

public  interface  Consumer<T>  {                  void  accept(T  t);    }                !

public  interface  Supplier<T>  {                    T  get();      }  !

public  interface  Function<T,  V>  {                  V  apply(T  t);  }                !

public  abstract  class  Predicate<T>  {                    boolean  test(T  t);    }      

Generic Callback

Page 288: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Consumer, Function, Supplier, Predicate

!111

public  interface  Consumer<T>  {                  void  accept(T  t);    }                !

public  interface  Supplier<T>  {                    T  get();      }  !

public  interface  Function<T,  V>  {                  V  apply(T  t);  }                !

public  abstract  class  Predicate<T>  {                    boolean  test(T  t);    }      

Generic Callback

Object Factory

Page 289: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Consumer, Function, Supplier, Predicate

!111

public  interface  Consumer<T>  {                  void  accept(T  t);    }                !

public  interface  Supplier<T>  {                    T  get();      }  !

public  interface  Function<T,  V>  {                  V  apply(T  t);  }                !

public  abstract  class  Predicate<T>  {                    boolean  test(T  t);    }      

Generic Callback

Object Factory

Map Operation

Page 290: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Consumer, Function, Supplier, Predicate

!111

public  interface  Consumer<T>  {                  void  accept(T  t);    }                !

public  interface  Supplier<T>  {                    T  get();      }  !

public  interface  Function<T,  V>  {                  V  apply(T  t);  }                !

public  abstract  class  Predicate<T>  {                    boolean  test(T  t);    }      

Generic Callback

Object Factory

Map Operation

Filter Operation

Page 291: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Streams

● Streams allow for composition of functions on data − Callback++ − Netflix RxJava Observable, JDK 8 Stream

!112

Stream<String>  str  =  obtainStream()  !

str.map{  it.toUpperCase()  }                  .filter{  someCondition()  }                  .consume{  s  -­‐>  log.info  "consumed  string  $s"  }

Page 292: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Streams

● Streams allow for composition of functions on data − Callback++ − Netflix RxJava Observable, JDK 8 Stream

!112

Stream<String>  str  =  obtainStream()  !

str.map{  it.toUpperCase()  }                  .filter{  someCondition()  }                  .consume{  s  -­‐>  log.info  "consumed  string  $s"  }

Coerces to Function

Page 293: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Streams

● Streams allow for composition of functions on data − Callback++ − Netflix RxJava Observable, JDK 8 Stream

!112

Stream<String>  str  =  obtainStream()  !

str.map{  it.toUpperCase()  }                  .filter{  someCondition()  }                  .consume{  s  -­‐>  log.info  "consumed  string  $s"  }

Coerces to Predicate

Coerces to Function

Page 294: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Streams

● Streams allow for composition of functions on data − Callback++ − Netflix RxJava Observable, JDK 8 Stream

!112

Stream<String>  str  =  obtainStream()  !

str.map{  it.toUpperCase()  }                  .filter{  someCondition()  }                  .consume{  s  -­‐>  log.info  "consumed  string  $s"  }

Coerces to Predicate

Coerces to Function

Coerces to Consumer

Page 295: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Promises

● Promises supersedes Java Future for composition − Share common functions with Stream − Stateful: only 1 transition allowed

!113

Promise<String>  p  =  doLater()  !

String  s  =  p    .onSuccess  {  s  -­‐>  log.info  "consumed  string  $s"  }      .onFailure  {  t  -­‐>  log.error  "$t.message"  }        .onComplete  {  log.info  'complete'  }          .await(5,  SECONDS)  !

p.map{  it.toUpperCase()  }.consume{s  -­‐>  log.info  "UC:  $s"}  

Page 296: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Promises

● Promises supersedes Java Future for composition − Share common functions with Stream − Stateful: only 1 transition allowed

!113

Promise<String>  p  =  doLater()  !

String  s  =  p    .onSuccess  {  s  -­‐>  log.info  "consumed  string  $s"  }      .onFailure  {  t  -­‐>  log.error  "$t.message"  }        .onComplete  {  log.info  'complete'  }          .await(5,  SECONDS)  !

p.map{  it.toUpperCase()  }.consume{s  -­‐>  log.info  "UC:  $s"}  Block for a return value

Page 297: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Processor● Thin wrapper around Disruptor RingBuffer − Converts Disruptor API to Reactor API − Uber fast performance for #UberFastData

!114

Processor<Buffer>  proc  !

Operation<Buffer>  op  =  proc.prepare()  op.get().append(data).flip()  op.commit()  !

proc.batch(512)  {  it.append(data).flip()  }

Page 298: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Processor● Thin wrapper around Disruptor RingBuffer − Converts Disruptor API to Reactor API − Uber fast performance for #UberFastData

!114

Processor<Buffer>  proc  !

Operation<Buffer>  op  =  proc.prepare()  op.get().append(data).flip()  op.commit()  !

proc.batch(512)  {  it.append(data).flip()  }

Fill 512 slots and release once

Page 299: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!

● Helpers to integrate Reactor into ApplicationContext !

− @EnableReactor for easy configuration !

− Wiring annotated handlers

!115

Page 300: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!116

@Configuration  @EnableReactor  class  ReactorConfiguration  {  !

               @Bean  Reactor  input(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                !

               @Bean  Reactor  output(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                }

Page 301: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!116

@Configuration  @EnableReactor  class  ReactorConfiguration  {  !

               @Bean  Reactor  input(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                !

               @Bean  Reactor  output(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                }

Setup Environment

Page 302: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!117

@Component  class  SimpleHandler  {  !

   @Autowired  Reactor  reactor  !

   @Selector('test.topic')  void  onTestTopic(String  s)  {                      //  Handle  data      }  }

Page 303: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!117

@Component  class  SimpleHandler  {  !

   @Autowired  Reactor  reactor  !

   @Selector('test.topic')  void  onTestTopic(String  s)  {                      //  Handle  data      }  }

Inject reactor

Page 304: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

!117

@Component  class  SimpleHandler  {  !

   @Autowired  Reactor  reactor  !

   @Selector('test.topic')  void  onTestTopic(String  s)  {                      //  Handle  data      }  }

Inject reactor

Register consumer on @reactor

Page 305: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Spring

● DispatcherTaskExecutor − Not really a high-scale TaskExecutor − Used to get Spring components running in same thread as

Reactor Consumers ● ConversionService integration ● PromiseHandlerMethodReturnValueHandler (!) ● ReactorSubscribableChannel

!118

Page 306: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

● First class citizen language implementation − @CompileStatic ready − Prominent use of Closure as Consumers, Functions and

more − Operator overloading for elegant programming − Full Reactor system Builder

!119

Page 307: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Page 308: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStatic

Page 309: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStaticCoerce String to $(string)

Page 310: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStaticCoerce String to $(string)

Send data back usingreplyTo key header

Page 311: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStaticCoerce String to $(string)

Send data back usingreplyTo key header

Coerce data arg toEvent.wrap(data)

Page 312: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStaticCoerce String to $(string)

Send data back usingreplyTo key header

Coerce data arg toEvent.wrap(data)

Notify & Listen for replies

Page 313: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy

!120

@CompileStatic  def  welcome()  {                  reactor.on('greetings')  {  String  s  -­‐>                                  reply  "hello  $s"                                  reply  "how  are  you?"                  }  !                reactor.notify  'greetings',  'Jon'  !                reactor.send('greetings',  'Stephane')  {                                  println  it                                  cancel()                  }  }

Works with Groovy 2 CompileStaticCoerce String to $(string)

Send data back usingreplyTo key header

Coerce data arg toEvent.wrap(data)

Notify & Listen for repliesStop listening for replies

Page 314: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Page 315: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Build an async function

Page 316: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Build an async function

Pipe promise with theclosure transformation

Page 317: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Build an async function

Pipe promise with theclosure transformation

Filter the stream withthe right hand closure

predicate

Page 318: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Build an async function

Pipe promise with theclosure transformation

Filter the stream withthe right hand closure

predicate

Add callback after filter

Page 319: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Promises and Streams

!121

def  promise  =  Promises.task  {  longStuff();  1  }  get()                                                          !

def  transformation  =  promise  |  {  it  +  1  }  transformation.await()  ==  2            !

def  deferredStream  =  Streams.defer().get()              (deferredStream  &  {  it  >  2  })  <<  {  send(it)  }  !

deferredStream  <<  1  <<  2  <<  3  <<  4

Build an async function

Pipe promise with theclosure transformation

Filter the stream withthe right hand closure

predicate

Add callback after filter

Send data

Page 320: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Page 321: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Works with Groovy 2@CompileStatic

Page 322: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Works with Groovy 2@CompileStatic

Prepare an environmentbuilder

Page 323: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Works with Groovy 2@CompileStatic

Prepare an environmentbuilder

which dispatcher to usewhen creating a reactor

Page 324: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Works with Groovy 2@CompileStatic

Prepare an environmentbuilder

which dispatcher to usewhen creating a reactor

Build a standardDispatcher

Page 325: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!122

GroovyEnvironment.create  {                  environment  {                                  defaultDispatcher  =  "test"  !

                               dispatcher('test')  {                                                  type  =  DispatcherType.SYNCHRONOUS                                  }                  }                }.environment()

Works with Groovy 2@CompileStatic

Prepare an environmentbuilder

which dispatcher to usewhen creating a reactor

Build a standardDispatcherReturn a ready to

use Environment

Page 326: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!123

GroovyEnvironment.create  {                  reactor('test1')  {                                  stream('test')  {                                                                                  consume  {  ev-­‐>                                                                                                                                                        log.info  ev.data                                                                                                                                  }                                                                              }                                                                                                                                              on('test')  {                                                  reply  it                                  }                  }                                                                                                            }  

Page 327: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!123

GroovyEnvironment.create  {                  reactor('test1')  {                                  stream('test')  {                                                                                  consume  {  ev-­‐>                                                                                                                                                        log.info  ev.data                                                                                                                                  }                                                                              }                                                                                                                                              on('test')  {                                                  reply  it                                  }                  }                                                                                                            }  

Build a named Reactor

Page 328: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!123

GroovyEnvironment.create  {                  reactor('test1')  {                                  stream('test')  {                                                                                  consume  {  ev-­‐>                                                                                                                                                        log.info  ev.data                                                                                                                                  }                                                                              }                                                                                                                                              on('test')  {                                                  reply  it                                  }                  }                                                                                                            }  

Build a named Reactor

Intercept the datastream coming by the

selector $(‘test’)

Page 329: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!123

GroovyEnvironment.create  {                  reactor('test1')  {                                  stream('test')  {                                                                                  consume  {  ev-­‐>                                                                                                                                                        log.info  ev.data                                                                                                                                  }                                                                              }                                                                                                                                              on('test')  {                                                  reply  it                                  }                  }                                                                                                            }  

Build a named Reactor

Intercept the datastream coming by the

selector $(‘test’)

Stream builder

Page 330: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Groovy Environment

!123

GroovyEnvironment.create  {                  reactor('test1')  {                                  stream('test')  {                                                                                  consume  {  ev-­‐>                                                                                                                                                        log.info  ev.data                                                                                                                                  }                                                                              }                                                                                                                                              on('test')  {                                                  reply  it                                  }                  }                                                                                                            }  

Build a named Reactor

Intercept the datastream coming by the

selector $(‘test’)

Stream builder

Attach inline consumers

Page 331: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Extensive Awesomeness

● TCP Client/Server, with a Netty 4 implementation

● Buffer tools

● Sequencer support, for event ordering

● Work Queue support with OoB Java Chronicle implementation

● Log Appender

!124

Page 332: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Roadmap

● 1.1 discussions − StateBox: a safe tool for concurrent writes

− Better Timer management

− Spring XD, Spring 4

− Exploring Distributed Reactors

● Voice your interest and your use-case here

!125

Page 333: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Roadmap

● 1.1 discussions − HTTP helpers

− Improved RingBuffer API for multithreaded consumers

(slow consumers)

− More Groovy Love: Buffer, TCP, Processor, Time,

!126

Page 334: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Uber Community Contribs

● Meltdown: A Clojure binding by @michaelklishin & @ifesdjeen

− https://github.com/clojurewerkz/meltdown

!127

Page 335: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Reactor — Uber Community Contribs

!

● High Performance Couchbase ingestion by @daschl − http://nitschinger.at/Using-the-Reactor-Processor-for-High-

Performance-TCP !

● Benefits of using Reactor Processor, TCP and Batching facilities

!128

Page 336: Groovy reactor grails realtime web   devoxx 2013

Demo

Page 337: Groovy reactor grails realtime web   devoxx 2013

Grails

Part 3

Page 338: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Age of Asynchronous

Fact #1: – HTTP request thread is critical path – Do the barely necessary for fast rendering – If it’s long*, do it in a separate thread

!131

Page 339: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Age of Asynchronous

Fact #2: – Creating new Threads needs caution – Context switching hurts performances – Concurrent programming is tricky*

!132

Page 340: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Age of Asynchronous

Fact #3: – Burden on your application is never constant – Scaling Up is a good start… – …And Scaling Out is only next

!133

Page 341: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Age of Asynchronous

So I have to use background threads ? But using them might lead to issues and headaches ? And what if I really need to scale out ?

!134

Page 342: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactive Programming Recap

• Adding a level of indirection : Driving your application with Events

• Laziness is key • Scale up/out by tweaking dispatching

!135

Page 343: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!136

Events Bus

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Application

Page 344: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!136

Events Bus

Publish/Subscribe

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Application

Page 345: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!136

Events Bus

Publish/Subscribe

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Application

Page 346: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!136

Events Bus

Publish/Subscribe

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Service Consumer

Application

Page 347: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!137

Events Bus

Publish/Subscribe

App

App

App

App

App

Cloud

Page 348: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Big Picture

!137

Events Bus

Publish/Subscribe

App

App

App

App

App

Cloud

Page 349: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb !138

Introducing  GRAILS-­‐EVENTS  plugin

BOOM!

worse slide ever™

Page 350: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Origins : Platform-Core plugin

• An initiative to provide modern tools for grails development

!

• Among them: the Events API

• An abstraction used in a few Grails applications today to decouple logic from producers

!

• grails-events can be considered as Platform Core Events API 2.0

!139

Page 351: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Why a new plugin ?

• New features. And quite a few. – Streaming data, Selectors, Queue

!

• Based on a new solid foundation – Reactor – Where Platform-core Events best ideas have leaked

!

• Semantic changes – But relatively straightforward migration path

!140

Page 352: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Why a new plugin ?

• Lightweight, only focused on events

!

• Ready to be embedded in a future Grails version

• Complete the asynchronous story

• Could enable runtime plugin deployment

!141

Page 353: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — So what Grails Events is about

• Grails Apps and Plugins can use Events to:

– Listen for plugins/app events

– Start simple with in-memory eventing (#uberfastdata)

– Do Asynchronous calls (default)

– Increase in flexibility if required

!142

Page 354: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Installing Grails Events

• It’s a binary plugin (!) • Requires Grails 2.2+

!143

repositories  {          //...                mavenRepo  "http://repo.springsource.org/libs-­‐snapshot"          mavenRepo  "http://repo.grails.org/grails/libs-­‐snapshots-­‐local/"  }  !

dependencies  {          compile  'org.grails.plugins:events:1.0.0.BUILD-­‐SNAPSHOT'  }  

Page 355: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Semantics: Consumer

• A Consumer:

– Accepts an Event

– Is registered in a Service or Events artifact, or by calling on()

– Can be thread safe

• Depending on the dispatcher type

• Assuming the consumer is not registered more than once

!144

Page 356: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Semantics: Selector

• A Selector:

– Matches an event key

– Is paired with a consumer during its registration

– Any bean method can be transformed into consumer with @Selector

!145

Page 357: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Semantics: Reactor

• A Reactor: – Is a dedicated Consumer Registry – Has an assigned Dispatcher – Uses a specific Event Router

!

• Usually, if the Dispatcher doesn’t need to be adapted, reuse the default reactor grailsReactor

!146

Page 358: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Event Driven CQRS

!147

GORM

http://martinfowler.com/bliki/CQRS.html

DBPostProcessingService

SaveService

Page 359: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Event Driven CQRS

!147

GORM

http://martinfowler.com/bliki/CQRS.html

DBPostProcessingService

SaveService

Consume afterInsert events

Page 360: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Event Driven CQRS

!147

GORM

http://martinfowler.com/bliki/CQRS.html

DBPostProcessingService

SaveService

Consume afterInsert events

Save a GORM entity

Page 361: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Event Driven CQRS

!147

GORM

http://martinfowler.com/bliki/CQRS.html

DBPostProcessingService

SaveService

Consume afterInsert events

Save a GORM entity

Insert Record

Page 362: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Event Driven CQRS

!147

GORM

http://martinfowler.com/bliki/CQRS.html

DBPostProcessingService

SaveService

Consume afterInsert events

Save a GORM entity

Insert RecordTrigger afterInsert

event

Page 363: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Modular Architecture

!148

Notification Plugin

RequestServiceMain Application

NotificationService

Page 364: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Modular Architecture

!148

Notification Plugin

RequestServiceMain Application

NotificationService

Trigger ‘request’ event

Page 365: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Modular Architecture

!148

Notification Plugin

RequestServiceMain Application

NotificationService

Trigger ‘request’ event

Create a decoupled module

Page 366: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Modular Architecture

!148

Notification Plugin

RequestServiceMain Application

NotificationService

Trigger ‘request’ event

Create a decoupled module Consume ‘request’ events

Page 367: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Modular Architecture

!148

Notification Plugin

RequestServiceMain Application

NotificationService

Trigger ‘request’ event

Create a decoupled module Consume ‘request’ events

Core application untouched

Page 368: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Background Processing

!149

REST service

Grails Controller HTTP Request

Request Service

Page 369: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Background Processing

!149

REST service

Grails Controller HTTP Request

Return immediately

Request Service

Page 370: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Background Processing

!149

REST service

Grails Controller HTTP Request

Return immediately

Request Service

Trigger ‘request’event (async)

Page 371: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : Background Processing

!149

REST service

Grails Controller HTTP Request

Return immediately

Request Service

Trigger ‘request’event (async)

Long REST call

Page 372: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Sending Events (grails-platform-core)

!150

def  user  =  new  User(params).save()  !

event('mailRegistration',  user)      //event('mailRegistration',  user).waitFor()      //event  topic:'mailRegistration',  data:user      //event  topic:'mailRegistration',  data:user,  fork:false      render(view:'sendingRegistrationMail')

Page 373: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Sending Events (grails-events)

!151

def  user  =  new  User(params).save()  !

event('mailRegistration',  user)                event('mailRegistration',  user)  {          if(it  ==  ‘end')  {                  cancel()          }  }      !

//  event  key:  'mailRegistration',  data:  user  !

render(view:  'sendingRegistrationMail')

Page 374: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Sending Events (grails-events)

!151

def  user  =  new  User(params).save()  !

event('mailRegistration',  user)                event('mailRegistration',  user)  {          if(it  ==  ‘end')  {                  cancel()          }  }      !

//  event  key:  'mailRegistration',  data:  user  !

render(view:  'sendingRegistrationMail')

Non blocking call totrigger app consumers

Page 375: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Sending Events (grails-events)

!151

def  user  =  new  User(params).save()  !

event('mailRegistration',  user)                event('mailRegistration',  user)  {          if(it  ==  ‘end')  {                  cancel()          }  }      !

//  event  key:  'mailRegistration',  data:  user  !

render(view:  'sendingRegistrationMail')

Non blocking call totrigger app consumers

Do things on each reply

Page 376: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Sending Events (grails-events)

!151

def  user  =  new  User(params).save()  !

event('mailRegistration',  user)                event('mailRegistration',  user)  {          if(it  ==  ‘end')  {                  cancel()          }  }      !

//  event  key:  'mailRegistration',  data:  user  !

render(view:  'sendingRegistrationMail')

Non blocking call totrigger app consumers

Do things on each reply

Map notation

Page 377: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Consuming Events (grails-platform-core)

!152

class  UserService{          @grails.events.Listener          def  mailRegistration(User  user)  {                  sendMail  {                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }  !        @grails.events.Listener(topic=  "mailRegistration")          def  mailRegistration2(org.grails.plugin.platform.events.EventMessage  msg)  {                  sendMail{                        to  msg.data.mail                        subject  "Confirmation"                        html  g.render(template:  "userMailConfirmation")                  }          }  }

Page 378: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

class  UserService{              @reactor.spring.annotation.Selector          def  mailRegistration(User  user){                  sendMail{                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:  "userMailConfirmation")                  }          }  !        @reactor.spring.annotation.Selector("mailRegistration")          def  mailRegistration2(reactor.event.Event  msg){                  sendMail{                          to  msg.data.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }  }

Grails — Consuming Events (grails-events)

!153

Page 379: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

class  UserService{              @reactor.spring.annotation.Selector          def  mailRegistration(User  user){                  sendMail{                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:  "userMailConfirmation")                  }          }  !        @reactor.spring.annotation.Selector("mailRegistration")          def  mailRegistration2(reactor.event.Event  msg){                  sendMail{                          to  msg.data.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }  }

Grails — Consuming Events (grails-events)

!153

Consume onSelector(method name)

Page 380: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

class  UserService{              @reactor.spring.annotation.Selector          def  mailRegistration(User  user){                  sendMail{                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:  "userMailConfirmation")                  }          }  !        @reactor.spring.annotation.Selector("mailRegistration")          def  mailRegistration2(reactor.event.Event  msg){                  sendMail{                          to  msg.data.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }  }

Grails — Consuming Events (grails-events)

!153

Consume onSelector(method name)

Consume on thisspecific topic

Page 381: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

class  UserService{              @reactor.spring.annotation.Selector          def  mailRegistration(User  user){                  sendMail{                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:  "userMailConfirmation")                  }          }  !        @reactor.spring.annotation.Selector("mailRegistration")          def  mailRegistration2(reactor.event.Event  msg){                  sendMail{                          to  msg.data.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }  }

Grails — Consuming Events (grails-events)

!153

Consume onSelector(method name)

Consume on thisspecific topic

Event typed signatureto inspect enveloppe

(‘headers…)

Page 382: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

includes  =  ['default']  !doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                  !                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                                                                                          }                                                      }                                                                                                                                                                                                }

Grails — A new Artifact conf/XxxxEvents

!154

Page 383: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

includes  =  ['default']  !doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                  !                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                                                                                          }                                                      }                                                                                                                                                                                                }

Grails — A new Artifact conf/XxxxEvents

!154

Merge with DefaultsEvents

Page 384: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

includes  =  ['default']  !doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                  !                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                                                                                          }                                                      }                                                                                                                                                                                                }

Grails — A new Artifact conf/XxxxEvents

!154

Merge with DefaultsEvents

Build a GroovyEnvironment

Page 385: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

includes  =  ['default']  !doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                  !                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                                                                                          }                                                      }                                                                                                                                                                                                }

Grails — A new Artifact conf/XxxxEvents

!154

Merge with DefaultsEvents

Build a GroovyEnvironment

Reactor Groovy Builders

Page 386: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

includes  =  ['default']  !doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                  !                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                                                                                          }                                                      }                                                                                                                                                                                                }

Grails — A new Artifact conf/XxxxEvents

!154

Merge with DefaultsEvents

Build a GroovyEnvironment

Reactor Groovy Builders

Grails extension: accept GORM events

Page 387: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Selectors

• Listen for arbitrary keys • import static reactor.event.selector.Selectors.*

!155

on(T(SpecificClassType))  {                  reply  it                                  }                                                                                                !

event(new  SpecificClassType(),  'data')                                                                  !

!

on(uri(‘/some/{captureIt}'))  {                                                                                                                        reply  it.headers.captureIt  }                                                                                                                                                                                                                !

event('/some/hourray',  'data')        

Page 388: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Selectors

• Listen for arbitrary keys • import static reactor.event.selector.Selectors.*

!155

on(T(SpecificClassType))  {                  reply  it                                  }                                                                                                !

event(new  SpecificClassType(),  'data')                                                                  !

!

on(uri(‘/some/{captureIt}'))  {                                                                                                                        reply  it.headers.captureIt  }                                                                                                                                                                                                                !

event('/some/hourray',  'data')        

Listen for SpecificClassType

Page 389: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Selectors

• Listen for arbitrary keys • import static reactor.event.selector.Selectors.*

!155

on(T(SpecificClassType))  {                  reply  it                                  }                                                                                                !

event(new  SpecificClassType(),  'data')                                                                  !

!

on(uri(‘/some/{captureIt}'))  {                                                                                                                        reply  it.headers.captureIt  }                                                                                                                                                                                                                !

event('/some/hourray',  'data')        

Listen for an URI

Listen for SpecificClassType

Page 390: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Selectors

• Listen for arbitrary keys • import static reactor.event.selector.Selectors.*

!155

on(T(SpecificClassType))  {                  reply  it                                  }                                                                                                !

event(new  SpecificClassType(),  'data')                                                                  !

!

on(uri(‘/some/{captureIt}'))  {                                                                                                                        reply  it.headers.captureIt  }                                                                                                                                                                                                                !

event('/some/hourray',  'data')        

Listen for an URI

Listen for SpecificClassType

Send using right key type

Page 391: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Selectors

• Listen for arbitrary keys • import static reactor.event.selector.Selectors.*

!155

on(T(SpecificClassType))  {                  reply  it                                  }                                                                                                !

event(new  SpecificClassType(),  'data')                                                                  !

!

on(uri(‘/some/{captureIt}'))  {                                                                                                                        reply  it.headers.captureIt  }                                                                                                                                                                                                                !

event('/some/hourray',  'data')        

Listen for an URI

Listen for SpecificClassType

Send using right key type

Send using matching URI

Page 392: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

Page 393: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

Build a Stream to capture any reply

Page 394: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

If a consumer fails

Build a Stream to capture any reply

Page 395: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

If a consumer fails

Build a Stream to capture any reply

$(‘test’) consumers may reply

Page 396: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

If a consumer fails

Build a Stream to capture any reply

$(‘test’) consumers may reply

Transform result

Page 397: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Stream API

• Reactive Extensions programming style • Avoid callback hell

!156

withStream  {          event(key:  'test',  data:  1)  }.when(Exception,  {          log.info  "exception:$it"  }).map  {          callExternalService(it)  }.consume('clientKey',  reactor('browser'))

If a consumer fails

Build a Stream to capture any reply

$(‘test’) consumers may reply

Transform result

Reroute to key ‘clientKey’on Reactor ‘browser’

Page 398: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness: Promise API

• Grails 2.3 Promises become a Reactor Promises • Benefits from Dispatcher overriding • Powerful once Combined with Consumers

!157

dispatcher(ReactorPromise.PromiseDispatcher)  {          type  =  DispatcherType.RingBuffer          backlog  =  512  }

Page 399: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness: Promise API

• Grails 2.3 Promises become a Reactor Promises • Benefits from Dispatcher overriding • Powerful once Combined with Consumers

!157

dispatcher(ReactorPromise.PromiseDispatcher)  {          type  =  DispatcherType.RingBuffer          backlog  =  512  }

task  {          def  res  =  longProcessing()          render  res  }

Page 400: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Routing

• During event dispatching, consumers list is selected • Publish Subscribe is the default • Possible to assign different routing strategy

!158

reactor('test1')  {          routingStrategy  'round-­‐robin'          on('test')  {                  reply  '1'          }                        on('test')  {                  reply  '2'          }                }

Page 401: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Reactor awesomeness : Routing

• During event dispatching, consumers list is selected • Publish Subscribe is the default • Possible to assign different routing strategy

!158

reactor('test1')  {          routingStrategy  'round-­‐robin'          on('test')  {                  reply  '1'          }                        on('test')  {                  reply  '2'          }                }

Will reply 1, 2, 1, 2, 1, 2…

Page 402: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Extensibility

!

• Main extension points: – Dispatcher, Selector, Registry, EventRouter, Consumer

!

• Metadata in Reactor Events DSL: – ext(‘someExtension’, [ ‘doStuff ’: true ])

!159

Page 403: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — GORM events

• GORM is now an extension – Using ext(‘gorm’, true) on any candidate reactor – Applicable Selectors: simple topic form (beforeInsert...) – A boolean reply is evaluated as a cancel directive

!160

reactor('someGormReactor'){          dispatcher  =  new  SynchronousDispatcher()          ext  'gorm',  true  }    

Page 404: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — GORM events

• GORM is now an extension – Using ext(‘gorm’, true) on any candidate reactor – Applicable Selectors: simple topic form (beforeInsert...) – A boolean reply is evaluated as a cancel directive

!160

reactor('someGormReactor'){          dispatcher  =  new  SynchronousDispatcher()          ext  'gorm',  true  }     @Selector(reactor  =  'someGormReactor')  

@ReplyTo  boolean  beforeValidate(Book  b){          false  }

Page 405: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb !161

GRAILS-­‐EVENTS-­‐PUSH  pluginEventing over HTTP!

Page 406: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : “Realtime” web

!162

Browser

ResponseService

Grails Controller RequestService

Page 407: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : “Realtime” web

!162

Browser

ResponseService

Grails Controller

Return immediately

RequestService

Page 408: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : “Realtime” web

!162

Browser

ResponseService

Grails Controller

Return immediately

RequestService

Trigger async event

Page 409: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : “Realtime” web

!162

Browser

ResponseService

Grails Controller

Return immediately

RequestService

Trigger async event

Reply a new event

Page 410: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Pattern Examples : “Realtime” web

!162

Browser

ResponseService

Grails Controller

Return immediately

RequestService

Trigger async event

Reply a new eventPush reply to browser: Websocket, SSE, long-polling…

Page 411: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — An elegant solution to browser push

• Powered by Atmosphere 2

• Automatically picks an adapted protocol:

– WebSockets, ServerSideEvent, Streaming, Polling…

• Consumer bridges for server-to-client push

• Reactor bridge for client-to-server push

• Javascript library

!163

Page 412: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Installing Grails Events Push

1. Install Grails Events plugin 2. Install Grails Events Push plugin

!164

grails.servlet.version  =  "3.0"  grails.tomcat.nio  =  true  !grails.project.dependency.resolution  =  {          repositories  {          //...                  mavenRepo  "https://oss.sonatype.org/content/repositories/snapshots"          }                                            dependencies  {                                  //...                                                    compile  'org.grails.plugins:events:1.0.0.BUILD-­‐SNAPSHOT'          }                                                                                            plugins  {                                                                                            //...                                                                                                    runtime  ":jquery:1.10.2"                                                                                                                                        runtime  ":events-­‐push:1.0.0.BUILD-­‐SNAPSHOT"                                                }  }

Page 413: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Installing Grails Events Push

1. Install Grails Events plugin 2. Install Grails Events Push plugin

!164

grails.servlet.version  =  "3.0"  grails.tomcat.nio  =  true  !grails.project.dependency.resolution  =  {          repositories  {          //...                  mavenRepo  "https://oss.sonatype.org/content/repositories/snapshots"          }                                            dependencies  {                                  //...                                                    compile  'org.grails.plugins:events:1.0.0.BUILD-­‐SNAPSHOT'          }                                                                                            plugins  {                                                                                            //...                                                                                                    runtime  ":jquery:1.10.2"                                                                                                                                        runtime  ":events-­‐push:1.0.0.BUILD-­‐SNAPSHOT"                                                }  }

Use a “long-connection” friendlytomcat configuration

Page 414: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 1 - Handshake

!165

Browser EventsPushHandler

Page 415: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 1 - Handshake

!165

Browser EventsPushHandler

Adapt Protocol and Opennew persistent connection

Page 416: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 2 - Register

!166

Browser Reactor(s)

Page 417: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 2 - Register

!166

Browser Reactor(s)

Bridge a Client Consumer with aremote Reactor Consumer

Page 418: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 2 - Register

!166

Browser Reactor(s)

Bridge a Client Consumer with aremote Reactor Consumer

Consumer registered on all Reactor with‘browser’ extension enabled

Page 419: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 3 - Notify

!167

Browser ‘browser’ Reactor RequestService

Page 420: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 3 - Notify

!167

Browser ‘browser’ Reactor

Notify any key

RequestService

Page 421: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 3 - Notify

!167

Browser ‘browser’ Reactor

Notify any key

RequestService

RequestService consumes on matchingSelector within the ‘browser’ Reactor

Page 422: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 4 - Consume

!168

Browser Reactor(s) ResponseService

Page 423: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 4 - Consume

!168

Browser Reactor(s)

Push event (WS, SSE…)

ResponseService

Page 424: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — grails-events-push Lifecycle 4 - Consume

!168

Browser Reactor(s)

Push event (WS, SSE…)

ResponseService

Notify ‘browser’ enabledReactor and match key

Page 425: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Simple Browsers bridges

!169

includes  =  'push'  !doWithReactor  =  {          reactor('browser')  {                  ext  'browser',  [                          'control',                          'move',                          'fire',                          'leave'                  ]          }          reactor(‘grailsReactor')  {                  ext  'browser',  ['sleepBrowser']  !                stream(‘sleepBrowser')  {                          filter  {                                    it.data  ==  'no'                          }                  }          }  }

Page 426: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Simple Browsers bridges

!169

includes  =  'push'  !doWithReactor  =  {          reactor('browser')  {                  ext  'browser',  [                          'control',                          'move',                          'fire',                          'leave'                  ]          }          reactor(‘grailsReactor')  {                  ext  'browser',  ['sleepBrowser']  !                stream(‘sleepBrowser')  {                          filter  {                                    it.data  ==  'no'                          }                  }          }  }

Bridge browser to these reactorconsumers $(‘control),…

Page 427: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Simple Browsers bridges

!169

includes  =  'push'  !doWithReactor  =  {          reactor('browser')  {                  ext  'browser',  [                          'control',                          'move',                          'fire',                          'leave'                  ]          }          reactor(‘grailsReactor')  {                  ext  'browser',  ['sleepBrowser']  !                stream(‘sleepBrowser')  {                          filter  {                                    it.data  ==  'no'                          }                  }          }  }

Bridge browser to these reactorconsumers $(‘control),…

Conventional name tooverride ‘browser’ reactor

Page 428: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Simple Browsers bridges

!169

includes  =  'push'  !doWithReactor  =  {          reactor('browser')  {                  ext  'browser',  [                          'control',                          'move',                          'fire',                          'leave'                  ]          }          reactor(‘grailsReactor')  {                  ext  'browser',  ['sleepBrowser']  !                stream(‘sleepBrowser')  {                          filter  {                                    it.data  ==  'no'                          }                  }          }  }

Bridge browser to these reactorconsumers $(‘control),…

Conventional name tooverride ‘browser’ reactor

Bridge browser to this reactorconsumer $(‘sleepBrowser)

Page 429: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Simple Browsers bridges

!169

includes  =  'push'  !doWithReactor  =  {          reactor('browser')  {                  ext  'browser',  [                          'control',                          'move',                          'fire',                          'leave'                  ]          }          reactor(‘grailsReactor')  {                  ext  'browser',  ['sleepBrowser']  !                stream(‘sleepBrowser')  {                          filter  {                                    it.data  ==  'no'                          }                  }          }  }

Bridge browser to these reactorconsumers $(‘control),…

Conventional name tooverride ‘browser’ reactor

Bridge browser to this reactorconsumer $(‘sleepBrowser)

Prevent data ‘no’ to bedispatched to browser bridges

Page 430: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — React on server side events

!170

Page 431: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — React on server side events

!170

Inject grailsEvents.js (requires resources plugin)

Page 432: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — React on server side events

!170

Inject grailsEvents.js (requires resources plugin)

Create a connectionbetween the browser and

the current Grails app

Page 433: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — React on server side events

!170

Inject grailsEvents.js (requires resources plugin)

Create a connectionbetween the browser and

the current Grails app

Listen for $(‘afterInsert’) events

Page 434: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Page 435: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Include PushEvents (configure areactor for events from Browsers)

Page 436: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Include PushEvents (configure areactor for events from Browsers)

Listen on GORM events

Page 437: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Include PushEvents (configure areactor for events from Browsers)

Listen on GORM events

Extension to bridgeBrowsers consumers to

Server-side pair

Page 438: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Include PushEvents (configure areactor for events from Browsers)

Listen on GORM events

Extension to bridgeBrowsers consumers to

Server-side pair

Override “From Browsers” reactorand bridge consumers

Page 439: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Generating Advanced Browsers bridges

!171

includes  =  ['push']  !doWithReactor  =  {          reactor(‘grailsReactor')  {                  ext  'gorm',  true                            ext  'browser',  [                                                                                                                                                                                                                    'test':  true,                      'afterInsert':  [                                        browserFilter:  {m,  r  -­‐>  true  }                                                                                                                                                                              ],                                                                                                                                                                                                                                                      (R("sampleBro-­‐.*"))  :  true,                  ]                                                                                                                                                                                                  }                                                                                                                                                                                                                                                                                                                      reactor(EventsPushConstants.FROM_BROWSERS)  {                  ext  'browser',  [R("sampleBro-­‐.*")]                                                                                                                                                }                                                                                                            }  

Include PushEvents (configure areactor for events from Browsers)

Listen on GORM events

Extension to bridgeBrowsers consumers to

Server-side pair

Override “From Browsers” reactorand bridge consumersEvents are only routed, from

Browsers to bridged Browsers

Page 440: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — The Bad Stuff

• events-si : Events API on top of Spring Integration – Not here (just) yet

!

• events-vertx : Abandoned experiment – Working around Distributed Reactor

!

• Stream DSL could be optimized – Reducing the number of objects

!172

Page 441: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Roadmap

• events: – Document, especially for Migration from Platform Core – Stick with latest awesome features from Reactor • Still Many API to expose: Processors, Buffer, TCP, Queues,

Sequencer… !

• events-push -> events-atmosphere : – Add support for replyTo – extract to standalone module : reactor-atmosphere

!173

Page 442: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb@glaforge — @smaldini / #DV13-rtweb

Grails — Roadmap

• events-sockjs: – Involves Reactor work here

!

• events-si: – Supports new events plugin

!

• events-xx: – The plugin where you are the hero

!174

Page 443: Groovy reactor grails realtime web   devoxx 2013

Demo

Page 444: Groovy reactor grails realtime web   devoxx 2013

Summary

Part 4

Page 445: Groovy reactor grails realtime web   devoxx 2013

@glaforge — @smaldini / #DV13-rtweb

Groovy, Reactor, Grails and the realtime web

• Embrace modern reactive architectures with Groovy, Reactor and Grails!

• Groovy is a versatile language, that enables development of concise and functional oriented applications

• Reactor fuels your asynchronous and reactive applications with its ultra fast dispatching engine and non-blocking model.

• Grails supports your today's and tomorrow's web app design, tooled with the right plugins you are prepared for responsive and interactive applications

!177