35,99 €
Build fault-tolerant, robust, and distributed applications in Scala
Reactive programming is a scalable, fast way to build applications, and one that helps us write code that is concise, clear, and readable. It can be used for many purposes such as GUIs, robotics, music, and others, and is central to many concurrent systems. This book will be your guide to getting started with Reactive programming in Scala.
You will begin with the fundamental concepts of Reactive programming and gradually move on to working with asynchronous data streams. You will then start building an application using Akka Actors and extend it using the Play framework. You will also learn about reactive stream specifications, event sourcing techniques, and different methods to integrate Akka Streams into the Play Framework. This book will also take you one step forward by showing you the advantages of the Lagom framework while working with reactive microservices. You will also learn to scale applications using multi-node clusters and test, secure, and deploy your microservices to the cloud.
By the end of the book, you will have gained the knowledge to build robust and
distributed systems with Scala and Akka.
This book is for Scala developers who would like to build fault-tolerant, scalable distributed systems. No knowledge of Reactive programming is required.
Rambabu Posa has been working as Java developer since 2004 and a Scala developer since mid-2015. He loves Functional Programming in the Test-Driven Development way to develop Reactive microservices. He loves teaching and has been giving online training and writing tutorials on both the Java and Scala ecosystems. He loves developing Reactive systems using Lightbend's Reactive Platform Technology stack like Lagom Framework, ConductR, Scala, Akka Toolkit, Akka Streams, Play Framework, and others.Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 460
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Merint MathewAcquisition Editor: Karan SadawanaContent Development Editor: Akshada IyerTechnical Editor: Abhishek SharmaCopy Editor: Pranjali Chury, Safis EditingProject Coordinator: Prajakta NaikProofreader: Safis EditingIndexer: Priyanka DhadkeGraphics: Jisha ChirayilProduction Coordinator: Nilesh Mohite
First published: February 2018
Production reference: 1270218
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78728-864-5
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Rambabu Posa has been working as Java developer since 2004 and a Scala developer since mid-2015. He loves Functional Programming in the Test-Driven Development way to develop Reactive microservices. He loves teaching and has been giving online training and writing tutorials on both the Java and Scala ecosystems. He loves developing Reactive systems using Lightbend's Reactive Platform Technology stack like Lagom Framework, ConductR, Scala, Akka Toolkit, Akka Streams, Play Framework, and others.
Pavlo Lysak is a seasoned developer with 10 years of experience in JVM and languages that run on it. He has previously worked on Java, that is, JavaEE and Spring, however, since the past 5 years, he has been working mostly with Scala, that is, Play, Akka, and Spark. After working with companies such as Jaspersoft, Kreditech, and more, he became an independent consultant. His daily work includes the development of Reactive Web Applications and RESTful services, taking care of their stability, maintainability, and transparency.
Dave Wentzel is the Chief Technology Officer (CTO) of Capax Global, a premier Microsoft consulting partner. He is responsible for setting the strategy and defining service offerings and capabilities for the data platform and Azure practice at Capax. Dave also works directly with clients to help them with their big data journey. He is a frequent blogger and speaker on big data and data science topics.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Scala Reactive Programming
Dedication
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the author
About the reviewers
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Getting Started with Reactive and Functional Programming
Introduction to Reactive
What is Reactive?
What is Reactive programming?
What is a data stream or stream?
RP versus Reactive systems versus Reactive architecture
Event-Driven versus Message-Driven
Benefits of Reactive systems with RP
Functional programming
What is functional programming?
Principles of functional programming
Benefits of functional programming
Functional Reactive programming
Types of RP
Why FP is the best fit for RP
Reactive Manifesto
Need of Reactive Manifesto
Principles of Reactive systems
Message-Driven
Elasticity
Resilience
Responsiveness
Why Reactive Streams specification?
Why is Play Framework the best for Reactive systems?
Reactive systems versus traditional systems
The Java 9 Flow API
Flow API – Publisher
Flow API – Subscriber
Flow API – Subscription
Flow API – Processor
Flow API – Flow
Implementations of Reactive Streams
Lightbend's Reactive Platform
Pivotal's Reactor project
Microsoft's Reactive Extensions (RX)
Netflix's RxJava
Eclipse's Vert.x
Ratpack
How are Reactive Streams born?
Marble diagrams
What is a Marble diagram?
Data transformation
Benefits of Marble diagrams
Rules of Marble diagrams
Important FRP operators
FRP – the map() function Marble diagram
FRP – the flatMap() function Marble diagram
FRP – the merge() function Marble diagram
FRP – the filter() function Marble diagram
FRP – the reduce() function Marble diagram
FRP – the concat() and sorted() functions Marble diagram
Observer pattern versus Reactive pattern
Summary
Functional Scala
Introduction to Scala
The Scala ecosystem
Understanding the Scala Application
Scala REPL
Principles of Scala FP
FP Design Patterns
Scala FP features in action
Immutability
Scala functions
Scala pure functions
Pattern matching
Scala combinators
For-comprehensions
Scala implicits
Implicit parameters
Implicit conversions
Scala anonymous functions
Everything is an expression
Referential transparency
Functions are first-class citizens
Partial functions
Function currying
Higher-Order Functions
Scala tail-recursion
Types of recursions
Benefits of linear recursion
A linear-recursion example
Benefits of tail-recursion
A tail-recursion example
Scala Type class
Benefits of Type classes
Scala Collections in action
Scala List
Scala List Cons operator
Right associative rule
Scala Map
Scala Range
Scala Functional Design Patterns
Scala map() function
Scala flatMap() function
Advantages of flatMap
Scala Monads in action
Scala Option
Scala Either
Scala Case class and object
Benefits of Scala Case class
Scala Traits in action
Trait as an interface
Traits linearization 
Linearization rules
Summary
Asynchronous Programming with Scala
Introduction to Scala AP
What is asynchronous?
Differences between asynchronous and synchronous
Benefits of asynchronous programming
Differences between Concurrency and Parallelism
How Scala supports AP
The Scala Future API
Building blocks of the Scala Future API
Benefits of the Scala Future API
The Scala Future
What is a Future in Scala?
The Scala Future API
What is a computation unit?
Future Trait definition
Future Companion object
The complete Scala Future API
Scala Future examples
The Scala Promise
What is a Scala Promise?
The Scala Promise API
Scala Promise examples
Scala ExecutionContext
What is ExecutionContext?
The relationship between Scala Future components
Differences between a Future and a Promise
Scala Future API callbacks
Scala Future API combinators
Scala Future.sequence()
The Scala Async Library
Scala Async API
The Scala Future API in Play Framework
The Scala Future API in the Akka Toolkit
A Scala Future versus a Java Future
Summary
Building Reactive Applications with Akka
Introduction to Akka
What is Akka?
Applications on the JVM (Java Virtual Machine)
Features of Akka
Benefits of Akka (or why do we need Akka?)
Building blocks of the Akka Toolkit
Akka Extensions (or modules)
Akka Clients
Actor Model in-depth
What is the Actor Model?
Principles of the Actor Model (or properties of Actor in the Actor Model)
Issues with the Shared-State Concurrency model
Benefits of the Actor Model
Components of the Actor Model (or building blocks of the Actor Model)
What are the benefits of immutable messages in the Actor Model?
How Akka implements the Actor Model
Other Actor Model implementations
Akka ActorSystem
What is the ActorSystem?
Roles and responsibilities of ActorSystem
How to create an Akka ActorSystem?
How to shut down an Akka ActorSystem?
Components of Akka's ActorSystem
What is materialization and Akka's implementation?
Akka Actors
What is an Actor?
Components of Akka Actor
Akka Actor – ActorRef
Akka Actor – Dispatcher
Benefits of the dispatcher pattern
Akka Actor – Mailbox(MessageQueue)
Akka Actor – Actor
Akka Actor – ActorPath
Actor versus thread
The lifecycle of an Akka Actor
Actor's preStart() lifecycle method
Actor's postStop() lifecycle method
Actor's preRestart() lifecycle method
Actor's postRestart() lifecycle method
Why Actors are lightweight?
Actor basic operations
Defining an Actor
Creating an Actor
Sending messages to an Actor
The tell (!) function
The ask (?) function
Replaying messages from an Actor
Actor to Actor communication
Actor to non-Actor communication
Stopping an Actor
Killing an Actor
Become/unbecoming an Actor
Case object Switch
Supervise an Actor
Akka Supervision
What is supervision?
What is the main goal of Akka's supervision?
Benefits of supervision
Why don't we write exceptions or failures handling in Actor itself?
Rules of Akka Supervision
Akka Supervision strategies
Akka's supervision hierarchy
Actor's Path
What is Akka's Let It Crash model?
Akka HelloWorld Actor example
Akka Actors communicate example
Akka Actor's lifecycle example
Akka parent-child Actors example
Actor's Path versus Reference
Differences between ActorRef and ActorPath
When we execute actorRef.tell (message), what happens internally?
MessageDispatcher
How to configure a dispatcher?
Akka Configuration
Akka SBT Templates
Akka Logging
Business problem
Problem discussion
Akka Actor's implementation
Summary
Adding Reactiveness with RxScala
Introduction to RxScala
Reactive Extensions
Understanding Rx implementations
RxScala
Benefits of Reactive Extensions
Limitations of Reactive Extensions
Building blocks of RxScala
Understanding the Observable
Developing RxScala HelloWorld with an Observable
Observer
Extending RxScala HelloWorld with Observer
Subscriber
Extending RxScala HelloWorld with Subscriber
Subscription
Scheduler
RxScala Marble diagrams
RxScala's map() function
Summary
Extending Applications with Play
Introduction to Play Framework
What is Play Framework?
Features of Play Framework
Benefits of Play Framework
Why Play Framework is so fast?
Clients of Play Framework
Building blocks of Play Framework
Play Routings
Client Request
Controller Action
Routes
Play Controllers
View Templates
Benefits of Twirl Templates
Model and Forms
Other components – services and repositories
Configuration
Play Framework View Template constructs
Twirl View Templates
Twirl Template Constructs
Architecture of Play Framework
The new features of Play Framework
Play Framework 2.5.x features
Play Framework 2.6.x features
Play Application project structure
Play/Scala HelloWorld example
What is Play Dependency Injection (DI)
Benefits of DI
Extend HelloWorld Example With DI
Extending HelloWorld example with Scala Futures
Play Form – Data Model
Play Framework Form API
Play Form – Binding Data
Play Form functions
Play Framework Form-based web application
Extending Play/Scala HelloWorld example with Akka Toolkit
Play Fileupload web application
Summary
Working with Reactive Streams
Introduction to Akka Streams
What is a stream?
Goals of data streaming
What is Akka Streams?
Goals of the Akka Streams API
Features of the Akka Streams API
Benefits of the Akka Streams API
Why do we need Akka Streams and why not just Akka?
Other Reactive Streams implementations
Components of Akka Streams
The Akka Streams API
What is streaming data?
The Akka Streams Source component
The Akka Streams Sink component
The Akka Streams Flow component
RunnableGraph or Graph
Modules of Akka Streams
Akka Materialization
What is materialization?
Akka's Materializer
Akka's ActorMaterializer
Roles and responsibilities of Akka's ActorMaterializer
Akka's Actor versus Akka Stream's ActorMaterializer
Backpressure
The traditional backpressure approach
Push – Fast Producer / Slow Consumer
Pull – Slow Producer/Fast Consumer
The dynamic push/pull model
Akka Streams programming basics
Creating a Source
Creating a Sink
Connect a Source to a Sink
Creating a Flow
Connecting a Source to a Flow to a Sink
Why do we need ActorSystem and ActorMaterializer?
Akka Streams HelloWorld example
Extending the Akka Streams HelloWorld example with the Flow component
HelloWorld example description
Akka Streams GraphDSL
Goal of Akka Streams Graph DSL
Building blocks of Akka Streams Graph DSL
Fan-In functions
Fan-Out functions
Edge operator
An Akka Streams GraphDSL example
Akka Persistence
Akka Persistence features
The ES (Event Sourcing) model
What is an Event?
An Event Stream
Principles of an Event Sourcing (ES) model
Event sourcing
The CQRS pattern
Benefits of CQRS
How Akka Persistence implements CQRS/ES
How to develop Akka Persistence Actors
Step1 – Use the PersistenceActor trait
Step2 – Implement PersistenceActor's receiveRecover
Step3 – Implement PersistenceActor's receiveCommand
Step4 – Implement PersistenceActor's persistenceId
Step5 – Configure our journal details in application.conf
Akka Persistence MongoDB Weather example
Summary
Integrating Akka Streams to Play Application
Akka Streams
Akka Streams revisited
Types of Akka Stream components
Akka Dynamic Streams
MergeHub
BroadcastHub
PartitionHub
Developing Akka Dynamic Streams
Integrating Akka Streams into Play
Designing a Reactive Chat System
Developing the Reactive Chat System
Test Reactive Chat Application
Akka Persistence Query
Building blocks of Akka Persistence App
Developing WF Reactive Akka Persistence App
Testing WF Reactive Akka Persistence App
Summary
Reactive Microservices with Lagom
Introduction to Lagom Framework
What is Lagom Framework?
Features of Lagom Framework
Benefits of Lagom Framework
Drawbacks of monolith architecture
Benefits of microservice architecture
Principles of microservices
Lagom Reactive Platform architecture
Modules of Lagom Framework
Lagom Core modules
Lagom Scala Core modules
Lagom Persistence modules
Lagom Clustering modules
Lagom Kafka modules
Lagom logging module
Building blocks of Lagom Framework
Lagom Service Locator
Lagom Service Gateway
Lagom Service Descriptor
Lagom Framework's identifiers
Lagom ServiceCall in detail
Description
Internal components of Lagom Framework
Kafka with ZooKeeper
Cassandra
Lagom project structure
Lagom System API
Lagom System – implementation
Lagom System – frontend
Lagom Hello Reactive System
Getting Hello Service code
Testing the Hello Reactive System
Lagom Hello Reactive System microservices
Understanding the Hello Service API code
Understanding HelloService implementation code
Developing Lagom WF Reactive System
WF Reactive System architecture
WF Reactive System – Producer API
WF Reactive System – Producer implementation
WF Reactive System – Consumer API
WF Reactive System – Consumer implementation
WF Reactive System – frontend
Testing the WF Reactive System
Summary
Testing Reactive Microservices
Introduction to TDD
What is TDD?
Code Coverage
Benefits of TDD
Unit testing frameworks
ScalaTest
ScalaTest Plus
Benefits of ScalaTest
Unit testing Scala applications
Unit testing Play Framework components
Test HelloWorld without using DI Controller
Test HelloWorld with DI Controller
Unit testing Akka Actors
Akka Toolkit's testing modules
Testing HelloWorld Actor
Unit testing HelloWorldActor (Version 2)
Executing HelloWorld Actor unit tests
Unit testing Akka Streams
Uniting test Akka Streams, with Actor's Testkit
Unit testing Akka Streams with Akka Stream's Testkit
Unit testing Lagom services
The Code Coverage tool
The SCoverage tool
SBT SCoverage plugin
Summary
Managing Microservices in ConductR
Introduction to Lightbend's ConductR
What is ConductR?
Responsibilities of ConductR
Advantages of ConductR
Components of ConductR
ConductR APIs
The Bundle API
The Control API
Installing Lightbend ConductR
Prerequisites
Installing the ConductR CLI
ConductR Sandbox Visualizer
Understanding ConductR Sandbox information
Preparing WF Reactive System for ConductR
ConductRSBT plugin
Mix ConductRApplicationComponents trait
Deploying the WF Reactive System on ConductR
Starting ConductR Sandbox with multinodes
Starting ConductR Sandbox with a single node
Bundle WF Reactive System components
Observing the WF Reactive System bundles
ConductR Bundle descriptor
Loading WF Reactive System bundles
Load wf-producer-impl
Loading wf-consumer-impl
Loading wf-frontend
Running and testing WF Reactive System bundles
Useful ConductR commands
Summary
Reactive Design Patterns and Best Practices
Understanding Design Patterns
Understanding Let-it-Crash
The Circuit Breaker pattern
Understanding the Circuit Breaker pattern
With or without Circuit Breaker
How a Circuit Breaker works
The Sharding Pattern
The Event Sourcing pattern
The Event Streaming Pattern
The Active-Passive Replication Pattern
The Resource Management Design Patterns
The Reactive Resource Loan pattern
The Reactive Resource Pool pattern
Message Flow Patterns
The Request-Response Design Pattern
Understanding the Reactive Design Pattern
Ask Reactive Design Pattern
The Throttling Pattern
The Pull pattern
Reactive System's best practices and tools
Tools
Useful best practices
Prefer tell over ask with Akka Actors
Don't sequentialize Futures
Summary
Scala Plugin for IntelliJ IDEA
Understanding Scala Plugin
How to set up Scala Plugin for IntelliJ IDE
Summary
Installing Robomongo
What is Robomongo?
Setting up Robomongo
How to use Robomongo?
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
This book is all about how to develop Reactive systems using the Functional Reactive Programming (FRP) style. It is a combination of both Functional Programming (FP) and Reactive Programming(RP) styles.
Scala is a multi-paradigm language that supports both FP and RP very well. It also has an AP (Asynchronous Programming) API. It supports Concurrency and true Parallelism using the Future API and Akka's Actor Model.
We will develop a couple of Reactive microservices using Lightbend's Reactive Platform, that is, Scala, Akka, Akka Streams, Play Framework, and Lagom Framework. We will deploy and test our Reactive system into Lightbend's ConductR sandbox environment.
This book is for Scala developers who have knowledge of the basics of Scala, SBT, and the IntelliJ IDEA and want to update their skills to develop Reactive microservices using Lightbend's Reactive Platform.
Chapter 1, Getting started With Reactive and Functional Programming, covers the FP, RP, and FRP paradigm in detail. It covers the Reactive Manifesto and explains how it solves most of the current systems' issues. It also discusses the Actor Model and the Shared-State Concurrency model. This chapter ends with Marble diagrams.
Chapter 2, Functional Scala, explains some of Scala's important Functional Programming features at a high level with some simple and useful examples.
Chapter 3, Asynchronous Programming with Scala, explains Scala's Future API, how it solves Concurrency issues, and how it supports asynchronous programming.
Chapter 4, Building Reactive Applications with Akka, explains about the Actor Model and Akka Toolkit concepts. It demonstrates how to develop Reactive applications using Akka's Actor Model and how it solves shared-state concurrency issues.
Chapter 5, Adding Reactiveness with RxScala, explains some basics of Reactive Extensions for Scala, that is, RxScala. Even though RxScala does not support full-fledged FRP functionality, it supports RP using Observables.
Chapter 6, Extending Applications with Play, introduces you to Play Framework, a full-stack web application framework. Even though Play Framework supports two separate APIs—one for Scala and another for Java, we will develop Reactive Web Applications using Play and Scala technologies.
Chapter 7, Working with Reactive Streams, explains the Akka Streams API, Akka's Reactive Streams implementations. It is a separate module or library from Akka Toolkit for developing streaming data applications using Akka's Actor model under the hood. We will develop a graph-based Streaming data application using Akka Streams Graph DSL.
Chapter 8, Integrating Akka Streams to Play Application, focuses on how to integrate the Akka Streams API into the Play web application and develop a multi-user chat application. It introduces you to Akka Stream’s dynamic streaming components.
Chapter 9, Reactive Microservices With Lagom, introduces Lightbend's new Reactive microservices framework, Lagom. It supports developing Reactive systems easily using Play, Akka, and Scala under the hood.
Chapter 10, Testing Reactive Microservices, explains what TDD is and its benefits. It's a good Agile practice to develop our application components by following the unit testing approach.
Chapter 11, Managing Microservices in ConductR, focuses on how to set up, deploy, and test our Reactive microservices locally using Lightbend's sandbox environment, ConductR.
Chapter 12, Reactive Design Patterns and Best Practices, explains Reactive design patterns and Reactive principles and best practices to develop Reactive systems easily.
Appendix A, Scala Plugin for IntelliJ IDEA, demonstrates how to install Scala Plugin for IntelliJ IDE and use it.
Appendix B, Installing Robomongo, shows a sequence of steps on how to setup and use Robo 3T or Robomongo tool to access our local MongoDB collections.
Readers are expected to have some knowledge of Scala, SBT, and the IntelliJ IDEA or any IDE usage. Familiarity with at least one web application development framework will make learning another web framework easy.
Readers should have Java 8, SBT, IntelliJ IDEA, and Scala in their local systems.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Scala-Reactive-Programming. In case there's an update to the code, it will be updated on the existing GitHub repository.
For more useful information and examples you can visit the following repository:
https://github.com/rposa-srp-book/srp-book-examples
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/ScalaReactiveProgramming_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: " The map() function does not give us the expected results, so we only use flatMap() function."
A block of code is set as follows:
object HelloWorldApp extends App{ println("Hello Scala World!") }
Any command-line input or output is written as follows:
For comprehension addition output: Some(Success(30))
Scala Future API addition output: Some(Success(30))
Scala Async API addition output: Some(Success(30))
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Go to Configure at the bottom right and click on the Plugins option available in the drop-down."
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
In recent times, the word Reactive has gained popularity far and wide. We can see this word in all IT books, magazines, blogs, tutorials, videos on YouTube, and so on.
Almost all programming languages, tools, IDEs, and platforms already support the Reactive architecture and the rest will move to it soon.
Here are some terms that are commonly heard in the Reactive world:
Reactive, Reactiveness, Reactive Manifesto, and Reactive Streams
Reactive programming
(
RP
),
Function Reactive Programming
(
FRP
), OOP RP, Imperative RP, and Reactive Engine
Reactive system, Reactive applications, Reactive microservices, and Reactive Web Applications
Reactive Architecture, Reactive Design Patterns, and Reactive principles
Reactive tools, Reactive Platform, and Lightbend Reactive Platform
Reactive Extensions
(
Rx
)—Rx Scala, Rx Java, Scala, Akka, Play Framework
Java Reactive API and Spring Reactor project
Are you really curious to know what Reactive is? Do you have the following questions and more in your mind—What is Reactive programming? Why do we need it? How do we write RP? Why is FP good for RP? What are the benefits of RP?
If yes, this book is for you. I'll introduce you to the Reactive World in a simple and easy way. I like a Diagram/Example-driven approach to learn new concepts and I feel you will like it too.
We can develop Reactive applications using a wide variety of languages or technologies. However, we will use Lightbend Reactive Platform in this book to develop our Reactive microservices.
Welcome to the Reactive World! Let's understand the Reactive World now. In this chapter, we will discuss the following topics:
What is Reactive? What is RP and FRP? What are the benefits of RP?
What is the Reactive Manifesto and what are its main goals?
Why is FP the best fit for RP?
What is the Java Reactive Streams API?
A discussion on the Flow API
What are Reactive Extensions?
What is the difference between Reactive and Observer Design Patterns?
What are RP Operators?
Marble diagrams for RP Operators
Before diving into the Reactive Manifesto, Reactive Streams Specification, or Java 9 Flow API, and Functional Reactive Programming (FRP), we will first understand the meaning of Reactive and Reactive programming in this section.
Reactive means reacting to changes in a timely manner or responding to changes in a timely manner.
Here, in the Reactive World, we can represent a change as an event. So we can also define Reactive as reacting to events in a timely manner. This change can occur on data or data elements.
Whenever a change occurs in our system, the system should react to those changes immediately in a timely manner. In the current world, users expect a response from an application (website, web application, mobile application, and so on) quickly and in a timely manner. If the system or application does not respond to the user (or customer) in a timely manner, the user will look for some other option and our application will lose its users.
In the Merriam Webster dictionary, Reactive means being readily responsive to a stimulus (check out https://www.merriam-webster.com/dictionary/Reactive).
Unlike imperative programming (IP) or (Object-Oriented Programming) OOP, where we write our code in terms of the order of lines or statements, in Reactive programming (RP), we write the code or programs in terms of events.
In simpler words, RP means writing programs using events, or RP means writing programs that define how to react to events. As we discussed, events are changes in the state of the program or application. So we can also define RP as follows:
Reactive programming is a kind of programming paradigm to that propagates changes.
Let's discuss one of the important and frequently used RP examples (almost all books or tutorials use the same scenario). Consider the following example of a spreadsheet application:
Observe that the A3 cell has a formula =A1+A2, that is, A3 is the sum of the values of the cells A1 and A2.
Initially, A3 has a value of 0. When we change the value of cell A1 or A2, or both, the spreadsheet updates the value of A3:
We can observe that the cell A3 is updated with 3 automatically; this is Reactive programming.
A Reactive system is a set of components that communicate with each other reactively. By combining those individual components into one, we can form a modern distributed system. We can develop a Reactive system by following a set of architectural design principles.
Reactive system components work as a single system and they react to changes in a timely manner.
Reactive systems or Reactive applications have the following features:
Responsiveness
: They react to users in a timely manner
Elasticity
: They react to load
Resilience
: They react to failures
Message-Driven
: They react to events or messages
We will discuss these components of Reactive Streams in detail in the Reactive Manifesto section. Reactive Architecture is a technique or a process of designing Reactive systems.
We can develop Reactive systems using many techniques. However, RP or FRP are the best tools to build Reactive systems.
The core principle of a Reactive system is developing its components using a Message-Driven approach, whereas RP is all about writing programs using events, which means it follows an Event-Driven approach.
As we said, a Reactive system is a set of components. We use RP at the component level, which means that we develop each component using RP. We use a Reactive system at the system level.
The core principle of RP is the Event-Driven approach, whereas the core principle of a Reactive system is the Message-Driven approach.
RP gives us the benefits at component level only because events are emitted and processed locally. They cannot work across the network in a distributed system.
Reactive systems give us the benefits at the system level, because messages are processed and communicated across the network in a distributed system.
We cannot get the full benefits just with RP; we should use the combination of RP and the Reactive system.
In a Reactive system with RP, generated events are represented as messages under-the-hood, and they are processed as messages.
We will get more benefits when we use RP as a programming paradigm to develop the components of a Reactive system. The combination of RP and Reactive systems gives us the following benefits:
Self-healing
: As per the Reactive Streams specification, RP should support Resilience. This means we can write Reactive systems in a way that they have some technique to recover from failure and continue working to give responses to the clients. This is known as self-healing. A client will not know about this, and they will never see those failures.
Highly available systems
: As per the Reactive Streams specification, RP should support Elasticity (scale up/down and scale out/in). This means we can write Reactive systems in a way that they are always available. They support 100% up time.
Highly Scalable to support heavy loads.
Loose coupling.
Utilizes system resources (both hardware and software) efficiently.
Provides better responsiveness.
Provides real-time behavior or data streaming.
Easy to perform distributed data processing.
Supports Location Transparency.
Low latency.
Better performance.
Ease of maintainability.
No need to use anonymous callbacks (so no more callback hell).
Easy to address and handle failures.
Easy to reason about failures.
We should also understand the things that are forcing us to develop and use Reactive systems:
IoT
(
Internet of Things
)
Cloud environment or services
Big data systems
Real-time fast data streaming
Mobile architectures
Communication between heterogeneous systems
Multicore hardware architecture
So far, we have discussed Reactive World, that is, RP. Now, it's time to enter the Functional World, that is, functional programming.
So far, we have discussed RP. Now it's time to move to FP (Functional Programming). Before discussing FRP, we should understand what FP is. We will discuss what FP is, its principles, and its benefits in this section.
Like OOP (Object-Oriented Programming), FP is a kind of programming paradigm.
It is a programming style in which we write programs in terms of pure functions and immutable data. It treats its programs as function evaluation.
As we use pure functions and immutable data to write our applications, we will get lots of benefits for free. For instance, with immutable data, we do not need to worry about shared-mutable states, side effects, and thread-safety.
It follows a Declarative programming style, which means programming is done in terms of expressions, not statements.
For instance, in OOP or imperative programming paradigms, we use statements to write programs where FP uses everything as expressions.
FP has the following principles:
Pure functions
Immutable data
No side effects
Referential transparency
(
RT
)
Functions are first-class citizens
Functions that include anonymous functions, higher order functions, combinators, partial functions, partially-applied functions, function currying, closures
Tail recursion
Functions composability
We will discuss these principles or properties of FP in brief here because we have a dedicated chapter on these concepts. Refer to Chapter 2, Functional Scala, to understand these concepts in-depth with some simple examples.
A pure function is a function that always returns the same results for the same inputs irrespective of how many times and where you run this function.
We will get lots of benefits with immutable data. For instance, no shared data, no side effects, thread safety for free, and so on.
Like an object is a first-class citizen in OOP, in FP, a function is a first-class citizen. This means that we can use a function as any of these:
An object
A value
A data
A data type
An operation
In simple words, in FP, we treat both functions and data as the same.
We can compose functions that are in sequential order so that we can solve even complex problems easily. Higher-Order Functions (HOF) are functions that take one or more functions as their parameters or return a function as their result or do both.
For instance, map(), flatMap(), filter(), and so on are some of the important and frequently used higher-order functions. Consider the following example:
map(x => x*x)
Here, the map() function is an example of Higher-Order Function because it takes an anonymous function as its parameter. This anonymous function x => x *x is of type Int => Int, which takes an Int as input and returns Int as its result.
An anonymous function is a function without any name.
Refer to Chapter 2, Functional Scala, to understand these concepts very well. I have provided a useful description and also some simple and easy-to-understand examples.
FP provides us with many benefits:
Thread-safe code
Easy-to-write concurrency and parallel code
We can write simple, readable, and elegant code
Type safety
Composability
Supports Declarative programming
As we use pure functions and immutability in FP, we will get thread-safety for free.
One of the greatest benefits of FP is function composability. We can compose multiple functions one by one and execute them either sequentially or parentally. It gives us a great approach to solve complex problems easily.
Even though most of the projects or companies use FP Paradigm to develop their Reactive systems or solutions, there are a couple of ways to use RP. They are known as types of RP:
FRP
(
Functional Reactive Programming
)
OORP
(
Object-Oriented Reactive Programming
)
However, FP is the best programming paradigm to conflate with RP. We will get all the benefits of FP for free.
When we conflate RP with FP, we will get the following benefits:
Composability—we can compose multiple data streams using functional operations so that we can solve even complex problems easily
Thread safety
Readability
Simple, concise, clear, and easy-to-understand code
Easy-to-write asynchronous, concurrent, and parallel code
Supports very flexible and easy-to-use operations
Supports Declarative programming
Easy to write, more Scalable, highly available, and robust code
In FP, we concentrate on what to do to fulfill a job, whereas in other programming paradigms, such as OOP or imperative programming (IP), we concentrate on how to do.
Declarative programming gives us the following benefits:
No side effects
Enforces to use immutability
Easy to write concise and understandable code
The main property of RP is real-time data streaming, and the main property of FP is composability. If we combine these two paradigms, we will get more benefits and can develop better solutions easily.
In RP, everything is a stream, while everything is a function in FP. We can use these functions to perform operations on data streams.
Reactive Manifesto is a manifesto that describes how to design and architect Reactive systems according to your needs. It describes the four traits of Reactive systems. As of now, we are using Reactive Manifest v.2.0, which was initially published on September 16, 2014.
As per Reactive Manifest 1.0 (initial and old version), Reactive systems are Responsive, Scalable, Resilient, and Event-Driven.
As per Reactive Manifest 2.0, Reactive systems are Responsive, Scalable, Resilient, and Message-Driven.
We can find the manifesto on GitHub as a repository, available at https://github.com/reactivemanifesto/reactivemanifesto.
We need to understand what the main need of Reactive Manifesto is, so that we will get clear picture about it.
The main needs or goals of Reactive Manifesto are as follows:
Users or customers need responses in a timely manner. They don't like slow responses and they don't use slow systems. If they don't get quick responses as needed, they will look for other options.
We should have an API to support asynchronous streaming data with non-blocking backpressure.
API for Reactive Technology (frameworks, tools, languages, IDEs, and so on) implementors.
Heterogeneous Reactive systems should work in an interoperable way.
We should have a better approach for consumers to avoid buffer overflow issues.
In this section, we will discuss what the four traits or principles of Reactive systems are that we should follow to develop Reliable, Flexible, Scalable, Distributable, and Resilient applications.
Reactive Manifesto defines the following four principles:
Message-Driven
Elastic
Resilient
Responsive
This preceding diagram is copied from Reactive Manifesto. These are design and architectural principles. They are also known as the Four tenants of Reactive Streams or Four core building blocks of Reactive Streams.
We will pick up each trait one-by-one and discuss it in detail in subsequent sections.
The last but very important trait is responsiveness. In Reactive systems, Responsive means reacting to the users or customers in a timely manner. Here, we should understand this point—a user should get a response when needed, otherwise they will lose interest and go for other options. In the current Reactive World, the following two things are the same:
Not giving response to users when needed or in a timely manner
Not giving any response to users at all
Even though our system does give a response to the user at a later time, the user does not need it then. Our system loses the users and ultimately, we lose our business.
In simple words, Responsive.
After going through these four traits of a Reactive system, we should understand the following things:
The main goal of a Reactive system is responsiveness
The core method that a Reactive system should follow is Message-Driven
The core principles of a Reactive system are Elasticity and Resilience:
The core method of a Reactive system, that is, the Message-Driven approach, will give us Elasticity and Resilience for free:
These three traits of a Reactive system (that is, Message-Driven, Elasticity, and Resilience) give us the main goal or value of that Reactive system—responsiveness.
After going through the Reactive Manifesto, we can represent it in a pictorial form, as shown here:
In this section, we will understand, first of all, why we really need the Reactive Streams specification. We will also answer a few more questions, like—What is the use of this specification or standard, and who really needs this specification?
RSS (Reactive Streams Specification) is a standard or specification. It explains how to develop frameworks, tools, toolkits, languages, libraries, IDEs, data stores, servers, and so on, which work in Reactive.
Are we getting any benefits by following this specification? Yes. That's why we need this specification.
The main goals or benefits of this specification are as follows:
To support reactiveness
To support interoperability:
If we observe the preceding diagram, we can understand that many applications are using many Reactive technologies. If they follow their own approach to develop their Reactive systems, then it is a bit tough for them to talk to or work with each other. It is possible to implement some kind of adapters or interfaces to fill the gap and make them work with each other. However, it is not only an old and tedious approach, but also outdated and obsolete.
If we have a specification or standard or API similar to the Reactive Streams Specification and everybody develops their tools, frameworks, and so on, by following this, then there will be no need for extra tools, such as adapters. They can work with each other without using any adapters and without any issues.
This means it enables heterogeneous Reactive systems to work with each other, that is, work in an interoperable way.
As a Java or Scala developer, we know what the use of an API is, why we need it, and who needs it. So, we need a Reactive API or standard or specification to implement or develop Reactive libraries, Reactive servers, Reactive languages, Reactive databases, Reactive tools, Reactive applications, or systems.
Initially, a set of developers from top companies such as Lightbend, Netflix, Pivotal, Redhot, and Oracle Corporation worked together on this area and prepared a specification to develop Reactive systems (or applications) easily. This is known as RSS (Reactive Streams Specification). They requested Oracle Corporation introduce an API to develop Reactive systems easily in a way that they should work interoperably. Finally, Oracle Corporation introduced a Reactive Streams API as part of JEP-266 in JDK 9 (Java SE 9). This API is known as the Flow API.
In the next section, we will discuss this Flow API in detail.
Play Framework is the best full-stack web framework available in the current market to develop Reactive Web Applications, Reactive systems, Reactive architecture, Reactive microservices, or Reactive libraries using both FP and RP paradigms, that is, FRP.
The following are the reasons to clarify why Play is good for RP:
Play Framework is built on top of the Akka Toolkit
By design, the Akka Toolkit supports Reactive Architecture using an Actor Model and Akka Streams
Akka Streams is the best Reactive API to develop Reactive data streaming
Play Framework has an integrated module for the Akka Streams API
Play Framework is written in Scala (a JVM language) and supports both Scala and Java programming languages
Both Scala and Java run on JVM
Scala supports FP very well
FP is the best programming paradigm for RP
The latest Play Framework has moved from Iteratees to Reactive Streams
It is a full-stack web framework for Reactive programming
In this section, we will see the main differences between a Reactive system and non-Reactive system, that is, a traditional system.
The first and foremost difference is that a Reactive system takes a user or customer request as an event or message, and then reacts to those events in a timely manner. Once it's done, it continuously looks for the next event, as illustrated here:
