SlideShare a Scribd company logo
Lightbend Lagom
Microservices “Just Right”
Mirco Dotta
@mircodotta
Scala Days NYC - May 10, 2016
Lagom - [lah-gome]
Adequate, sufficient, just right
Agenda
â—Ź Why Lagom?
â—Ź Lagom dive in
â—‹ Development Environment
â—‹ Service API
â—‹ Persistence API
â—Ź Running in Production
Why Lagom?
â—Ź Opinionated
â—Ź Developer experience matters!
â—‹ No brittle script to run your services
â—‹ Inter-service communication just works
â—‹ Services are automatically reloaded on code change
â—Ź Takes you through to production deployment
â—Ź sbt build tool (developer experience)
â—Ź Play 2.5
â—Ź Akka 2.4 (clustering, streams, persistence)
â—Ź Cassandra (default data store)
â—Ź Jackson (JSON serialization)
â—Ź Guice (DI)
â—Ź Architectural Concepts: immutability, Event Sourcing/CQRS,
circuit breakers
Under the hood
Enough slides,
Demo time
Anatomy of a Lagom project
â—Ź sbt build
â—Ź Scala 2.11 and JDK8
â—Ź Each service definition is split into two sbt projects:
â—‹ api
â—‹ Implementation
Service API
Service definition
trait HelloService extends Service {
override def descriptor(): Descriptor = {
named("helloservice").`with`(
namedCall("/hello", sayHello _)
)
}
def sayHello(): ServiceCall[String, String]
}
// this source is placed in your api project
ServiceCall explained
â—Ź ServiceCall can be invoked when consuming a service:
â—‹ Request: type of incoming request message (e.g. String)
â—‹ Response: type of outgoing response message (e.g. String)
â—Ź JSON is the default serialization format for request/response messages
â—Ź There are two kinds of request/response messages:
â—‹ Strict
â—‹ Streamed
trait ServiceCall[Request, Response] {
def invoke(request: Request): Future[Response]
}
Strict Messages
Strict messages are fully buffered into memory
override def descriptor(): Descriptor = {
named("friendservice").`with`(
pathCall("/users/:userId/friends", addFriend _)
)
}
def addFriend(userId: String): ServiceCall[FriendId, NotUsed]
Streamed Messages
override def descriptor(): Descriptor = {
named("clock").`with`(
pathCall("/tick/:interval", tick())
)
}
def tick(): ServiceCall[String, Source[String, _]]
â—Ź A streamed message is of type Source (an Akka streams API)
â—Ź It allows asynchronous streaming and handling of messages
â—Ź Lagom will select transport protocol (currently WebSockets)
Remember the Service definition?
trait HelloService extends Service {
override def descriptor(): Descriptor = {
named("helloservice").`with`(
namedCall(sayHello _)
)
}
def sayHello(): ServiceCall[String, String]
}
// this source is placed in your api project
Here is the Service implementation
class HelloServiceImpl extends HelloService {
override def sayHello(): ServiceCall[String, String] {
name => Future.successful(s"Hello, $name!")
}
}
// this source is placed in your implementation project
Inter-service communication
class MyServiceImpl @Inject()(helloService: HelloService)
(implicit ec: ExecutionContext) extends MyService {
override def sayHelloLagom(): ServiceCall[NotUsed, String] = unused => {
val response = helloService.sayHello().invoke("Lagom")
response.map(answer => s"Hello service said: $answer")
}
}
Persistence API
Principles
â—Ź Each service owns its data
â—‹ Only the service has direct access to the DB
â—Ź We advocate the use of Event Sourcing (ES) and CQRS
○ ES: Capture all state’s changes as events
â—‹ CQRS: separate models for write and read
Benefits of Event Sourcing/CQRS
â—Ź Allows you to time travel
â—Ź Audit log
â—Ź Future business opportunities
â—Ź No need for ORM
â—Ź No database migration script, ever
â—Ź Performance & Scalability
â—Ź Testability & Debuggability
Event Sourcing: Write Side
â—Ź Create your own Command and Event classes
â—Ź Subclass PersistentEntity
â—‹ Define Command and Event handlers
â—‹ Can be accessed from anywhere in the cluster
â—‹ (corresponds to an Aggregate Root in DDD)
Event Sourcing: Example
Create the Command classes
sealed trait FriendCommand extends Jsonable
case class AddFriend(friendUserId: String) extends
PersistentEntity.ReplyType[Done] with FriendCommand
// more friend commands
Event Sourcing: Example cont’d
Create the Event classes
sealed trait FriendEvent extends Jsonable
case class FriendAdded(userId: String, friendId: String,
timestamp: Instant = Instant.now()) extends FriendEvent
// more friend events
Event Sourcing: Example cont’d
class FriendEntity extends
PersistentEntity[FriendCommand, FriendEvent, FriendState] {
def initialBehavior(snapshotState: Optional[FriendState]): Behavior =
// TODO: define command and event handlers
}
Create a subclass of PersistentEntity
Event Sourcing: Example cont’d
val b: Behavior = newBehaviorBuilder(/*...*/)
b.setCommandHandler(classOf[AddFriend],
(cmd: AddFriend, ctx: CommandContext[Done]) => state.user match {
case None =>
ctx.invalidCommand(s"User ${entityId} is not created")
ctx.done()
case Some(user) =>
ctx.thenPersist(FriendAdded(user.userId, cmd.friendUserId),
(evt: FriendAdded) => ctx.reply(Done))
})
b.setEventHandler(classOf[FriendAdded],
(evt: FriendAdded) => state.addFriend(evt.friendId))
Event Sourcing: Example cont’d
No side-effects in the event handler!
Event Sourcing: Example cont’d
Create the State class
case class FriendState(user: Option[User]) extends Jsonable {
def addFriend(friendUserId: String): FriendState = user match {
case None => throw new IllegalStateException(
"friend can't be added before user is created")
case Some(user) =>
val newFriends = user.friends :+ friendUserId
FriendState(Some(user.copy(friends = newFriends)))
}
}
class FriendServiceImpl @Inject() (persistentEntities: PersistentEntityRegistry)
(implicit ec: ExecutionContext) extends FriendService {
// at service startup we must register the needed entities
persistentEntities.register(classOf[FriendEntity])
def addFriend(userId: String): ServiceCall[FriendId, NotUsed] = request => {
val ref = persistentEntities.refFor(classOf[FriendEntity], userId)
ref.ask[Done, AddFriend](AddFriend(request.friendId))
}
// ...
}
Event Sourcing: Example cont’d
Event Sourcing: Read Side
â—Ź Tightly integrated with Cassandra
â—Ź Create the query tables:
â—‹ Subclass CassandraReadSideProcessor
â—‹ Consumes events produced by the PersistentEntity and
updates tables in Cassandra optimized for queries
â—Ź Retrieving data: Cassandra Query Language
â—‹ e.g., SELECT id, title FROM postsummary
Running in Production
â—Ź sbt-native packager is used to produce zip, MSI, RPM, Docker
â—Ź Lightbend ConductR* (our container orchestration tool)
â—Ź Lightbend Reactive Platform*
â—‹ Split Brain Resolver (for Akka cluster)
â—‹ Lightbend Monitoring
*Requires a Lightbend subscription (ConductR is free to use during development)
Current[Lagom]
â—Ź Current version is 1.0.0-M2
â—‹ 1.0 soon
â—Ź Java API, but no Scala API yet
â—‹ We are working on the Scala API
â—‹ But using Scala with the Java API works well! https:
//github.com/dotta/activator-lagom-scala-chirper
Future[Lagom]
â—Ź Maven support
â—Ź Message broker integration
â—Ź Scala API
â—Ź Support for other cluster orchestration tools
â—Ź Support for writing integration tests
â—Ź Swagger integration
â—‹ Which also removes binary coupling!
Next: Seq[Step]
â—Ź Try Lagom yourself
â—‹ https://lightbend.com/lagom
â—Ź Using Scala with Lagom
â—‹ https://github.com/dotta/activator-lagom-scala-chirper
â—Ź Lagom on Github
â—‹ https://github.com/lagom/lagom
● Read Jonas Bonér's free book Reactive Services Architecture
â—‹ https://lightbend.com/reactive-microservices-architecture
â—Ź Great presentation by Greg Young on why you should use ES
â—‹ https://www.youtube.com/watch?v=JHGkaShoyNs
Thank you for listening!
@mircodotta
@lagom
override def descriptor(): Descriptor = {
named("friendservice").`with`(
namedCall("/users", createUser _),
pathCall("/users/:id", getUser _),
restCall(Method.POST, "/users/:userId/friends", addFriend _)
)
}
def createUser(): ServiceCall[User, NotUsed]
def getUser(id: String): ServiceCall[NotUsed, User]
def addFriend(userId: String): ServiceCall[FriendId, NotUsed]
Different kinds of service call descriptors

More Related Content

What's hot (20)

ODP
Introduction to Scala Macros
Knoldus Inc.
 
ZIP
Above the clouds: introducing Akka
nartamonov
 
PPTX
Akka Actor presentation
Gene Chang
 
PPTX
Developing distributed applications with Akka and Akka Cluster
Konstantin Tsykulenko
 
PPTX
JVM languages "flame wars"
Gal Marder
 
ODP
Akka Persistence | Event Sourcing
Knoldus Inc.
 
PDF
Type-safe front-end development with Scala
takezoe
 
PDF
Scala, Akka, and Play: An Introduction on Heroku
Havoc Pennington
 
PDF
Understanding Akka Streams, Back Pressure, and Asynchronous Architectures
Lightbend
 
PPTX
Spark real world use cases and optimizations
Gal Marder
 
PPTX
Multi-threading in the modern era: Vertx Akka and Quasar
Gal Marder
 
PDF
Scala Frameworks for Web Application 2016
takezoe
 
PPTX
Implementing Micro Services Tasks (service discovery, load balancing etc.) - ...
Gal Marder
 
KEY
The Why and How of Scala at Twitter
Alex Payne
 
PDF
Node.js Enterprise Middleware
Behrad Zari
 
PPTX
Dive into spark2
Gal Marder
 
