This document discusses using reactive event-driven architecture with Grails applications. It introduces the Platform-Core plugin, which provides an events API for publishing and listening to events within Grails applications and across plugins. It also discusses several other plugins that integrate Platform-Core events with technologies like Spring Integration, Atmosphere for client-side events, and Vert.x for clustering and scalability. The document provides code examples of publishing and handling events and also discusses configuring events using a DSL.
1. Reactive Grails
Event-driven architecture made easy
Stephane Maldini – Consultant @ SpringSource/VMware*
* Changes may apply in the next couple of months
3. In Memory use cases
• Loosely coupled
– Plugin oriented
– Testable handlers without mocking
• Declarative logic
– Workflow by contract
• Threading scalability
– Scale to multicores without digging too deep in your code
3
4. In Cloud use cases
• Sharing workload
– And on demand !
– One machine can handle the task: using a shared work queue
• Synchronizing
– All machines need to work: Cache invalidation, indexing...
• Communicating with Service API
– Layering at machine level instead of software level
4
5. The big picture
Application
Service Listener
Service Listener Point to point
Events
Bus Service Listener
Service Listener
Service Listener
5
6. The big picture
Application
Service Listener
Service Listener Publish/Subscribe
Events
Bus Service Listener
Service Listener
Service Listener
6
7. The big picture
Cloud
App
App Publish/Subscribe
Events
Bus App
App
App
7
9. Grails on bus : current plugins
• Spring Events
– Use ApplicationContext to propagate ApplicationEvents
– Code boilerplate
• Routing (Apache Camel)
– Super flexible
– Simple but powerful
– Routing DSL but not so Grailsy
• Falcone Utils
– Fully integrated with Grails
– Not maintained
9
10. Platform-Core
• This plugin purpose is to provide key features for todays
application development and plugin oriented architecture
• Provided by Marc Palmer and your guest
• Initiated mid 2012, currently version 1.0.RC2:
– Nearly complete API stabilization
– Integrated with grails development
• Fully extensible, API driven design
10
11. Platform-Core: API
Configuration
Navigation
Security
Injection
Events
11
13. Platform-Core : Events
• Grails Apps and Plugins can use Platform-Core/Events to:
– Listen for plugins/app events
– Avoid topic name conflicts using namespacing support
– Do in-memory eventing
– Do Asynchronous calls (default)
– Increase in flexibility if required
13
14. Platform-Core : Events
• Add this to your BuildConfig RIGHT NOW :
– compile :platform-core:1.0.RC2
14
15. Events : Sending Events
class
UserController{
def
registration(){
def
user
=
new
User(params).save()
if(user){
//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')
}else{
render(view:'errorRegistration')
}
}
}
15
16. Events : Listening 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")
}
}
}
16
17. Events : DSL
events
=
{
//prevents
any
events
in
gorm
namespace
'*'
namespace:'gorm',
disabled:true
//filters
any
events
on
'testTopic'
where
data
<=
2
testTopic
filter:{it
>
2}
//filters
any
events
on
'testTopic2'
where
data
is
not
a
TestTopic
class
type
testTopic2
filter:TestTopic
//filters
any
events
on
'testTopicX'
using
boolean
method
from
service
testTopicX
filter:ctx.myService.&someMethod
//only
if
using
events-‐push
plugin,
allows
client-‐side
listener
on
this
topic
testTopic3
browser:true
//Default
Error
Handling,
Global
Reply
Handling,
timeout
and
fork
testTopicD
onError:{},
onReply:{},
timeout:1000l
testTopicD2
fork:false
}
17
18. Platform-Core : Events, more!
• Listen to GORM events
– using the same API
• Reply handlers
– Return values from your listeners to pass them back to caller
• Errors handler
– Listen for any exceptions
18
20. Events : Plugins
• Leveraging and enriching the Platform-core API
• May update events registering/dispatching engine
• Combine them and achieve kool kombos
• Currently 3 plugins in development
– Events-SI : Spring Integration backed events
– Events-Push : Events to the browser using Atmosphere
– Vertx : Vertx integration and platform-core backed events
20
21. grails-events-si
• Change in-memory default mechanism:
– @Listener now generates a channel + endpoint
– event methods now send through Spring Integration gateway
– This channel can be overriden using the naming convention
– Super flexible, connect to the world
21
23. grails-events-si + Groovy DSL
• Based on the excellent module from David Turanski:
– https://github.com/SpringSource/spring-integration-dsl-groovy
• Integration with Events plugin registry and publishing
– Easy to add queuing behavior
– Easy to transform Pub/Sub to Point 2 Point
– Additional declarative logic (filtering, system integration etc)
• Still possible to fallback to standard BeanBuilder
23
25. How to send through RabbitMQ in minutes
With this in BuildConfig :
runtime ":rabbitmq:1.0.0 "
runtime ":events-si:1.0.M4-SNAPSHOT"
beans = { !
xmlns siAmqp:
'http://www.springframework.org/schema/integration/amqp' !
!
siAmqp.'publish-subscribe-channel'(id: 'gorm://afterInsert') !
!
siAmqp.'publish-subscribe-channel'(id: 'gorm://afterDelete') !
!
siAmqp.'publish-subscribe-channel'(id: 'gorm://afterUpdate') !
!
}!
25
26. grails-events-push
• And if you want to listen for events... in Javascript
– Like Socket.IO or Vertx
– Like a free bird
– But not so free, prevent from listening everything
– But which damn protocol using ??
26
31. grails-vertx
• No hands clustering
– Using Vert.x Hazelcast support
• Super scalable events processor
– Mom’ said Event loop is darn good at handling high concurrent
load
• Deploying features as verticles
– WIN for hot reloading plugins/services
31
34. Roadmaps
• Platform-Core
– Work Queue / Point to Point eventing
– Response Streaming
• Events-SI
– Overridable listeners with Queue channels
• Events-Push
– More on filtering
– ... per request security (with PlatformCore security)
34
35. Roadmaps
• Some more Vertx love:
– Better integration
– Specific DSL to manage verticles
– SockJS support
– request dispatching
• Vertx Back / Grails Front
• Vertx Front / Grails Back ?
– Rename it Testx
35