Download - Lagom in Practice
![Page 1: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/1.jpg)
LAGOM IN PRACTICETHE NEW JAVA MICROSERVICES FRAMEWORK
![Page 2: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/2.jpg)
ABOUT ME
Yannick De Turck Java Developer
Scala and Play enthousiast Ordina Belgium
@YannickDeTurckhttps://github.com/YannickDeTurck
![Page 3: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/3.jpg)
BLOGPOST LAGOMLagom: First Impressions and Initial Comparison to Spring Cloud
http://bit.ly/1sClupt
![Page 4: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/4.jpg)
TOPICSIntroduction
Writing microservices
Demo: writing a simple service
ES & CQRS
Demo: Lagom Shop
![Page 5: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/5.jpg)
INTRODUCTION
![Page 6: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/6.jpg)
MEET LAGOMLightbend's microservices frameworkFocus on reactivenessMVP versionJava API available, Scala API coming soon
![Page 7: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/7.jpg)
DESIGN PHILOSOPHYOpinionatedMessage-Driven and AsynchronousStreaming �rst-class conceptDistributed persistent patterns using ES and CQRSEmbraces Domain-Driven Design
![Page 8: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/8.jpg)
DEVELOPER PRODUCTIVITYHot code reloadingStart up with $ runAllIntra-service communication is managed for you
![Page 9: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/9.jpg)
ARCHITECTURE AND TECHNOLOGIESScalaJavaPlay FrameworkAkka Cluster & Akka PersistencesbtCassandraGuiceConductR
![Page 10: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/10.jpg)
WRITING MICROSERVICES
![Page 11: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/11.jpg)
PROJECT STRUCTUREhelloworld-api → Microservice API submodule └ src/main/java → Java source code interfaces with model objects helloworld-impl → Microservice implementation submodule └ logs → Logs of the microservice └ src/main/java → Java source code implementation of the API submodule └ src/main/resources → Contains the microservice application config └ src/test/java → Java source code unit tests logs → Logs of the Lagom system project → Sbt configuration files └ build.properties → Marker for sbt project └ plugins.sbt → Sbt plugins including the declaration for Lagom itself .gitignore → Git ignore file build.sbt → Application build script
![Page 12: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/12.jpg)
API INTERFACEpublic interface HelloService extends Service { ServiceCall<NotUsed, String> hello(String name);
ServiceCall<GreetingMessage, String> useGreeting(String id);
@Override default Descriptor descriptor() { return named("helloservice").with( restCall(Method.GET, "/api/hello/:name", this::hello), restCall(Method.POST, "/api/hello/:id", this::useGreeting) ).withAutoAcl(true); } }
![Page 13: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/13.jpg)
API IMPLEMENTATIONpublic class HelloServiceImpl implements HelloService { List<String> savedGreetings = new ArrayList<>();
@Override public ServiceCall<NotUsed, String> hello(String name) { return (request) -> { CompletableFuture.completedFuture("Hello, " + name); }; }
@Override public ServiceCall<GreetingMessage, String> useGreeting() { return (request) -> { String greeting = request.getGreeting(); savedGreeting.add(greeting); CompletableFuture.completedFuture("Greeting '" + greeting + "' saved!"); }; } }
![Page 14: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/14.jpg)
API MODULEpublic class HelloServiceModule extends AbstractModule implements ServiceGuiceSupport { @Override protected void configure() { bindServices(serviceBinding(HelloService.class, HelloServiceImpl.class)); bindClient(OtherService.class); } }
![Page 15: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/15.jpg)
API MODULEThe module is de�ned in the application.con�g
play.modules.enabled += sample.helloworld.impl.HelloServiceModule
![Page 16: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/16.jpg)
REGISTERING THE MICROSERVICEbuild.sbt
lazy val helloworldApi = project("helloworld-api") .settings( version := "1.0-SNAPSHOT", libraryDependencies += lagomJavadslApi )
lazy val helloworldImpl = project("helloworld-impl") .enablePlugins(LagomJava) .settings( version := "1.0-SNAPSHOT", libraryDependencies ++= Seq( lagomJavadslPersistence, lagomJavadslTestKit ) ) .settings(lagomForkedTestSettings: _*) .dependsOn(helloworldApi)
![Page 17: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/17.jpg)
TESTING THE MICROSERVICE$ curl localhost:24266/api/hello/World Hello, World!
$ curl -H "Content-Type: application/json" -X POST -d \ '{"message": "Hello "}' http://localhost:24266/api/hello/World Greeting 'Hello' was saved!
![Page 18: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/18.jpg)
TESTING THE MICROSERVICEpublic class HelloServiceTest { private static ServiceTest.TestServer server;
@Test public void shouldRespondHello() throws Exception { withServer(defaultSetup(), server -> { HelloService service = server.client(HelloService.class); String hello = service.hello("Yannick") .invoke(NotUsed.getInstance()).toCompletableFuture().get(5, SECONDS); assertEquals("Hello, Yannick", hello); }); } }
![Page 19: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/19.jpg)
DEMO: WRITING A SIMPLE SERVICE
![Page 20: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/20.jpg)
DEMOImplement a new service: capitaliseWrite a unit testDeploy it to ConductR
![Page 21: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/21.jpg)
ES & CQRS
![Page 22: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/22.jpg)
ES AND CQRS
![Page 23: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/23.jpg)
![Page 24: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/24.jpg)
EVENT SOURCINGCapture all changes as domain eventsHandlers process these events
![Page 25: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/25.jpg)
EVENT SOURCING BENEFITSAll events are stored in an event storeNo object-relational impedance mismatchBuilt-in audit mechanism and historical tracingPerformance, simpli�cation and scalabilityTestabilityDebugging by replaying the event log
![Page 26: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/26.jpg)
CQRSSeparation of write- and read-sideScalabilityDi�erent models for write- and read-sideEventual consistency
![Page 27: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/27.jpg)
ES AND CQRS IN LAGOM
![Page 28: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/28.jpg)
ES AND CQRS IN LAGOM
![Page 29: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/29.jpg)
ES AND CQRS IN LAGOM
![Page 30: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/30.jpg)
ES AND CQRS IN LAGOM
![Page 31: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/31.jpg)
ES AND CQRS IN LAGOM
![Page 32: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/32.jpg)
ES AND CQRS IN LAGOM
![Page 33: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/33.jpg)
ES AND CQRS IN LAGOM
![Page 34: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/34.jpg)
ES AND CQRS IN LAGOM
![Page 35: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/35.jpg)
ES AND CQRS IN LAGOM
![Page 36: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/36.jpg)
ES AND CQRS IN LAGOM
![Page 37: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/37.jpg)
ES AND CQRS IN LAGOM
![Page 38: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/38.jpg)
ES AND CQRS IN LAGOM
![Page 39: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/39.jpg)
CQRS AND ES INTRODUCTIONhttps://msdn.microsoft.com/en-us/library/jj591573.aspx
![Page 40: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/40.jpg)
ES AND CQRS - PERSISTENTENTITYpublic class HelloWorld extends PersistentEntity { @Override public Behavior initialBehavior(Optional snapshotState) { BehaviorBuilder b = newBehaviorBuilder( snapshotState.orElse(new WorldState("Hello", LocalDateTime.now().toString())));
b.setCommandHandler(UseGreetingMessage.class, (cmd, ctx) -> ctx.thenPersist(new GreetingMessageChanged(cmd.message), evt -> ctx.reply(Done.getInstance())) );
b.setEventHandler(GreetingMessageChanged.class, evt -> new WorldState(evt.message, LocalDateTime.now().toString()));
b.setReadOnlyCommandHandler(Hello.class, (cmd, ctx) -> ctx.reply(state().message + ", " + cmd.name + "!") ); } }
![Page 41: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/41.jpg)
ES AND CQRS - STATE@Immutable @JsonDeserialize public final class WorldState implements CompressedJsonable {
public final String message; public final String timestamp;
@JsonCreator public WorldState(String message, String timestamp) { this.message = Preconditions.checkNotNull(message, "message"); this.timestamp = Preconditions.checkNotNull(timestamp, "timestamp"); }
// equals, hashcode, toString, ... }
![Page 42: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/42.jpg)
ES AND CQRS - COMMANDpublic interface HelloCommand extends Jsonable { @Immutable @JsonDeserialize public final class UseGreetingMessage implements HelloCommand, CompressedJsonable, PersistentEntity.ReplyType { public final String message;
@JsonCreator public UseGreetingMessage(String message) { this.message = Preconditions.checkNotNull(message, "message"); }
// equals, hashcode, toString,... } }
![Page 43: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/43.jpg)
ES AND CQRS - EVENTpublic interface HelloEvent extends Jsonable {
@Immutable @JsonDeserialize public final class GreetingMessageChanged implements HelloEvent { public final String message;
@JsonCreator public GreetingMessageChanged(String message) { this.message = Preconditions.checkNotNull(message, "message"); }
// equals, hashCode, toString }
![Page 44: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/44.jpg)
ES AND CQRS - SERVICEIMPL@Override public ServiceCall useGreeting(String id) { return (request) -> { PersistentEntityRef ref = persistentEntityRegistry.refFor(HelloWorld.class, id); return ref.ask(new UseGreetingMessage(request.message)); }; }
![Page 45: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/45.jpg)
DEMO: LAGOM SHOP
![Page 46: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/46.jpg)
LAGOM SHOPItem Service: Create and lookup itemsOrder Service: Create and lookup orders for itemsPlay front-end
![Page 47: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/47.jpg)
QUESTIONS?Lagom Shop & Presentation:
https://github.com/yannickdeturck/lagom-shop
Blogpost Lagom: First Impressions and Initial Comparison to SpringCloud http://bit.ly/1sClupt
Podcast Lightbend Podcast Ep. 09: Andreas Evers test drives Lagomin comparison with Spring Cloud: http://bit.ly/25XVT8w
![Page 48: Lagom in Practice](https://reader030.vdocument.in/reader030/viewer/2022021500/587331c11a28ab596c8b6bf5/html5/thumbnails/48.jpg)
THANKS FOR WATCHING!