SlideShare a Scribd company logo
1 of 113
Download to read offline
Ignasi Marimon-Clos - @ignasi35
(based on slides by Markus Jura - @markusjura)
Microservices “Just Right”
Disclaimer
Lagom - [lah-gome]
Adequate, sufficient, just right
• Overview
• Developer experience
• Service API
• Persistence & Clustering
• Running in production
TOC
Overview
• Reactive
• Built-in resiliency & failure handling patterns
• Developer experience
• No setup of external services
• Intra-service communication just works
• Services automatically reload on code change
• Takes you through to production deployment
Why Lagom?
• Java 8
• Play 2.5
• Akka 2.4 (Clustering, Streams, Persistence)
• Cassandra (default data store)
• Jackson (JSON serialization)
• Guice (DI)
Under the hood
Developer experience
• Ocado rip-off
• BasketService: CreateBasket, AddItem, RemoveItem
• InventoryService: AddItem, ProvisionItem, ReserveItem, PickUpItem
• OrderService: PlaceOrder, CompleteOrder, FailOrder
• DeliveryService: DeliverOrder
Today’s workshop
BasketService
OrderService
InventoryService
DeliveryService
Enough slides,
Demo time
$ sbt runAll
$ mvn lagom:runAll
Service API
Service definition
public interface BasketService extends Service {
@Override
default Descriptor descriptor() {
return named("basketservice").withCalls(
namedCall("/api/baskets", this::createBasket)
)
}
ServiceCall<Basket, String> createBasket();
}
Service definition
public interface BasketService extends Service {
@Override
default Descriptor descriptor() {
return named("basketservice").withCalls(
restCall(Method.POST,
”/api/baskets”,this::createBasket)
)
}
ServiceCall<Basket, String> createBasket();
}
Each service definition is split into two sbt projects: api &
impl
Anatomy Lagom project
my-lagom-system ! Project root

# helloworld-api ! helloworld api project

# helloworld-impl ! helloworld implementation project

# project ! sbt configuration files

# plugins.sbt ! sbt plugins

# build.sbt ! Your project build file
Service definition
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
restCall(Method.POST,
”/api/users”,this::createUser)
)
}
ServiceCall<User, String> createUser();
}
Service definition
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
pathCall(”/api/users”,this::createUser)
)
}
ServiceCall<User, String> createUser();
}
Service definition
// this source is placed in your api project
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
namedCall(”createUser", this::createUser)
)
}
ServiceCall<User, String> createUser();
}
Service definition
// this source is placed in your api project
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
call(this::createUser)
)
}
ServiceCall<User, String> createUser();
}
$ sbt runAll
$ mvn lagom:runAll
$ sbt runAll
[info] Loading project definition from /Users/ignasi/workshop/hello/project
[info] Set current project to hello-workshop (in build file:/Users/ignasi/workshop/hello/)
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-kafka...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Starting Kafka
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-cassandra...
[info] Resolving com.google.guava#guava;18.0 ...
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Starting Cassandra
..........
[info] Cassandra server running at 127.0.0.1:4000
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-service-locator...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Service locator is running at http://localhost:8000
[info] Service gateway is running at http://localhost:9000
[info] Compiling 3 Java sources to /Users/ignasi/workshop/hello/hello-api/target/scala-2.11/classes...
[info] Compiling 1 Java source to /Users/ignasi/workshop/hello/hello-stream-api/target/scala-2.11/classes...
[info] Compiling 4 Java sources to /Users/ignasi/workshop/hello/hello-stream-impl/target/scala-2.11/classes...
[info] Compiling 6 Java sources to /Users/ignasi/workshop/hello/hello-impl/target/scala-2.11/classes...
[warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 1 : {hello-
events=LEADER_NOT_AVAILABLE}
[warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 2 : {hello-
events=LEADER_NOT_AVAILABLE}
[info] Service hello-impl listening for HTTP on 0:0:0:0:0:0:0:0:57797
[info] Service hello-stream-impl listening for HTTP on 0:0:0:0:0:0:0:0:58322
[info] (Services started, press enter to stop and go back to the console...)
curl http://localhost:9000/api/hello/Alice
$ sbt runAll
[info] Loading project definition from /Users/ignasi/workshop/hello/project
[info] Set current project to hello-workshop (in build file:/Users/ignasi/workshop/hello/)
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-kafka...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Starting Kafka
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-cassandra...
[info] Resolving com.google.guava#guava;18.0 ...
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Starting Cassandra
..........
[info] Cassandra server running at 127.0.0.1:4000
[info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-service-locator...
[info] Resolving jline#jline;2.12.1 ...
[info] Done updating.
[info] Service locator is running at http://localhost:8000
[info] Service gateway is running at http://localhost:9000
[info] Compiling 3 Java sources to /Users/ignasi/workshop/hello/hello-api/target/scala-2.11/classes...
[info] Compiling 1 Java source to /Users/ignasi/workshop/hello/hello-stream-api/target/scala-2.11/classes...
[info] Compiling 4 Java sources to /Users/ignasi/workshop/hello/hello-stream-impl/target/scala-2.11/classes...
[info] Compiling 6 Java sources to /Users/ignasi/workshop/hello/hello-impl/target/scala-2.11/classes...
[warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 1 : {hello-
events=LEADER_NOT_AVAILABLE}
[warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 2 : {hello-
events=LEADER_NOT_AVAILABLE}
[info] Service hello-impl listening for HTTP on 0:0:0:0:0:0:0:0:57797
[info] Service hello-stream-impl listening for HTTP on 0:0:0:0:0:0:0:0:58322
[info] (Services started, press enter to stop and go back to the console...)
curl http://localhost:9000/api/hello/Alice
Service definition
// this source is placed in your api project
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
namedCall(”createUsers", this::createUsers)
)
}
ServiceCall< Source<User,…> , …> createUsers();
}
$ git clone
https://github.com/ignasi35/lagom-java-workshop.git
ex001-start
Exercise
• Create service descriptor for Basket Service
ex001-start
Service definition
public interface SearchService extends Service {
@Override
default Descriptor descriptor() {
return named("search").withCalls(
pathCall(
”/api/search?pageNo&pageSize“,
this::search)
)
}
ServiceCall<SearchRequest, PageSeq<Result>>
search(int pageNo, int pageSize);
}
… pet/findByStatus”:{“get":{"tags":["pet"],"summary":"Finds Pets by
status","description":"Multiple status values can be provided with comma separated
strings","operationId":"findPetsByStatus","produces":["application/xml","application/
json"],"parameters":[{"name":"status","in":"query","description":"Status values that need to
be considered for filter","required":true,"type":"array","items":{"type":"string","enum":
["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses
":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/
definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":
[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":
["pet"],"summary":"Finds Pets by tags","description":"Muliple tags can be provided with comma
separated strings. Use tag1, tag2, tag3 for
testing.","operationId":"findPetsByTags","produces":["application/xml","application/
json"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter
by","required":true,"type":"array","items":
{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful
operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":
{"description":"Invalid tag value"}},"security":[{"petstore_auth":
["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":
["pet"],"summary":"Find pet by ID","description":"Returns a single
pet","operationId":"getPetById","produces":["application/xml","application/
json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to
return","required":true,"type":"integer","format":"int64"}],"responses":{"200":
{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":
{"description":"Invalid ID supplied”},…
Service call explained
public interface ServiceCall<Request, Response> {
CompletionStage<Response> invoke(Request request)
}
• ServiceCall is invoked when consuming a service
• JSON is the default serialization format for request/response
messages
• There are two kinds of request/response messages
• Strict
• Streamed
SAM
Strict Messages
default Descriptor descriptor() {
return named("friendservice").withCalls(
namedCall("/api/users", this::createUser)
)
}
ServiceCall<User, String> createUser();
Strict messages are buffered into memory
Streamed Messages
default Descriptor descriptor() {
return named("activityservice").withCalls(
pathCall("/activity/:userId", this::stream)
)
}
ServiceCall<NotUsed, Source<Tweet, ?>> stream(String userId);
• Streamed message is of type Source (Akka streams API)
• Back-pressured, asynchronous handling of messages
• Lagom selects transport protocol (currently WebSockets)
Each service definition is split into two sbt projects: api &
impl
Anatomy Lagom project
my-lagom-system ! Project root

# helloworld-api ! helloworld api project

# helloworld-impl ! helloworld implementation project

# project ! sbt configuration files

# plugins.sbt ! sbt plugins

# build.sbt ! Your project build file
Remember the Service definition?
// this source is placed in your api project
public interface FriendService extends Service {
@Override
default Descriptor descriptor() {
return named("friendservice").withCalls(
namedCall("/api/users", this::createUser)
)
}
ServiceCall<User, String> createUser();
}
Service implementation
import com.lightbend.lagom.javadsl.api.*;
import akka.NotUsed;
import static java.util.concurrent.CompletableFuture.completedFuture;
@Override
public ServiceCall<User, String> createUser() {
return request -> completedFuture("Created user");
}
Exercise
• Implement deleteItem
ex002-startEx001-end
???
Intra-service communication
public class MyModule
extends AbstractModule // Guice
implements ServiceGuiceSupport { // Lagom
protected void configure() {
bindClient(FriendService.class);
…
}
Intra-service communication
public class LikesSrvcImpl implements LikesService {
private final friendService;
@Inject
public LikesSrvcImpl(FriendService friendSrvc) {
this.friendService = friendSrvc;
}
…
Intra-service communication
@Override
public ServiceCall<…,…> like(String id) {
return request -> {
CompletionStage<String> userId =
friendService.createUser(user).invoke()
return userId;
}
}
Circuit breakers
• Circuit breaker is used to provide stability and prevent cascading
failures
• Services calls interacting with Lagom services are using circuit
breakers by default
• Circuit breakers can be configured
• Each service call can have a separate circuit breaker
Persistence & Clustering
Each service owns
its data
Lagom Persistence
Lagom
Persistence
CQRS Event
Sourcing
implements Using
Commands
Queries
???
= f(data)info
Commands
Queries
???
Data
Info
Events = g(Staten, Command)
Staten+1 = h(Staten, Event)
List<Event> g(State, Command)
State h(State, Event)
(State, Command) -> List<Event>
(State, Event) -> State
State -> Command -> List<Event>
State -> Event -> State
State -> Command -> List<Event>
State -> Event -> State
State -> Command -> List<Event>
State -> Event -> State
Info = f(data)
Commands
Queries
???
Data
Info
Commands
Queries
Data
Info
Info
Data
Info
Info
Journal
Snapshots
Projections
Write-side
Read-side
Exercise
• Implement the InventoryIncreased command handling
ex003-start
Persistent Entities
• Persistent Entity corresponds to an
Aggregate Root (DDD)
• Persistent Entities receive commands
• Triggered by a command, Persistent
Entities will change their state
• Example: CreateBasket, AddItem(“apple”,
3), RemoveItem(“apple”, 7), AddItem(“apple”,
5), Checkout
FriendService
Peter
Bob
Alice
Lagom Cluster
• Lagom allows you to scale
out by forming a cluster of
nodes
• Nodes can be added and
removed dynamically
Node A
Node B
Node C
Node D
join
Lagom Cluster
• Lagom allows you to scale
out by distributing your
Persistent Entities in the
cluster
Node A Node B
Node C
X
Bob
Alice
Z
X
Steve
Paul
Peter
Lagom Cluster
• We have now moved from
a CRUD approach to a
Memory Image approach
• We keep all* our data in
memory!
• See http://
martinfowler.com/bliki/
MemoryImage.html


(*) or a working set, actors can be
passivated and activated as needed
Node A Node B
Node C
X
Bob
Alice
Z
X
Steve
Paul
Peter
Lagom Persistence
• But how does our data
survive a system crash?
• We log all the state
changes!
• Persistent Entities are
recreated on another node
and all state changes are
replayed
Node A Node B
Node C
X
Bob
Alice
Z
X
Y
Paul
Peter
Journal
Snapshots
Write-side
Lagom Persistence
Node A
Node C
X
Bob
Alice
Paul
Peter Steve
Exercise
• Fix the InventoryDecreased command handling and
write a test to prevent bug regressions
ex004-start
Commands
Queries
Data
Info
Info
Event sourcing: Storing deltas
• Every state change is materialized in an Event
• All events are stored in an Event Log
• Current state is constructed by replaying all events
Event Sourcing: Benefits
• Bullet-proof auditing and historical tracing
• Support future ways of looking at data
• No object-relational impedance mismatch
• Performance and scalability
• Testability
• Keep all data in memory
• Optional: Only working set, by using passivation/activation
• Store all state changes as events
• Replay all events to re-create the state
• Optional: Start from snapshot
• Scale out with Lagom Cluster and scalable data store
Event Sourcing with Lagom Persistence
Read-Side
UserCreated(Alice)
FriendAdded(Bob)
FriendAdded(Peter)
FOLLOWERS
userid followedby
Bob Alice
Bob X
Bob Y
Peter Alice
• Derived from event log
• Can be discarded and re-created
• The “book of record” is the event log
• Can be scaled out by creating copies - it’s read only
Read-Side
Consistency
FOLLOWERS
userid followedby
Bob Alice
Bob X
Bob Y
Peter Alice
Data Store
(e.g. Cassandra Cluster)
Alice1 - Persistent
Entity
2 - Journal / Event Log
3 - Read Side
Consistency
Alice
• Persistent Entities define an
Aggregate root
• Aggregate Root is the Transactional
Boundary
• Strong consistency within an
Aggregate Root
• Commands are executed sequentially
on the latest state
• No limit to scalability
1 - Persistent
Entity
Consistency
• Depending on implementation and
configuration
• Popular choice: Casssandra
• “Tunable consistency”
• Use of quorums ensures consistencyData Store
(e.g. Cassandra Cluster)
2 - Journal / Event Log
Consistency
• Will not be updated immediately, but
deferred
• Not much different from queries in
interactive applicationsFOLLOWERS
userid followedby
Bob Alice
Bob X
Bob Y
Peter Alice
3 - Read Side
What if I don’t want to use Event Sourcing?
• Don’t use Lagom Persistence
• You can use any data store
• Beware of blocking APIs (JDBC)
Easter Egg: Broker API
Journal
Snapshots
Write-side
Read-side
Exercise
• Consume the topic where BasketService emits events to
generate the InventoryDecreased commands into
InventoryEntity
ex005-start
Production
• sbt-native packager produces several packages
• ZIP
• Docker
• RPM
• ConductR bundle
Packaging
• Infrastructure need to support Akka clustering
• Deployment tool
• Need to implement Lagom service locator interface
• Should handle node failure scenarios
Production considerations
• Akka Cluster support
• Service locator
• Consolidated logging
• Restart services automatically
• Handling network failures
• Rolling updates
• Monitoring support
ConductR
ConductR
Demo
• Getting started: lightbend.com/lagom
• Examples: lightbend.com/activator/templates
• Contribute: https://github.com/lagom
• Communicate:
• https://groups.google.com/forum/#!forum/lagom-framework
• https://gitter.im/lagom/lagom
• Lightbend Proof of Concept Program: lightbend.com/company/
contact
Try it out
Read this book
https://www.lightbend.com/reactive-
microservices-architecture
(free, registration required)
Lagom Workshop  BarcelonaJUG 2017-06-08

More Related Content

What's hot

High-Performance Hibernate - JDK.io 2018
High-Performance Hibernate - JDK.io 2018High-Performance Hibernate - JDK.io 2018
High-Performance Hibernate - JDK.io 2018Vlad Mihalcea
 
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and ScalabilitySolving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and ScalabilityZendCon
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with SpringJoshua Long
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akkanartamonov
 
Java MySQL Connector & Connection Pool Features & Optimization
Java MySQL Connector & Connection Pool Features & OptimizationJava MySQL Connector & Connection Pool Features & Optimization
Java MySQL Connector & Connection Pool Features & OptimizationKenny Gryp
 
Why we chose mongodb for guardian.co.uk
Why we chose mongodb for guardian.co.ukWhy we chose mongodb for guardian.co.uk
Why we chose mongodb for guardian.co.ukGraham Tackley
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentationGene Chang
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariJayush Luniya
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Oscar Renalias
 
Apache Aries Overview
Apache Aries   OverviewApache Aries   Overview
Apache Aries OverviewIan Robinson
 
JPA and Hibernate Performance Tips
JPA and Hibernate Performance TipsJPA and Hibernate Performance Tips
JPA and Hibernate Performance TipsVlad Mihalcea
 
Creating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSCreating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSGunnar Hillert
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayYardena Meymann
 
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe Sencha
 
Oozie HUG May12
Oozie HUG May12Oozie HUG May12
Oozie HUG May12mislam77
 

What's hot (20)

High-Performance Hibernate - JDK.io 2018
High-Performance Hibernate - JDK.io 2018High-Performance Hibernate - JDK.io 2018
High-Performance Hibernate - JDK.io 2018
 
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and ScalabilitySolving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akka
 
Java MySQL Connector & Connection Pool Features & Optimization
Java MySQL Connector & Connection Pool Features & OptimizationJava MySQL Connector & Connection Pool Features & Optimization
Java MySQL Connector & Connection Pool Features & Optimization
 
Java EE 8
Java EE 8Java EE 8
Java EE 8
 
Why we chose mongodb for guardian.co.uk
Why we chose mongodb for guardian.co.ukWhy we chose mongodb for guardian.co.uk
Why we chose mongodb for guardian.co.uk
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache Ambari
 
Connection Pooling
Connection PoolingConnection Pooling
Connection Pooling
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
 
Apache Aries Overview
Apache Aries   OverviewApache Aries   Overview
Apache Aries Overview
 
COScheduler
COSchedulerCOScheduler
COScheduler
 
JPA and Hibernate Performance Tips
JPA and Hibernate Performance TipsJPA and Hibernate Performance Tips
JPA and Hibernate Performance Tips
 
Creating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJSCreating Modular Test-Driven SPAs with Spring and AngularJS
Creating Modular Test-Driven SPAs with Spring and AngularJS
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka way
 
Liberty management
Liberty managementLiberty management
Liberty management
 
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
 
The Spring Update
The Spring UpdateThe Spring Update
The Spring Update
 
Oozie HUG May12
Oozie HUG May12Oozie HUG May12
Oozie HUG May12
 

Similar to Lagom Workshop BarcelonaJUG 2017-06-08

Creating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuCreating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuJoe Kutner
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundryrajdeep
 
deep learning in production cff 2017
deep learning in production cff 2017deep learning in production cff 2017
deep learning in production cff 2017Ari Kamlani
 
Ansible benelux meetup - Amsterdam 27-5-2015
Ansible benelux meetup - Amsterdam 27-5-2015Ansible benelux meetup - Amsterdam 27-5-2015
Ansible benelux meetup - Amsterdam 27-5-2015Pavel Chunyayev
 
Apache Ambari: Simplified Hadoop Cluster Operation & Troubleshooting
Apache Ambari: Simplified Hadoop Cluster Operation & TroubleshootingApache Ambari: Simplified Hadoop Cluster Operation & Troubleshooting
Apache Ambari: Simplified Hadoop Cluster Operation & TroubleshootingJayush Luniya
 
Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Rafał Leszko
 
Getting Started with MariaDB with Docker
Getting Started with MariaDB with DockerGetting Started with MariaDB with Docker
Getting Started with MariaDB with DockerMariaDB plc
 
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Rafał Leszko
 
Scala, ECS, Docker: Delayed Execution @Coursera
Scala, ECS, Docker: Delayed Execution @CourseraScala, ECS, Docker: Delayed Execution @Coursera
Scala, ECS, Docker: Delayed Execution @CourseraC4Media
 
Advanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesAdvanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesHiroshi SHIBATA
 
Just one-shade-of-openstack
Just one-shade-of-openstackJust one-shade-of-openstack
Just one-shade-of-openstackRoberto Polli
 
Maxim Salnikov - Service Worker: taking the best from the past experience for...
Maxim Salnikov - Service Worker: taking the best from the past experience for...Maxim Salnikov - Service Worker: taking the best from the past experience for...
Maxim Salnikov - Service Worker: taking the best from the past experience for...Codemotion
 
Introduction to Apache CloudStack by David Nalley
Introduction to Apache CloudStack by David NalleyIntroduction to Apache CloudStack by David Nalley
Introduction to Apache CloudStack by David Nalleybuildacloud
 
Docker & ECS: Secure Nearline Execution
Docker & ECS: Secure Nearline ExecutionDocker & ECS: Secure Nearline Execution
Docker & ECS: Secure Nearline ExecutionBrennan Saeta
 
The Play Framework at LinkedIn
The Play Framework at LinkedInThe Play Framework at LinkedIn
The Play Framework at LinkedInYevgeniy Brikman
 
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...The Play Framework at LinkedIn: productivity and performance at scale - Jim B...
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...jaxconf
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariAlejandro Fernandez
 

Similar to Lagom Workshop BarcelonaJUG 2017-06-08 (20)

Creating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuCreating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on Heroku
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundry
 
deep learning in production cff 2017
deep learning in production cff 2017deep learning in production cff 2017
deep learning in production cff 2017
 
Ansible benelux meetup - Amsterdam 27-5-2015
Ansible benelux meetup - Amsterdam 27-5-2015Ansible benelux meetup - Amsterdam 27-5-2015
Ansible benelux meetup - Amsterdam 27-5-2015
 
Simplified Cluster Operation and Troubleshooting
Simplified Cluster Operation and TroubleshootingSimplified Cluster Operation and Troubleshooting
Simplified Cluster Operation and Troubleshooting
 
Simplified Cluster Operation & Troubleshooting
Simplified Cluster Operation & TroubleshootingSimplified Cluster Operation & Troubleshooting
Simplified Cluster Operation & Troubleshooting
 
Apache Ambari: Simplified Hadoop Cluster Operation & Troubleshooting
Apache Ambari: Simplified Hadoop Cluster Operation & TroubleshootingApache Ambari: Simplified Hadoop Cluster Operation & Troubleshooting
Apache Ambari: Simplified Hadoop Cluster Operation & Troubleshooting
 
Sprint 17
Sprint 17Sprint 17
Sprint 17
 
Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016
 
Getting Started with MariaDB with Docker
Getting Started with MariaDB with DockerGetting Started with MariaDB with Docker
Getting Started with MariaDB with Docker
 
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
 
Scala, ECS, Docker: Delayed Execution @Coursera
Scala, ECS, Docker: Delayed Execution @CourseraScala, ECS, Docker: Delayed Execution @Coursera
Scala, ECS, Docker: Delayed Execution @Coursera
 
Advanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutesAdvanced technic for OS upgrading in 3 minutes
Advanced technic for OS upgrading in 3 minutes
 
Just one-shade-of-openstack
Just one-shade-of-openstackJust one-shade-of-openstack
Just one-shade-of-openstack
 
Maxim Salnikov - Service Worker: taking the best from the past experience for...
Maxim Salnikov - Service Worker: taking the best from the past experience for...Maxim Salnikov - Service Worker: taking the best from the past experience for...
Maxim Salnikov - Service Worker: taking the best from the past experience for...
 
Introduction to Apache CloudStack by David Nalley
Introduction to Apache CloudStack by David NalleyIntroduction to Apache CloudStack by David Nalley
Introduction to Apache CloudStack by David Nalley
 
Docker & ECS: Secure Nearline Execution
Docker & ECS: Secure Nearline ExecutionDocker & ECS: Secure Nearline Execution
Docker & ECS: Secure Nearline Execution
 
The Play Framework at LinkedIn
The Play Framework at LinkedInThe Play Framework at LinkedIn
The Play Framework at LinkedIn
 
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...The Play Framework at LinkedIn: productivity and performance at scale - Jim B...
The Play Framework at LinkedIn: productivity and performance at scale - Jim B...
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache Ambari
 

More from Ignasi Marimon-Clos i Sunyol (10)

The Emperor Has No Docs (Geecon Oct'23)
The Emperor Has No Docs (Geecon Oct'23)The Emperor Has No Docs (Geecon Oct'23)
The Emperor Has No Docs (Geecon Oct'23)
 
Jeroglificos, Minotauros y la factura de la luz
Jeroglificos, Minotauros y la factura de la luzJeroglificos, Minotauros y la factura de la luz
Jeroglificos, Minotauros y la factura de la luz
 
Contributing to Akka (Hacktoberfest 2020)
Contributing to Akka (Hacktoberfest 2020)Contributing to Akka (Hacktoberfest 2020)
Contributing to Akka (Hacktoberfest 2020)
 
Contributing to OSS (Scalator 2020-01-22)
Contributing to OSS (Scalator 2020-01-22)Contributing to OSS (Scalator 2020-01-22)
Contributing to OSS (Scalator 2020-01-22)
 
Reactive Microsystems (Sw Crafters Barcelona 2018)
Reactive Microsystems (Sw Crafters Barcelona 2018)Reactive Microsystems (Sw Crafters Barcelona 2018)
Reactive Microsystems (Sw Crafters Barcelona 2018)
 
Intro scala for rubyists (ironhack)
Intro scala for rubyists (ironhack)Intro scala for rubyists (ironhack)
Intro scala for rubyists (ironhack)
 
Functional Programming in JAVA 8
Functional Programming in JAVA 8Functional Programming in JAVA 8
Functional Programming in JAVA 8
 
Scala 101-bcndevcon
Scala 101-bcndevconScala 101-bcndevcon
Scala 101-bcndevcon
 
Scala 101
Scala 101Scala 101
Scala 101
 
Spray & Maven Intro for Scala Barcelona Developers Meetup
Spray & Maven Intro for Scala Barcelona Developers MeetupSpray & Maven Intro for Scala Barcelona Developers Meetup
Spray & Maven Intro for Scala Barcelona Developers Meetup
 

Recently uploaded

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 

Recently uploaded (20)

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 

Lagom Workshop BarcelonaJUG 2017-06-08

  • 1. Ignasi Marimon-Clos - @ignasi35 (based on slides by Markus Jura - @markusjura) Microservices “Just Right”
  • 2.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8. Lagom - [lah-gome] Adequate, sufficient, just right
  • 9. • Overview • Developer experience • Service API • Persistence & Clustering • Running in production TOC
  • 11. • Reactive • Built-in resiliency & failure handling patterns • Developer experience • No setup of external services • Intra-service communication just works • Services automatically reload on code change • Takes you through to production deployment Why Lagom?
  • 12. • Java 8 • Play 2.5 • Akka 2.4 (Clustering, Streams, Persistence) • Cassandra (default data store) • Jackson (JSON serialization) • Guice (DI) Under the hood
  • 14.
  • 15.
  • 16.
  • 17. • Ocado rip-off • BasketService: CreateBasket, AddItem, RemoveItem • InventoryService: AddItem, ProvisionItem, ReserveItem, PickUpItem • OrderService: PlaceOrder, CompleteOrder, FailOrder • DeliveryService: DeliverOrder Today’s workshop
  • 19.
  • 21. $ sbt runAll $ mvn lagom:runAll
  • 23.
  • 24.
  • 25. Service definition public interface BasketService extends Service { @Override default Descriptor descriptor() { return named("basketservice").withCalls( namedCall("/api/baskets", this::createBasket) ) } ServiceCall<Basket, String> createBasket(); }
  • 26. Service definition public interface BasketService extends Service { @Override default Descriptor descriptor() { return named("basketservice").withCalls( restCall(Method.POST, ”/api/baskets”,this::createBasket) ) } ServiceCall<Basket, String> createBasket(); }
  • 27. Each service definition is split into two sbt projects: api & impl Anatomy Lagom project my-lagom-system ! Project root
 # helloworld-api ! helloworld api project
 # helloworld-impl ! helloworld implementation project
 # project ! sbt configuration files
 # plugins.sbt ! sbt plugins
 # build.sbt ! Your project build file
  • 28. Service definition public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( restCall(Method.POST, ”/api/users”,this::createUser) ) } ServiceCall<User, String> createUser(); }
  • 29. Service definition public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( pathCall(”/api/users”,this::createUser) ) } ServiceCall<User, String> createUser(); }
  • 30. Service definition // this source is placed in your api project public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( namedCall(”createUser", this::createUser) ) } ServiceCall<User, String> createUser(); }
  • 31. Service definition // this source is placed in your api project public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( call(this::createUser) ) } ServiceCall<User, String> createUser(); }
  • 32.
  • 33. $ sbt runAll $ mvn lagom:runAll
  • 34. $ sbt runAll [info] Loading project definition from /Users/ignasi/workshop/hello/project [info] Set current project to hello-workshop (in build file:/Users/ignasi/workshop/hello/) [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-kafka... [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Starting Kafka [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-cassandra... [info] Resolving com.google.guava#guava;18.0 ... SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Starting Cassandra .......... [info] Cassandra server running at 127.0.0.1:4000 [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-service-locator... [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Service locator is running at http://localhost:8000 [info] Service gateway is running at http://localhost:9000 [info] Compiling 3 Java sources to /Users/ignasi/workshop/hello/hello-api/target/scala-2.11/classes... [info] Compiling 1 Java source to /Users/ignasi/workshop/hello/hello-stream-api/target/scala-2.11/classes... [info] Compiling 4 Java sources to /Users/ignasi/workshop/hello/hello-stream-impl/target/scala-2.11/classes... [info] Compiling 6 Java sources to /Users/ignasi/workshop/hello/hello-impl/target/scala-2.11/classes... [warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 1 : {hello- events=LEADER_NOT_AVAILABLE} [warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 2 : {hello- events=LEADER_NOT_AVAILABLE} [info] Service hello-impl listening for HTTP on 0:0:0:0:0:0:0:0:57797 [info] Service hello-stream-impl listening for HTTP on 0:0:0:0:0:0:0:0:58322 [info] (Services started, press enter to stop and go back to the console...)
  • 36. $ sbt runAll [info] Loading project definition from /Users/ignasi/workshop/hello/project [info] Set current project to hello-workshop (in build file:/Users/ignasi/workshop/hello/) [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-kafka... [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Starting Kafka [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-cassandra... [info] Resolving com.google.guava#guava;18.0 ... SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Starting Cassandra .......... [info] Cassandra server running at 127.0.0.1:4000 [info] Updating {file:/Users/ignasi/workshop/hello/}lagom-internal-meta-project-service-locator... [info] Resolving jline#jline;2.12.1 ... [info] Done updating. [info] Service locator is running at http://localhost:8000 [info] Service gateway is running at http://localhost:9000 [info] Compiling 3 Java sources to /Users/ignasi/workshop/hello/hello-api/target/scala-2.11/classes... [info] Compiling 1 Java source to /Users/ignasi/workshop/hello/hello-stream-api/target/scala-2.11/classes... [info] Compiling 4 Java sources to /Users/ignasi/workshop/hello/hello-stream-impl/target/scala-2.11/classes... [info] Compiling 6 Java sources to /Users/ignasi/workshop/hello/hello-impl/target/scala-2.11/classes... [warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 1 : {hello- events=LEADER_NOT_AVAILABLE} [warn] o.a.k.c.NetworkClient - Error while fetching metadata with correlation id 2 : {hello- events=LEADER_NOT_AVAILABLE} [info] Service hello-impl listening for HTTP on 0:0:0:0:0:0:0:0:57797 [info] Service hello-stream-impl listening for HTTP on 0:0:0:0:0:0:0:0:58322 [info] (Services started, press enter to stop and go back to the console...)
  • 38. Service definition // this source is placed in your api project public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( namedCall(”createUsers", this::createUsers) ) } ServiceCall< Source<User,…> , …> createUsers(); }
  • 40. Exercise • Create service descriptor for Basket Service ex001-start
  • 41. Service definition public interface SearchService extends Service { @Override default Descriptor descriptor() { return named("search").withCalls( pathCall( ”/api/search?pageNo&pageSize“, this::search) ) } ServiceCall<SearchRequest, PageSeq<Result>> search(int pageNo, int pageSize); }
  • 42. … pet/findByStatus”:{“get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/xml","application/ json"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum": ["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses ":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/ definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security": [{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags": ["pet"],"summary":"Finds Pets by tags","description":"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/xml","application/ json"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items": {"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400": {"description":"Invalid tag value"}},"security":[{"petstore_auth": ["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags": ["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/xml","application/ json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200": {"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400": {"description":"Invalid ID supplied”},…
  • 43. Service call explained public interface ServiceCall<Request, Response> { CompletionStage<Response> invoke(Request request) } • ServiceCall is invoked when consuming a service • JSON is the default serialization format for request/response messages • There are two kinds of request/response messages • Strict • Streamed SAM
  • 44. Strict Messages default Descriptor descriptor() { return named("friendservice").withCalls( namedCall("/api/users", this::createUser) ) } ServiceCall<User, String> createUser(); Strict messages are buffered into memory
  • 45. Streamed Messages default Descriptor descriptor() { return named("activityservice").withCalls( pathCall("/activity/:userId", this::stream) ) } ServiceCall<NotUsed, Source<Tweet, ?>> stream(String userId); • Streamed message is of type Source (Akka streams API) • Back-pressured, asynchronous handling of messages • Lagom selects transport protocol (currently WebSockets)
  • 46. Each service definition is split into two sbt projects: api & impl Anatomy Lagom project my-lagom-system ! Project root
 # helloworld-api ! helloworld api project
 # helloworld-impl ! helloworld implementation project
 # project ! sbt configuration files
 # plugins.sbt ! sbt plugins
 # build.sbt ! Your project build file
  • 47. Remember the Service definition? // this source is placed in your api project public interface FriendService extends Service { @Override default Descriptor descriptor() { return named("friendservice").withCalls( namedCall("/api/users", this::createUser) ) } ServiceCall<User, String> createUser(); }
  • 48. Service implementation import com.lightbend.lagom.javadsl.api.*; import akka.NotUsed; import static java.util.concurrent.CompletableFuture.completedFuture; @Override public ServiceCall<User, String> createUser() { return request -> completedFuture("Created user"); }
  • 50. ???
  • 51. Intra-service communication public class MyModule extends AbstractModule // Guice implements ServiceGuiceSupport { // Lagom protected void configure() { bindClient(FriendService.class); … }
  • 52. Intra-service communication public class LikesSrvcImpl implements LikesService { private final friendService; @Inject public LikesSrvcImpl(FriendService friendSrvc) { this.friendService = friendSrvc; } …
  • 53. Intra-service communication @Override public ServiceCall<…,…> like(String id) { return request -> { CompletionStage<String> userId = friendService.createUser(user).invoke() return userId; } }
  • 54. Circuit breakers • Circuit breaker is used to provide stability and prevent cascading failures • Services calls interacting with Lagom services are using circuit breakers by default • Circuit breakers can be configured • Each service call can have a separate circuit breaker
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 66. Events = g(Staten, Command) Staten+1 = h(Staten, Event)
  • 68. (State, Command) -> List<Event> (State, Event) -> State
  • 69. State -> Command -> List<Event> State -> Event -> State
  • 70. State -> Command -> List<Event> State -> Event -> State
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77. State -> Command -> List<Event> State -> Event -> State Info = f(data)
  • 80.
  • 83. Exercise • Implement the InventoryIncreased command handling ex003-start
  • 84. Persistent Entities • Persistent Entity corresponds to an Aggregate Root (DDD) • Persistent Entities receive commands • Triggered by a command, Persistent Entities will change their state • Example: CreateBasket, AddItem(“apple”, 3), RemoveItem(“apple”, 7), AddItem(“apple”, 5), Checkout FriendService Peter Bob Alice
  • 85. Lagom Cluster • Lagom allows you to scale out by forming a cluster of nodes • Nodes can be added and removed dynamically Node A Node B Node C Node D join
  • 86. Lagom Cluster • Lagom allows you to scale out by distributing your Persistent Entities in the cluster Node A Node B Node C X Bob Alice Z X Steve Paul Peter
  • 87. Lagom Cluster • We have now moved from a CRUD approach to a Memory Image approach • We keep all* our data in memory! • See http:// martinfowler.com/bliki/ MemoryImage.html 
 (*) or a working set, actors can be passivated and activated as needed Node A Node B Node C X Bob Alice Z X Steve Paul Peter
  • 88. Lagom Persistence • But how does our data survive a system crash? • We log all the state changes! • Persistent Entities are recreated on another node and all state changes are replayed Node A Node B Node C X Bob Alice Z X Y Paul Peter
  • 90. Lagom Persistence Node A Node C X Bob Alice Paul Peter Steve
  • 91. Exercise • Fix the InventoryDecreased command handling and write a test to prevent bug regressions ex004-start
  • 93. Event sourcing: Storing deltas • Every state change is materialized in an Event • All events are stored in an Event Log • Current state is constructed by replaying all events
  • 94. Event Sourcing: Benefits • Bullet-proof auditing and historical tracing • Support future ways of looking at data • No object-relational impedance mismatch • Performance and scalability • Testability
  • 95. • Keep all data in memory • Optional: Only working set, by using passivation/activation • Store all state changes as events • Replay all events to re-create the state • Optional: Start from snapshot • Scale out with Lagom Cluster and scalable data store Event Sourcing with Lagom Persistence
  • 97. • Derived from event log • Can be discarded and re-created • The “book of record” is the event log • Can be scaled out by creating copies - it’s read only Read-Side
  • 98. Consistency FOLLOWERS userid followedby Bob Alice Bob X Bob Y Peter Alice Data Store (e.g. Cassandra Cluster) Alice1 - Persistent Entity 2 - Journal / Event Log 3 - Read Side
  • 99. Consistency Alice • Persistent Entities define an Aggregate root • Aggregate Root is the Transactional Boundary • Strong consistency within an Aggregate Root • Commands are executed sequentially on the latest state • No limit to scalability 1 - Persistent Entity
  • 100. Consistency • Depending on implementation and configuration • Popular choice: Casssandra • “Tunable consistency” • Use of quorums ensures consistencyData Store (e.g. Cassandra Cluster) 2 - Journal / Event Log
  • 101. Consistency • Will not be updated immediately, but deferred • Not much different from queries in interactive applicationsFOLLOWERS userid followedby Bob Alice Bob X Bob Y Peter Alice 3 - Read Side
  • 102. What if I don’t want to use Event Sourcing? • Don’t use Lagom Persistence • You can use any data store • Beware of blocking APIs (JDBC)
  • 105. Exercise • Consume the topic where BasketService emits events to generate the InventoryDecreased commands into InventoryEntity ex005-start
  • 107. • sbt-native packager produces several packages • ZIP • Docker • RPM • ConductR bundle Packaging
  • 108. • Infrastructure need to support Akka clustering • Deployment tool • Need to implement Lagom service locator interface • Should handle node failure scenarios Production considerations
  • 109. • Akka Cluster support • Service locator • Consolidated logging • Restart services automatically • Handling network failures • Rolling updates • Monitoring support ConductR
  • 111. • Getting started: lightbend.com/lagom • Examples: lightbend.com/activator/templates • Contribute: https://github.com/lagom • Communicate: • https://groups.google.com/forum/#!forum/lagom-framework • https://gitter.im/lagom/lagom • Lightbend Proof of Concept Program: lightbend.com/company/ contact Try it out