ODP
Introduction to Apache Kafka- Part 2
Knoldus Inc.
 
PPTX
What’s expected in Spring 5
Gal Marder
 
PDF
Introduction to akka actors with java 8
Johan Andrén
 
PPTX
What’s expected in Java 9
Gal Marder
 
Introduction to Scala Macros
Knoldus Inc.
 
Above the clouds: introducing Akka
nartamonov
 
Akka Actor presentation
Gene Chang
 
Developing distributed applications with Akka and Akka Cluster
Konstantin Tsykulenko
 
JVM languages "flame wars"
Gal Marder
 
Akka Persistence | Event Sourcing
Knoldus Inc.
 
Type-safe front-end development with Scala
takezoe
 
Scala, Akka, and Play: An Introduction on Heroku
Havoc Pennington
 
Understanding Akka Streams, Back Pressure, and Asynchronous Architectures
Lightbend
 
Spark real world use cases and optimizations
Gal Marder
 
Multi-threading in the modern era: Vertx Akka and Quasar
Gal Marder
 
Scala Frameworks for Web Application 2016
takezoe
 
Implementing Micro Services Tasks (service discovery, load balancing etc.) - ...
Gal Marder
 
The Why and How of Scala at Twitter
Alex Payne
 
Node.js Enterprise Middleware
Behrad Zari
 
Dive into spark2
Gal Marder
 
Introduction to Apache Kafka- Part 2
Knoldus Inc.
 
What’s expected in Spring 5
Gal Marder
 
Introduction to akka actors with java 8
Johan Andrén
 
What’s expected in Java 9
Gal Marder
 

