SlideShare a Scribd company logo
© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Grails and the “Real-time web”
By Stephane Maldini
Prologue
Solving a basic problem
“Your valuable users don’t like waiting”
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
The Age of Asynchronous
Fact #2:
– Creating new Threads needs caution
– Context switching hurts performances
– Concurrent programming is tricky*
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
Dilemma
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 ?
Reactive programming
• Adding a level of indirection :
Driving your application with Events
• Laziness is key
• Scale up/out by tweaking dispatching
The big picture
Events
Bus
Point to point
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Application
The big picture
Events
Bus
Publish/Subscribe
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Application
The big picture
Events
Bus
Publish/Subscribe
App
App
App
App
App
Cloud
Remember Platform-Core ? Remember Events ?
Introducing GRAILS-EVENTS
BOOM!
worse slide ever™
The new deal
• New features. And quite a few.
– Streaming data, Selectors, Queue
• Based on a solid foundation – Reactor
– Where Platform-core Events best ideas have leaked
• Semantic changes
– But relatively easy migration path
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
– Do Asynchronous calls (default)
– Increase in flexibility if required
Installing Grails Events
• It‟s a binary plugin (!)
• Requires Grails 2.2+
Reactor big picture
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
Semantics: Selector
• A Selector:
– Matches an event key
– Is paired with a consumer during its registration
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
Platform Core: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//blocking call :
//event('mailRegistration', user).waitFor()
//can also be written like that
//event topic:'mailRegistration', data:user
//and if you need to reuse the current thread
//event topic:'mailRegistration', data:user, fork:false
render(view:'sendingRegistrationMail’)
Events: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//Do things on each reply :
//event('mailRegistration', user){
if(it == ‘end’){
cancel()
}
}
//can also be written like that
//event key:'mailRegistration', data:user
render(view:'sendingRegistrationMail')
Platform Core Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Listener(topic='test')
@grails.events.Listener
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an EventMessage to get more information on this particular event)
@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")
}
}
}
Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Selector(‘test')
@reactor.spring.annotation.Selector
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an Event to get more information on this particular event)
@reactor.spring.annotation.Selector("mailRegistration")
def mailRegistration2(reactor.event.Event msg){
sendMail{
to msg.data.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
}
Events : A new Artifact
Reactor awesomeness : Selectors
• Listen for arbitrary keys
• import static reactor.event.selector.Selectors.*
Reactor awesomeness : Stream API
• Reactive Extensions programming style
• Avoid callback hell
Reactor awesomeness : Promise API
• Grails 2.3 Promises become a Reactor Promises
• Benefits from Dispatcher overriding
• Powerful once Combined with Consumers
Reactor awesomeness : Routing
• During event dispatching, consumers list is selected
• Publish Subscribe is the default
• Possible to assign different routing strategy
Reactor awesomeness : Extensibility
• Main extension points:
– Dispatcher, Selector, Registry, EventRouter
• Metadata in Reactor Events DSL:
– ext(„someExtension‟, [ „doStuff‟ : true ])
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
GRAILS-EVENTS-PUSH
Eventing over HTTP
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
Installing Grails Events Push
1. Install Grails Events plugin
2. Install Grails Events Push plugin
Generating Simple Browsers bridges
React on server side events
Generating Advanced Browsers bridges
DEMO
Burn some idols for the demo gods please
Epilogue
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
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 :
– More robust subscription mech
– Update atmosphere client
– Add support for replyTo
– Add support for binary
Roadmap
• events-sockjs:
– Involves Reactor work here
• events-si:
– Supports new events plugin
• events-xx:
– The plugin where you are the hero
Learn More. Stay Connected.
• Follow-up
– Reactor repository: http://github.com/reactor/
– Mail: @smaldini / smaldini@gopivotal.com
• Talk to us on Twitter: @springcentral
• Find Session replays on YouTube: spring.io/video

More Related Content

Ss2gx

  • 1. © 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission. Grails and the “Real-time web” By Stephane Maldini
  • 3. Solving a basic problem “Your valuable users don’t like waiting”
  • 4. 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
  • 5. The Age of Asynchronous Fact #2: – Creating new Threads needs caution – Context switching hurts performances – Concurrent programming is tricky*
  • 6. 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
  • 7. Dilemma 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 ?
  • 8. Reactive programming • Adding a level of indirection : Driving your application with Events • Laziness is key • Scale up/out by tweaking dispatching
  • 9. The big picture Events Bus Point to point Service Consumer Service Consumer Service Consumer Service Consumer Service Consumer Application
  • 12. Remember Platform-Core ? Remember Events ?
  • 14. The new deal • New features. And quite a few. – Streaming data, Selectors, Queue • Based on a solid foundation – Reactor – Where Platform-core Events best ideas have leaked • Semantic changes – But relatively easy migration path
  • 15. 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 – Do Asynchronous calls (default) – Increase in flexibility if required
  • 16. Installing Grails Events • It‟s a binary plugin (!) • Requires Grails 2.2+
  • 18. 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
  • 19. Semantics: Selector • A Selector: – Matches an event key – Is paired with a consumer during its registration
  • 20. 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
  • 21. Platform Core: Sending Events def user = new User(params).save() //non-blocking call, will trigger application listeners for this topic event('mailRegistration', user) //blocking call : //event('mailRegistration', user).waitFor() //can also be written like that //event topic:'mailRegistration', data:user //and if you need to reuse the current thread //event topic:'mailRegistration', data:user, fork:false render(view:'sendingRegistrationMail’)
  • 22. Events: Sending Events def user = new User(params).save() //non-blocking call, will trigger application listeners for this topic event('mailRegistration', user) //Do things on each reply : //event('mailRegistration', user){ if(it == ‘end’){ cancel() } } //can also be written like that //event key:'mailRegistration', data:user render(view:'sendingRegistrationMail')
  • 23. Platform Core Events : Consuming Events class UserService{ //use method name 'mailRegistration' as topic name //can also use custom topic name using topic arg: @Listener(topic='test') @grails.events.Listener def mailRegistration(User user){ sendMail{ to user.mail subject "Confirmation" html g.render(template:"userMailConfirmation") } } //Can also receive an EventMessage to get more information on this particular event) @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") } } }
  • 24. Events : Consuming Events class UserService{ //use method name 'mailRegistration' as topic name //can also use custom topic name using topic arg: @Selector(‘test') @reactor.spring.annotation.Selector def mailRegistration(User user){ sendMail{ to user.mail subject "Confirmation" html g.render(template:"userMailConfirmation") } } //Can also receive an Event to get more information on this particular event) @reactor.spring.annotation.Selector("mailRegistration") def mailRegistration2(reactor.event.Event msg){ sendMail{ to msg.data.mail subject "Confirmation" html g.render(template:"userMailConfirmation") } } }
  • 25. Events : A new Artifact
  • 26. Reactor awesomeness : Selectors • Listen for arbitrary keys • import static reactor.event.selector.Selectors.*
  • 27. Reactor awesomeness : Stream API • Reactive Extensions programming style • Avoid callback hell
  • 28. Reactor awesomeness : Promise API • Grails 2.3 Promises become a Reactor Promises • Benefits from Dispatcher overriding • Powerful once Combined with Consumers
  • 29. Reactor awesomeness : Routing • During event dispatching, consumers list is selected • Publish Subscribe is the default • Possible to assign different routing strategy
  • 30. Reactor awesomeness : Extensibility • Main extension points: – Dispatcher, Selector, Registry, EventRouter • Metadata in Reactor Events DSL: – ext(„someExtension‟, [ „doStuff‟ : true ])
  • 31. 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
  • 33. 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
  • 34. Installing Grails Events Push 1. Install Grails Events plugin 2. Install Grails Events Push plugin
  • 36. React on server side events
  • 38. DEMO Burn some idols for the demo gods please
  • 40. 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
  • 41. 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 : – More robust subscription mech – Update atmosphere client – Add support for replyTo – Add support for binary
  • 42. Roadmap • events-sockjs: – Involves Reactor work here • events-si: – Supports new events plugin • events-xx: – The plugin where you are the hero
  • 43. Learn More. Stay Connected. • Follow-up – Reactor repository: http://github.com/reactor/ – Mail: @smaldini / smaldini@gopivotal.com • Talk to us on Twitter: @springcentral • Find Session replays on YouTube: spring.io/video

Editor's Notes

  • #5: Challenge long* Long is sometimes ok or a necessary evil.
  • #6: Synchronized block