SlideShare a Scribd company logo
Jarek Ratajski
CSS Versicherung
jratajski@gmail.com
@jarek000000
Lagom it's about time
Jarek Ratajski
Developer, wizard, anarchitectDeveloper, wizard, anarchitect
Lives in LuzernLives in Luzern
Works in CSS InsuranceWorks in CSS Insurance
C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS,C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS,
ScalaJS....ScalaJS....
jratajski@gmail.comjratajski@gmail.com @jarek000000@jarek000000
Agenda
●
Intro
●
Something, something - Lagom
●
End
Architecture of 90-ties
● Single core processors
● Small RAM ( 256 MB)
● 1000s of clients
● 10 Req / S
Motto: Conserve RAM
Result: heavy disk usage, concurrency by locks
90ties revenge
Architecture now
● Multicores 8-20 Cores
● Huge RAM 1TB
● 100 000 Clients
● 1000 Req / s
● Cloud
Motto: Scale
Scaling - Amdahl's law
Do you know what is your AS doing?
Challenges
● Use multiple cores
● Do not lock
● Minimize context switching
Proposal: non blocking architecture, proces many events using only few threads
Non blocking architecture
Request 2
parse, call http
Request 1
parse http response
Call DB
Request 2
parse http response
Call DB
Request 2
Prosess DB result
Send response
Request 1
Prosess DB result
Send response
Http response for 1 Http response for 2 Db 2 Db 1
service
db
Http server
1
2
Lagom
Lighbend (Typesafe)
Creators of Akka / Play
Java 8 API
Microservices
Reactive
Cassandra
Non blocking
ConductR
Event Sourcing
CQRS
Opinionated
DEMO
Lagom project structure
● Maven (or SBT)
● Build
● Configs
user-api game-api score-api
user-impi user-impiuser-impi
HTTP/REST HTTP/REST
Does not have to be
implemented by LAGOM
Lagom – Define Service - API
public interface UsersService extends Service{
ServiceCall<NewUser, RegUserStatus> addUser(String id);
ServiceCall<LoginData, Option<Session>> login(String id);
ServiceCall<NotUsed, Option<Session>> session(String sessionId);
@Override
default Descriptor descriptor() {
return named("users").withCalls(
pathCall("/api/users/add/:id", this::addUser),
pathCall("/api/users/login/:id", this::login),
pathCall("/api/users/session/:id", this::session)
).withAutoAcl(true);
}
}
Lagom – Implement Service
@Override
public HeaderServiceCall<NewUser, RegUserStatus> addUser(String id) {
return (reqHeaders, postedUser) -> {
PersistentEntityRef<UserCommand> ref =
persistentEntityRegistry.refFor(UserEntity.class, id);
return ref.ask(new UserCommand.RegisterUser(id, postedUser))
.thenApply( stat -> Pair.create(ResponseHeader.OK, stat));
};
}
Entities - CQRS
● Commands
● Events
● State
● Behaviour
● Based on akka-actors / akka-persistence
request
command
events
state
response
Lagom – Commands
@Immutable
@JsonDeserialize
class RegisterUser implements UserCommand , CompressedJsonable,
PersistentEntity.ReplyType<RegUserStatus>{
public final String userId;
public final String password;
@JsonCreator
public RegisterUser(String userId, String password) {
this.userId = userId;
this.password = password;
}
}
Lagom – Events
@Immutable
@JsonDeserialize
final class RegisteredUser implements UserEvent {
public final String userId;
public final String password;
@JsonCreator
public RegisteredUser(String id, String password) {
this.userId = id;
this.password = password;
}
}
Lagom – State
@Immutable
public class UserData {
public final String id;
public final String hashedPassword;
public UserData(String id, String hashedPassword) {
this.id = id;
this.hashedPassword = hashedPassword;
}
}
@Immutable
public class UserState {
public final Option<UserData> user ;
public UserState(final Option<UserData> user) {
this.user = user;
}
public static UserState empty() {
return new UserState(Option.none());
}
}
Lagom - entity
public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> {
@Override
public Behavior initialBehavior(Optional<UserState> snapshotState) {
BehaviorBuilder b = newBehaviorBuilder(
snapshotState.orElse(UserState.empty()));
b.setEventHandler(UserEvent.RegisteredUser.class,
evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password))));
b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD);
b.setReadOnlyCommandHandler( UserCommand.LoginUser.class,
(cmd,ctx) ->
ctx.reply( state()
.user.map(
u-> u.hashedPassword
.equals(cmd.data.password))
.getOrElse(false))
);
return b.build();
}
private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) {
if (state().user.isDefined()) {
ctx.reply(new RegUserStatus(Option.some("user exists")));
return ctx.done();
} else {
return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data),
evt -> ctx.reply( new RegUserStatus(Option.none())));
}
}
}
Lagom - entity
public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> {
@Override
public Behavior initialBehavior(Optional<UserState> snapshotState) {
BehaviorBuilder b = newBehaviorBuilder(
snapshotState.orElse(UserState.empty()));
b.setEventHandler(UserEvent.RegisteredUser.class,
evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password))));
b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD);
b.setReadOnlyCommandHandler( UserCommand.LoginUser.class,
(cmd,ctx) ->
ctx.reply( state()
.user.map(
u-> u.hashedPassword
.equals(cmd.data.password))
.getOrElse(false))
);
return b.build();
}
private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) {
if (state().user.isDefined()) {
ctx.reply(new RegUserStatus(Option.some("user exists")));
return ctx.done();
} else {
return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data),
evt -> ctx.reply( new RegUserStatus(Option.none())));
}
}
}
Lagom - entity
public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> {
@Override
public Behavior initialBehavior(Optional<UserState> snapshotState) {
BehaviorBuilder b = newBehaviorBuilder(
snapshotState.orElse(UserState.empty()));
b.setEventHandler(UserEvent.RegisteredUser.class,
evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password))));
b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD);
b.setReadOnlyCommandHandler( UserCommand.LoginUser.class,
(cmd,ctx) ->
ctx.reply( state()
.user.map(
u-> u.hashedPassword
.equals(cmd.data.password))
.getOrElse(false))
);
return b.build();
}
private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) {
if (state().user.isDefined()) {
ctx.reply(new RegUserStatus(Option.some("user exists")));
return ctx.done();
} else {
return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data),
evt -> ctx.reply( new RegUserStatus(Option.none())));
}
}
}
Cassandra
Lagom – Read Side and SQL/NoSQL
● Cassandra is default Event Store from few options
● SQL DB also goes ... typically makes no sense
● There can be additional READ MODELS created for Entities (for READs SQL
makes sense)
events
state
Read side projection
Read side processor
request
response
Lagom – read side... writeProcessor
private CompletionStage<List<BoundStatement>> processScoreAdded(ScoreEvent.RecordAdded event) {
System.out.println("score in PROCESSOR:"+ event);
final ScoreRecord singleRecord = event.record;
return this.getSingleScore(singleRecord.userId).thenApply(
score -> {
BoundStatement bindWriteScore = writeScore.bind();
boolean won = singleRecord.result == GameResult.WON;
bindWriteScore.setInt("totalScore", score.totalScore + (won ? 5 : 0 ));
bindWriteScore.setInt("gamesWon", score.gamesWon + (won ? 1 : 0));
bindWriteScore.setInt("gamesLost",score.gamesLost + (won ? 0 : 1) );
bindWriteScore.setInt("gamesPlayed",score.gamesPlayed + 1 );
bindWriteScore.setInt("pointsScored", score.pointsScored+ singleRecord.playerScored);
bindWriteScore.setInt("pointsLost", score.pointsLost+ singleRecord.opponentScore);
bindWriteScore.setString("userId", singleRecord.userId);
System.out.println("bound for:"+singleRecord.userId);
return bindWriteScore;
}
).thenApply(bs -> Arrays.asList(bs));
}
Lagom – read side... read with CQL
public ServiceCall<NotUsed, List<UserScore>> getTopScores() {
return request -> {
return cassandraSession.selectAll(
"SELECT userId, " +
"totalScore, " +
"gamesWon, " +
"gamesLost, " +
"gamesPlayed, " +
"pointsScored, " +
"pointsLost FROM userScore "
)
.thenApply(allRows ->
List.ofAll(allRows)
.map(ScoreRSProcessor.getRowUserScoreFunction())
.sortBy(score ->score.totalScore)
.reverse()
.take(20)
);
};
}
Websocket
private Source<GameState, NotUsed> createFlow(Source<String, NotUsed> input, final String gameId) {
final PubSubRef<GameState> ref = pubSub.refFor(TopicId.of(GameState.class, gameId));
Source<GameState, NotUsed> games = ref.subscriber();
return games;
}
@Override
public ServiceCall<Source<String, NotUsed>, Source<GameState, NotUsed>> stream(final String
gameId) {
return req ->
CompletableFuture.completedFuture(createFlow(req, gameId));
}
Security
public HeaderServiceCall<String, Done> movePaddle(final String gameId) {
return runSecure((session, newPosition) -> {
float targetY = Float.parseFloat(newPosition);
PersistentEntityRef<GameStateCommand> ref =
persistentEntityRegistry.refFor(GameStateEntity.class, gameId);
return ref.ask(new GameStateCommand.MovePlayerPaddle(session.userId, targetY));
}, () -> Done.getInstance());
}
Lagom - testing
@Test
public void testDoubleCreateUser() {
withServer(defaultSetup().withCassandra(true), server -> {
UsersService service = server.client(UsersService.class);
RegUserStatus created1st = service.addUser("aaa").invoke(new NewUser("aaa")).toCompletableFuture().get(5,
SECONDS);
RegUserStatus created2nd= service.addUser("aaa").invoke(new NewUser("aaa")).toCompletableFuture().get(5,
SECONDS);
assertTrue( created1std.ok);
assertFalse( created2nd.ok);
});
}
Lagom programming - summary
● Java 8
● High order functions
● CompletableFuture FTW
● Immutability
● JavaSlang – perfect fit
● Fast feedback with sbt and maven(!)
● Nice tests... but slow
● Nice Documentation
● Still changing API
Lagom programming – very little magic
● No aspects with annotations
● Very simple DI framework Guice
● No beans – just classes
● Clean code with lagom is natural
Lagom alternatives
● Scala + Akka/ Akka persistence
● Ratpack + Airomem DROP DB
● Spring 5 Reactive
● JavaEE
● Spring
Lagom alternative - Ratpack
● Java 8 Non blocking http library
● Netty based
● Non blocking
● Not a framework
● Open source
● Do persistence on your own (like #DROPDB or async SQL or NoSQL)
● Fast tests
● More code to write
● No magic at all
● Ratpack + airomem : All you can get from single machine
Lagom alternative – Scala + Akka stack
● Lightbend
● Lagom is built on top of akka + play
● Scala first API
● Implementaions in Scala OK, in Java .... so so
● Lot of existing implementations, mature standard, help + support
● Professional support
● Open source
● Same as Lagom but Probably best for Scala teams
Lagom alternative – Spring 5 Reactive
● Comes soon
● No magic (like Spring Beans with DI) needed
● Similar to Ratpack !
● IMO Better looking API
● Some compatibility with Spring
● With better SpringData (non blocking, non magic) might be really killer platform!
Lagom alternatives – JavaEE or Spring
● Too much magic
● Too much locking
● Hell of getters, setters and singletons( Spring)
● Tests with mocks will test mocks
● Cleand code... with those platforms ?
● Classical state based persistence makes it easy for people
● We've seen enough!
Do you want to know more?
Life Beyond the Illusion of Present by
Jonas Boner
Polyglot Data by
Greg Young
Monadic Java & G o F patterns
Mario Fusco
Q&AJarek Ratajski
@jarek000000
jratajski@gmail.com

More Related Content

Similar to [4 dev] lagom

Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016
takezoe
 
10 ways to make your code rock
10 ways to make your code rock10 ways to make your code rock
10 ways to make your code rock
martincronje
 
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Red Hat Developers
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSockets
Yakov Fain
 
Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012
hwilming
 
Event Sourcing - what could possibly go wrong?
Event Sourcing - what could possibly go wrong?Event Sourcing - what could possibly go wrong?
Event Sourcing - what could possibly go wrong?
Andrzej Ludwikowski
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer project
GeoSolutions
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Spark Summit
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
GITS Indonesia
 
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Codemotion
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita Galkin
Sigma Software
 
Building a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless frameworkBuilding a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless framework
Luciano Mammino
 
Hatohol technical-brief-20130830-hbstudy
Hatohol technical-brief-20130830-hbstudyHatohol technical-brief-20130830-hbstudy
Hatohol technical-brief-20130830-hbstudy
koedoyoshida
 
Introduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript ConferenceIntroduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript Conference
Bo-Yi Wu
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
petabridge
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NA
GeoSolutions
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
Andrzej Ludwikowski
 
Lightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just RightLightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just Right
mircodotta
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
Jorge Lopez-Malla
 
Giga Spaces Data Grid / Data Caching Overview
Giga Spaces Data Grid / Data Caching OverviewGiga Spaces Data Grid / Data Caching Overview
Giga Spaces Data Grid / Data Caching Overview
jimliddle
 

Similar to [4 dev] lagom (20)

Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016
 
10 ways to make your code rock
10 ways to make your code rock10 ways to make your code rock
10 ways to make your code rock
 
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
 
Speed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSocketsSpeed up your Web applications with HTML5 WebSockets
Speed up your Web applications with HTML5 WebSockets
 
Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012
 
Event Sourcing - what could possibly go wrong?
Event Sourcing - what could possibly go wrong?Event Sourcing - what could possibly go wrong?
Event Sourcing - what could possibly go wrong?
 
The State of the GeoServer project
The State of the GeoServer projectThe State of the GeoServer project
The State of the GeoServer project
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
 
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
Andrzej Ludwikowski - Event Sourcing - what could possibly go wrong? - Codemo...
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita Galkin
 
Building a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless frameworkBuilding a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless framework
 
Hatohol technical-brief-20130830-hbstudy
Hatohol technical-brief-20130830-hbstudyHatohol technical-brief-20130830-hbstudy
Hatohol technical-brief-20130830-hbstudy
 
Introduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript ConferenceIntroduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript Conference
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 
State of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NAState of GeoServer at FOSS4G-NA
State of GeoServer at FOSS4G-NA
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
 
Lightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just RightLightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just Right
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
 
Giga Spaces Data Grid / Data Caching Overview
Giga Spaces Data Grid / Data Caching OverviewGiga Spaces Data Grid / Data Caching Overview
Giga Spaces Data Grid / Data Caching Overview
 

More from Jarek Ratajski

respect-estimates.pdf
respect-estimates.pdfrespect-estimates.pdf
respect-estimates.pdf
Jarek Ratajski
 
Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021
Jarek Ratajski
 
Lambda hardcore
Lambda hardcoreLambda hardcore
Lambda hardcore
Jarek Ratajski
 
Pure kotlin
Pure kotlinPure kotlin
Pure kotlin
Jarek Ratajski
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monad
Jarek Ratajski
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
Jarek Ratajski
 
Spring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good partsSpring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good parts
Jarek Ratajski
 
Eta lang Beauty And The Beast
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast
Jarek Ratajski
 
Another programming language - jeszcze jeden język
Another programming language - jeszcze jeden językAnother programming language - jeszcze jeden język
Another programming language - jeszcze jeden język
Jarek Ratajski
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVM
Jarek Ratajski
 
Fighting null with memes
Fighting null with memesFighting null with memes
Fighting null with memes
Jarek Ratajski
 
Eta
EtaEta
Geecon walking in CODE
Geecon walking in CODEGeecon walking in CODE
Geecon walking in CODE
Jarek Ratajski
 
Scalaworld lambda core hardcore
Scalaworld lambda core hardcoreScalaworld lambda core hardcore
Scalaworld lambda core hardcore
Jarek Ratajski
 
Lambda core
Lambda coreLambda core
Lambda core
Jarek Ratajski
 
Jdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASEJdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASE
Jarek Ratajski
 
DROPDB Galactic story
DROPDB Galactic storyDROPDB Galactic story
DROPDB Galactic story
Jarek Ratajski
 

More from Jarek Ratajski (17)

respect-estimates.pdf
respect-estimates.pdfrespect-estimates.pdf
respect-estimates.pdf
 
Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021Pure Kotlin Devoxx PL 2021
Pure Kotlin Devoxx PL 2021
 
Lambda hardcore
Lambda hardcoreLambda hardcore
Lambda hardcore
 
Pure kotlin
Pure kotlinPure kotlin
Pure kotlin
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monad
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
 
Spring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good partsSpring, CDI, Jakarta EE good parts
Spring, CDI, Jakarta EE good parts
 
Eta lang Beauty And The Beast
Eta lang Beauty And The Beast Eta lang Beauty And The Beast
Eta lang Beauty And The Beast
 
Another programming language - jeszcze jeden język
Another programming language - jeszcze jeden językAnother programming language - jeszcze jeden język
Another programming language - jeszcze jeden język
 
Beauty and the beast - Haskell on JVM
Beauty and the beast  - Haskell on JVMBeauty and the beast  - Haskell on JVM
Beauty and the beast - Haskell on JVM
 
Fighting null with memes
Fighting null with memesFighting null with memes
Fighting null with memes
 
Eta
EtaEta
Eta
 
Geecon walking in CODE
Geecon walking in CODEGeecon walking in CODE
Geecon walking in CODE
 
Scalaworld lambda core hardcore
Scalaworld lambda core hardcoreScalaworld lambda core hardcore
Scalaworld lambda core hardcore
 
Lambda core
Lambda coreLambda core
Lambda core
 
Jdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASEJdd 2016 DROP DATABASE
Jdd 2016 DROP DATABASE
 
DROPDB Galactic story
DROPDB Galactic storyDROPDB Galactic story
DROPDB Galactic story
 

Recently uploaded

AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
HarpalGohil4
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
zjhamm304
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
Neo4j
 
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
ScyllaDB
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
christinelarrosa
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
Antonios Katsarakis
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
LizaNolte
 
Day 2 - Intro to UiPath Studio Fundamentals
Day 2 - Intro to UiPath Studio FundamentalsDay 2 - Intro to UiPath Studio Fundamentals
Day 2 - Intro to UiPath Studio Fundamentals
UiPathCommunity
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
DanBrown980551
 
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeckPoznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
FilipTomaszewski5
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
Sease
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
Javier Junquera
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
leebarnesutopia
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
ScyllaDB
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
christinelarrosa
 

Recently uploaded (20)

AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
 
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham HillinQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
inQuba Webinar Mastering Customer Journey Management with Dr Graham Hill
 
Day 2 - Intro to UiPath Studio Fundamentals
Day 2 - Intro to UiPath Studio FundamentalsDay 2 - Intro to UiPath Studio Fundamentals
Day 2 - Intro to UiPath Studio Fundamentals
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
 
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeckPoznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
Poznań ACE event - 19.06.2024 Team 24 Wrapup slidedeck
 
From Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMsFrom Natural Language to Structured Solr Queries using LLMs
From Natural Language to Structured Solr Queries using LLMs
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
 

[4 dev] lagom

  • 2. Jarek Ratajski Developer, wizard, anarchitectDeveloper, wizard, anarchitect Lives in LuzernLives in Luzern Works in CSS InsuranceWorks in CSS Insurance C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS,C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS, ScalaJS....ScalaJS.... jratajski@gmail.comjratajski@gmail.com @jarek000000@jarek000000
  • 4. Architecture of 90-ties ● Single core processors ● Small RAM ( 256 MB) ● 1000s of clients ● 10 Req / S Motto: Conserve RAM Result: heavy disk usage, concurrency by locks
  • 6. Architecture now ● Multicores 8-20 Cores ● Huge RAM 1TB ● 100 000 Clients ● 1000 Req / s ● Cloud Motto: Scale
  • 8. Do you know what is your AS doing?
  • 9.
  • 10.
  • 11. Challenges ● Use multiple cores ● Do not lock ● Minimize context switching Proposal: non blocking architecture, proces many events using only few threads
  • 12. Non blocking architecture Request 2 parse, call http Request 1 parse http response Call DB Request 2 parse http response Call DB Request 2 Prosess DB result Send response Request 1 Prosess DB result Send response Http response for 1 Http response for 2 Db 2 Db 1 service db Http server 1 2
  • 13. Lagom Lighbend (Typesafe) Creators of Akka / Play Java 8 API Microservices Reactive Cassandra Non blocking ConductR Event Sourcing CQRS Opinionated
  • 14. DEMO
  • 15. Lagom project structure ● Maven (or SBT) ● Build ● Configs
  • 16. user-api game-api score-api user-impi user-impiuser-impi HTTP/REST HTTP/REST Does not have to be implemented by LAGOM
  • 17. Lagom – Define Service - API public interface UsersService extends Service{ ServiceCall<NewUser, RegUserStatus> addUser(String id); ServiceCall<LoginData, Option<Session>> login(String id); ServiceCall<NotUsed, Option<Session>> session(String sessionId); @Override default Descriptor descriptor() { return named("users").withCalls( pathCall("/api/users/add/:id", this::addUser), pathCall("/api/users/login/:id", this::login), pathCall("/api/users/session/:id", this::session) ).withAutoAcl(true); } }
  • 18. Lagom – Implement Service @Override public HeaderServiceCall<NewUser, RegUserStatus> addUser(String id) { return (reqHeaders, postedUser) -> { PersistentEntityRef<UserCommand> ref = persistentEntityRegistry.refFor(UserEntity.class, id); return ref.ask(new UserCommand.RegisterUser(id, postedUser)) .thenApply( stat -> Pair.create(ResponseHeader.OK, stat)); }; }
  • 19. Entities - CQRS ● Commands ● Events ● State ● Behaviour ● Based on akka-actors / akka-persistence request command events state response
  • 20. Lagom – Commands @Immutable @JsonDeserialize class RegisterUser implements UserCommand , CompressedJsonable, PersistentEntity.ReplyType<RegUserStatus>{ public final String userId; public final String password; @JsonCreator public RegisterUser(String userId, String password) { this.userId = userId; this.password = password; } }
  • 21. Lagom – Events @Immutable @JsonDeserialize final class RegisteredUser implements UserEvent { public final String userId; public final String password; @JsonCreator public RegisteredUser(String id, String password) { this.userId = id; this.password = password; } }
  • 22. Lagom – State @Immutable public class UserData { public final String id; public final String hashedPassword; public UserData(String id, String hashedPassword) { this.id = id; this.hashedPassword = hashedPassword; } } @Immutable public class UserState { public final Option<UserData> user ; public UserState(final Option<UserData> user) { this.user = user; } public static UserState empty() { return new UserState(Option.none()); } }
  • 23. Lagom - entity public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> { @Override public Behavior initialBehavior(Optional<UserState> snapshotState) { BehaviorBuilder b = newBehaviorBuilder( snapshotState.orElse(UserState.empty())); b.setEventHandler(UserEvent.RegisteredUser.class, evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password)))); b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD); b.setReadOnlyCommandHandler( UserCommand.LoginUser.class, (cmd,ctx) -> ctx.reply( state() .user.map( u-> u.hashedPassword .equals(cmd.data.password)) .getOrElse(false)) ); return b.build(); } private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) { if (state().user.isDefined()) { ctx.reply(new RegUserStatus(Option.some("user exists"))); return ctx.done(); } else { return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data), evt -> ctx.reply( new RegUserStatus(Option.none()))); } } }
  • 24. Lagom - entity public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> { @Override public Behavior initialBehavior(Optional<UserState> snapshotState) { BehaviorBuilder b = newBehaviorBuilder( snapshotState.orElse(UserState.empty())); b.setEventHandler(UserEvent.RegisteredUser.class, evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password)))); b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD); b.setReadOnlyCommandHandler( UserCommand.LoginUser.class, (cmd,ctx) -> ctx.reply( state() .user.map( u-> u.hashedPassword .equals(cmd.data.password)) .getOrElse(false)) ); return b.build(); } private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) { if (state().user.isDefined()) { ctx.reply(new RegUserStatus(Option.some("user exists"))); return ctx.done(); } else { return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data), evt -> ctx.reply( new RegUserStatus(Option.none()))); } } }
  • 25. Lagom - entity public class UserEntity extends PersistentEntity<UserCommand, UserEvent, UserState> { @Override public Behavior initialBehavior(Optional<UserState> snapshotState) { BehaviorBuilder b = newBehaviorBuilder( snapshotState.orElse(UserState.empty())); b.setEventHandler(UserEvent.RegisteredUser.class, evt -> new UserState(Option.some(new UserData(evt.userId, evt.data.password)))); b.setCommandHandler(UserCommand.RegisterUser.class, this::handleRegisterUserCMD); b.setReadOnlyCommandHandler( UserCommand.LoginUser.class, (cmd,ctx) -> ctx.reply( state() .user.map( u-> u.hashedPassword .equals(cmd.data.password)) .getOrElse(false)) ); return b.build(); } private Persist handleRegisterUserCMD(UserCommand.RegisterUser cmd, CommandContext ctx) { if (state().user.isDefined()) { ctx.reply(new RegUserStatus(Option.some("user exists"))); return ctx.done(); } else { return ctx.thenPersist(new UserEvent.RegisteredUser(cmd.userId, cmd.data), evt -> ctx.reply( new RegUserStatus(Option.none()))); } } }
  • 27. Lagom – Read Side and SQL/NoSQL ● Cassandra is default Event Store from few options ● SQL DB also goes ... typically makes no sense ● There can be additional READ MODELS created for Entities (for READs SQL makes sense) events state Read side projection Read side processor request response
  • 28. Lagom – read side... writeProcessor private CompletionStage<List<BoundStatement>> processScoreAdded(ScoreEvent.RecordAdded event) { System.out.println("score in PROCESSOR:"+ event); final ScoreRecord singleRecord = event.record; return this.getSingleScore(singleRecord.userId).thenApply( score -> { BoundStatement bindWriteScore = writeScore.bind(); boolean won = singleRecord.result == GameResult.WON; bindWriteScore.setInt("totalScore", score.totalScore + (won ? 5 : 0 )); bindWriteScore.setInt("gamesWon", score.gamesWon + (won ? 1 : 0)); bindWriteScore.setInt("gamesLost",score.gamesLost + (won ? 0 : 1) ); bindWriteScore.setInt("gamesPlayed",score.gamesPlayed + 1 ); bindWriteScore.setInt("pointsScored", score.pointsScored+ singleRecord.playerScored); bindWriteScore.setInt("pointsLost", score.pointsLost+ singleRecord.opponentScore); bindWriteScore.setString("userId", singleRecord.userId); System.out.println("bound for:"+singleRecord.userId); return bindWriteScore; } ).thenApply(bs -> Arrays.asList(bs)); }
  • 29. Lagom – read side... read with CQL public ServiceCall<NotUsed, List<UserScore>> getTopScores() { return request -> { return cassandraSession.selectAll( "SELECT userId, " + "totalScore, " + "gamesWon, " + "gamesLost, " + "gamesPlayed, " + "pointsScored, " + "pointsLost FROM userScore " ) .thenApply(allRows -> List.ofAll(allRows) .map(ScoreRSProcessor.getRowUserScoreFunction()) .sortBy(score ->score.totalScore) .reverse() .take(20) ); }; }
  • 30. Websocket private Source<GameState, NotUsed> createFlow(Source<String, NotUsed> input, final String gameId) { final PubSubRef<GameState> ref = pubSub.refFor(TopicId.of(GameState.class, gameId)); Source<GameState, NotUsed> games = ref.subscriber(); return games; } @Override public ServiceCall<Source<String, NotUsed>, Source<GameState, NotUsed>> stream(final String gameId) { return req -> CompletableFuture.completedFuture(createFlow(req, gameId)); }
  • 31. Security public HeaderServiceCall<String, Done> movePaddle(final String gameId) { return runSecure((session, newPosition) -> { float targetY = Float.parseFloat(newPosition); PersistentEntityRef<GameStateCommand> ref = persistentEntityRegistry.refFor(GameStateEntity.class, gameId); return ref.ask(new GameStateCommand.MovePlayerPaddle(session.userId, targetY)); }, () -> Done.getInstance()); }
  • 32. Lagom - testing @Test public void testDoubleCreateUser() { withServer(defaultSetup().withCassandra(true), server -> { UsersService service = server.client(UsersService.class); RegUserStatus created1st = service.addUser("aaa").invoke(new NewUser("aaa")).toCompletableFuture().get(5, SECONDS); RegUserStatus created2nd= service.addUser("aaa").invoke(new NewUser("aaa")).toCompletableFuture().get(5, SECONDS); assertTrue( created1std.ok); assertFalse( created2nd.ok); }); }
  • 33. Lagom programming - summary ● Java 8 ● High order functions ● CompletableFuture FTW ● Immutability ● JavaSlang – perfect fit ● Fast feedback with sbt and maven(!) ● Nice tests... but slow ● Nice Documentation ● Still changing API
  • 34. Lagom programming – very little magic ● No aspects with annotations ● Very simple DI framework Guice ● No beans – just classes ● Clean code with lagom is natural
  • 35. Lagom alternatives ● Scala + Akka/ Akka persistence ● Ratpack + Airomem DROP DB ● Spring 5 Reactive ● JavaEE ● Spring
  • 36. Lagom alternative - Ratpack ● Java 8 Non blocking http library ● Netty based ● Non blocking ● Not a framework ● Open source ● Do persistence on your own (like #DROPDB or async SQL or NoSQL) ● Fast tests ● More code to write ● No magic at all ● Ratpack + airomem : All you can get from single machine
  • 37. Lagom alternative – Scala + Akka stack ● Lightbend ● Lagom is built on top of akka + play ● Scala first API ● Implementaions in Scala OK, in Java .... so so ● Lot of existing implementations, mature standard, help + support ● Professional support ● Open source ● Same as Lagom but Probably best for Scala teams
  • 38. Lagom alternative – Spring 5 Reactive ● Comes soon ● No magic (like Spring Beans with DI) needed ● Similar to Ratpack ! ● IMO Better looking API ● Some compatibility with Spring ● With better SpringData (non blocking, non magic) might be really killer platform!
  • 39.
  • 40. Lagom alternatives – JavaEE or Spring ● Too much magic ● Too much locking ● Hell of getters, setters and singletons( Spring) ● Tests with mocks will test mocks ● Cleand code... with those platforms ? ● Classical state based persistence makes it easy for people ● We've seen enough!
  • 41. Do you want to know more? Life Beyond the Illusion of Present by Jonas Boner Polyglot Data by Greg Young Monadic Java & G o F patterns Mario Fusco