Similar to Lightbend Lagom: Microservices Just Right (20)

PDF
Trivadis TechEvent 2016 Introduction to Lagom - another microservice-based fr...
Trivadis
 
PDF
Lagom : Reactive microservice framework
Fabrice Sznajderman
 
PDF
Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...
OpenCredo
 
PDF
How lagom helps to build real world microservice systems
Markus Eisele
 
PDF
Microservice Come in Systems
Markus Eisele
 
PDF
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
Lightbend
 
ODP
Introduction to Lagom Framework
Knoldus Inc.
 
PDF
Stay productive while slicing up the monolith
Markus Eisele
 
PDF
CQRS and ES with Lagom
Miel Donkers
 
PDF
Spring Cloud: Why? How? What?
Orkhan Gasimov
 
PDF
Event Sourcing in less than 20 minutes - With Akka and Java 8
J On The Beach
 
PDF
Lagom Workshop BarcelonaJUG 2017-06-08
Ignasi Marimon-Clos i Sunyol
 
PDF
NetflixOSS Open House Lightning talks
Ruslan Meshenberg
 
PPTX
How to ensure Presto scalability 
in multi use case
Kai Sasaki
 
PDF
Dragoncraft Architectural Overview
jessesanford
 
PDF
Full Stack Reactive In Practice
Lightbend
 
PDF
Lagom in Practice
JWORKS powered by Ordina
 
PDF
Java one2013
Aleksei Kornev
 
PDF
Stay productive_while_slicing_up_the_monolith
Markus Eisele
 
PPTX
Exploring Twitter's Finagle technology stack for microservices
đź’ˇ Tomasz Kogut
 
Trivadis TechEvent 2016 Introduction to Lagom - another microservice-based fr...
Trivadis
 
Lagom : Reactive microservice framework
Fabrice Sznajderman
 
Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...
OpenCredo
 
How lagom helps to build real world microservice systems
Markus Eisele
 
Microservice Come in Systems
Markus Eisele
 
The 6 Rules for Modernizing Your Legacy Java Monolith with Microservices
Lightbend
 
Introduction to Lagom Framework
Knoldus Inc.
 
Stay productive while slicing up the monolith
Markus Eisele
 
CQRS and ES with Lagom
Miel Donkers
 
Spring Cloud: Why? How? What?
Orkhan Gasimov
 
Event Sourcing in less than 20 minutes - With Akka and Java 8
J On The Beach
 
Lagom Workshop BarcelonaJUG 2017-06-08
Ignasi Marimon-Clos i Sunyol
 
NetflixOSS Open House Lightning talks
Ruslan Meshenberg
 
How to ensure Presto scalability 
in multi use case
Kai Sasaki
 
Dragoncraft Architectural Overview
jessesanford
 
Full Stack Reactive In Practice
Lightbend
 
Lagom in Practice
JWORKS powered by Ordina
 
Java one2013
Aleksei Kornev
 
Stay productive_while_slicing_up_the_monolith
Markus Eisele
 
Exploring Twitter's Finagle technology stack for microservices
đź’ˇ Tomasz Kogut
 
Ad

More from mircodotta (9)

PDF
Scala Past, Present & Future
mircodotta
 
PDF
Akka streams scala italy2015
mircodotta
 
PDF
Akka streams
mircodotta
 
PDF
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems (Soft-Sha...
mircodotta
 
PDF
Effective Scala (JavaDay Riga 2013)
mircodotta
 
PDF
Effective Scala (SoftShake 2013)
mircodotta
 
PDF
Scala: Simplifying Development
mircodotta
 
PDF
Managing Binary Compatibility in Scala (Scala Lift Off 2011)
mircodotta
 
PDF
Managing Binary Compatibility in Scala (Scala Days 2011)
mircodotta
 
Scala Past, Present & Future
mircodotta
 
Akka streams scala italy2015
mircodotta
 
Akka streams
mircodotta
 
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems (Soft-Sha...
mircodotta
 
Effective Scala (JavaDay Riga 2013)
mircodotta
 
Effective Scala (SoftShake 2013)
mircodotta
 
Scala: Simplifying Development
mircodotta
 
Managing Binary Compatibility in Scala (Scala Lift Off 2011)
mircodotta
 
Managing Binary Compatibility in Scala (Scala Days 2011)
mircodotta
 
Ad

Recently uploaded (20)

PDF
AWS_Agentic_AI_in_Indian_BFSI_A_Strategic_Blueprint_for_Customer.pdf
siddharthnetsavvies
 
PDF
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
PPTX
Employee salary prediction using Machine learning Project template.ppt
bhanuk27082004
 
PDF
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
 
PPTX
classification of computer and basic part of digital computer
ravisinghrajpurohit3
 
PPTX
Explanation about Structures in C language.pptx
Veeral Rathod
 
PDF
Salesforce Pricing Update 2025: Impact, Strategy & Smart Cost Optimization wi...
GetOnCRM Solutions
 
PPT
Brief History of Python by Learning Python in three hours
adanechb21
 
PDF
Salesforce Implementation Services Provider.pdf
VALiNTRY360
 
PPTX
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
PDF
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
PPTX
Farrell__10e_ch04_PowerPoint.pptx Programming Logic and Design slides
bashnahara11
 
PDF
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
PDF
Supabase Meetup: Build in a weekend, scale to millions
Carlo Gilmar Padilla Santana
 
PDF
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
PDF
What companies do with Pharo (ESUG 2025)
ESUG
 
PDF
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
PPTX
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
PPT
Activate_Methodology_Summary presentatio
annapureddyn
 
PPTX
Role Of Python In Programing Language.pptx
jaykoshti048
 
AWS_Agentic_AI_in_Indian_BFSI_A_Strategic_Blueprint_for_Customer.pdf
siddharthnetsavvies
 
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
Employee salary prediction using Machine learning Project template.ppt
bhanuk27082004
 
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
 
classification of computer and basic part of digital computer
ravisinghrajpurohit3
 
Explanation about Structures in C language.pptx
Veeral Rathod
 
Salesforce Pricing Update 2025: Impact, Strategy & Smart Cost Optimization wi...
GetOnCRM Solutions
 
Brief History of Python by Learning Python in three hours
adanechb21
 
Salesforce Implementation Services Provider.pdf
VALiNTRY360
 
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
Farrell__10e_ch04_PowerPoint.pptx Programming Logic and Design slides
bashnahara11
 
Download iTop VPN Free 6.1.0.5882 Crack Full Activated Pre Latest 2025
imang66g
 
Supabase Meetup: Build in a weekend, scale to millions
Carlo Gilmar Padilla Santana
 
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
What companies do with Pharo (ESUG 2025)
ESUG
 
MiniTool Power Data Recovery Crack New Pre Activated Version Latest 2025
imang66g
 
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
Activate_Methodology_Summary presentatio
annapureddyn
 
Role Of Python In Programing Language.pptx
jaykoshti048
 

Lightbend Lagom: Microservices Just Right

  • 1. Lightbend Lagom Microservices “Just Right” Mirco Dotta @mircodotta Scala Days NYC - May 10, 2016
  • 2. Lagom - [lah-gome] Adequate, sufficient, just right
  • 3. Agenda â—Ź Why Lagom? â—Ź Lagom dive in â—‹ Development Environment â—‹ Service API â—‹ Persistence API â—Ź Running in Production
  • 4. Why Lagom? â—Ź Opinionated â—Ź Developer experience matters! â—‹ No brittle script to run your services â—‹ Inter-service communication just works â—‹ Services are automatically reloaded on code change â—Ź Takes you through to production deployment
  • 5. â—Ź sbt build tool (developer experience) â—Ź Play 2.5 â—Ź Akka 2.4 (clustering, streams, persistence) â—Ź Cassandra (default data store) â—Ź Jackson (JSON serialization) â—Ź Guice (DI) â—Ź Architectural Concepts: immutability, Event Sourcing/CQRS, circuit breakers Under the hood
  • 7. Anatomy of a Lagom project â—Ź sbt build â—Ź Scala 2.11 and JDK8 â—Ź Each service definition is split into two sbt projects: â—‹ api â—‹ Implementation
  • 9. Service definition trait HelloService extends Service { override def descriptor(): Descriptor = { named("helloservice").`with`( namedCall("/hello", sayHello _) ) } def sayHello(): ServiceCall[String, String] } // this source is placed in your api project
  • 10. ServiceCall explained â—Ź ServiceCall can be invoked when consuming a service: â—‹ Request: type of incoming request message (e.g. String) â—‹ Response: type of outgoing response message (e.g. String) â—Ź JSON is the default serialization format for request/response messages â—Ź There are two kinds of request/response messages: â—‹ Strict â—‹ Streamed trait ServiceCall[Request, Response] { def invoke(request: Request): Future[Response] }
  • 11. Strict Messages Strict messages are fully buffered into memory override def descriptor(): Descriptor = { named("friendservice").`with`( pathCall("/users/:userId/friends", addFriend _) ) } def addFriend(userId: String): ServiceCall[FriendId, NotUsed]
  • 12. Streamed Messages override def descriptor(): Descriptor = { named("clock").`with`( pathCall("/tick/:interval", tick()) ) } def tick(): ServiceCall[String, Source[String, _]] â—Ź A streamed message is of type Source (an Akka streams API) â—Ź It allows asynchronous streaming and handling of messages â—Ź Lagom will select transport protocol (currently WebSockets)
  • 13. Remember the Service definition? trait HelloService extends Service { override def descriptor(): Descriptor = { named("helloservice").`with`( namedCall(sayHello _) ) } def sayHello(): ServiceCall[String, String] } // this source is placed in your api project
  • 14. Here is the Service implementation class HelloServiceImpl extends HelloService { override def sayHello(): ServiceCall[String, String] { name => Future.successful(s"Hello, $name!") } } // this source is placed in your implementation project
  • 15. Inter-service communication class MyServiceImpl @Inject()(helloService: HelloService) (implicit ec: ExecutionContext) extends MyService { override def sayHelloLagom(): ServiceCall[NotUsed, String] = unused => { val response = helloService.sayHello().invoke("Lagom") response.map(answer => s"Hello service said: $answer") } }
  • 17. Principles â—Ź Each service owns its data â—‹ Only the service has direct access to the DB â—Ź We advocate the use of Event Sourcing (ES) and CQRS â—‹ ES: Capture all state’s changes as events â—‹ CQRS: separate models for write and read
  • 18. Benefits of Event Sourcing/CQRS â—Ź Allows you to time travel â—Ź Audit log â—Ź Future business opportunities â—Ź No need for ORM â—Ź No database migration script, ever â—Ź Performance & Scalability â—Ź Testability & Debuggability
  • 19. Event Sourcing: Write Side â—Ź Create your own Command and Event classes â—Ź Subclass PersistentEntity â—‹ Define Command and Event handlers â—‹ Can be accessed from anywhere in the cluster â—‹ (corresponds to an Aggregate Root in DDD)
  • 20. Event Sourcing: Example Create the Command classes sealed trait FriendCommand extends Jsonable case class AddFriend(friendUserId: String) extends PersistentEntity.ReplyType[Done] with FriendCommand // more friend commands
  • 21. Event Sourcing: Example cont’d Create the Event classes sealed trait FriendEvent extends Jsonable case class FriendAdded(userId: String, friendId: String, timestamp: Instant = Instant.now()) extends FriendEvent // more friend events
  • 22. Event Sourcing: Example cont’d class FriendEntity extends PersistentEntity[FriendCommand, FriendEvent, FriendState] { def initialBehavior(snapshotState: Optional[FriendState]): Behavior = // TODO: define command and event handlers } Create a subclass of PersistentEntity
  • 23. Event Sourcing: Example cont’d val b: Behavior = newBehaviorBuilder(/*...*/) b.setCommandHandler(classOf[AddFriend], (cmd: AddFriend, ctx: CommandContext[Done]) => state.user match { case None => ctx.invalidCommand(s"User ${entityId} is not created") ctx.done() case Some(user) => ctx.thenPersist(FriendAdded(user.userId, cmd.friendUserId), (evt: FriendAdded) => ctx.reply(Done)) })
  • 24. b.setEventHandler(classOf[FriendAdded], (evt: FriendAdded) => state.addFriend(evt.friendId)) Event Sourcing: Example cont’d No side-effects in the event handler!
  • 25. Event Sourcing: Example cont’d Create the State class case class FriendState(user: Option[User]) extends Jsonable { def addFriend(friendUserId: String): FriendState = user match { case None => throw new IllegalStateException( "friend can't be added before user is created") case Some(user) => val newFriends = user.friends :+ friendUserId FriendState(Some(user.copy(friends = newFriends))) } }
  • 26. class FriendServiceImpl @Inject() (persistentEntities: PersistentEntityRegistry) (implicit ec: ExecutionContext) extends FriendService { // at service startup we must register the needed entities persistentEntities.register(classOf[FriendEntity]) def addFriend(userId: String): ServiceCall[FriendId, NotUsed] = request => { val ref = persistentEntities.refFor(classOf[FriendEntity], userId) ref.ask[Done, AddFriend](AddFriend(request.friendId)) } // ... } Event Sourcing: Example cont’d
  • 27. Event Sourcing: Read Side â—Ź Tightly integrated with Cassandra â—Ź Create the query tables: â—‹ Subclass CassandraReadSideProcessor â—‹ Consumes events produced by the PersistentEntity and updates tables in Cassandra optimized for queries â—Ź Retrieving data: Cassandra Query Language â—‹ e.g., SELECT id, title FROM postsummary
  • 28. Running in Production â—Ź sbt-native packager is used to produce zip, MSI, RPM, Docker â—Ź Lightbend ConductR* (our container orchestration tool) â—Ź Lightbend Reactive Platform* â—‹ Split Brain Resolver (for Akka cluster) â—‹ Lightbend Monitoring *Requires a Lightbend subscription (ConductR is free to use during development)
  • 29. Current[Lagom] â—Ź Current version is 1.0.0-M2 â—‹ 1.0 soon â—Ź Java API, but no Scala API yet â—‹ We are working on the Scala API â—‹ But using Scala with the Java API works well! https: //github.com/dotta/activator-lagom-scala-chirper
  • 30. Future[Lagom] â—Ź Maven support â—Ź Message broker integration â—Ź Scala API â—Ź Support for other cluster orchestration tools â—Ź Support for writing integration tests â—Ź Swagger integration â—‹ Which also removes binary coupling!
  • 31. Next: Seq[Step] â—Ź Try Lagom yourself â—‹ https://lightbend.com/lagom â—Ź Using Scala with Lagom â—‹ https://github.com/dotta/activator-lagom-scala-chirper â—Ź Lagom on Github â—‹ https://github.com/lagom/lagom â—Ź Read Jonas BonĂ©r's free book Reactive Services Architecture â—‹ https://lightbend.com/reactive-microservices-architecture â—Ź Great presentation by Greg Young on why you should use ES â—‹ https://www.youtube.com/watch?v=JHGkaShoyNs
  • 32. Thank you for listening! @mircodotta @lagom
  • 33. override def descriptor(): Descriptor = { named("friendservice").`with`( namedCall("/users", createUser _), pathCall("/users/:id", getUser _), restCall(Method.POST, "/users/:userId/friends", addFriend _) ) } def createUser(): ServiceCall[User, NotUsed] def getUser(id: String): ServiceCall[NotUsed, User] def addFriend(userId: String): ServiceCall[FriendId, NotUsed] Different kinds of service call descriptors