SlideShare a Scribd company logo
1 of 67
Download to read offline
Consuming web services
asynchronously with Futures
and Rx Observables
Chris Richardson
Author of POJOs in Action
Founder of the original CloudFoundry.com
@crichardson
chris@chrisrichardson.net
http://plainoldobjects.com
@crichardson
Presentation goal

Learn how to use (Scala)
Futures and Rx
Observables to write simple
yet robust and scalable
concurrent code
@crichardson
About Chris

@crichardson
About Chris

Founder of a buzzword compliant (stealthy, social, mobile,
big data, machine learning, ...) startup
Consultant helping organizations improve how they
architect and deploy applications using cloud, micro
services, polyglot applications, NoSQL, ...

@crichardson
Agenda

The need for concurrency
Simplifying concurrent code with Futures
Consuming asynchronous streams with Reactive
Extensions

@crichardson
Let’s imagine you are building
an online store

@crichardson
Reviews

Product
Info
Shipping

Recomendations

@crichardson
Product
Info

Sales
ranking

Reviews

@crichardson
Related
books

Forum
Viewing
history

@crichardson
+ mobile apps

@crichardson
Application architecture
Desktop
browser

REST

REST

HTML/
JSON

Product Info Service

Recomendation
Service

REST

Review Service

Front end server
Web Application

Mobile
browser

Native
mobile
client

REST

API gateway

JSON

@crichardson
How does the client get product
details?
Product Info Service
getProductInfo()

Browser/
Client

?

Front-end
server

getRecommendations()

Recommendations
Service

getReviews()

Review
Service
@crichardson
Product details - client-side
aggregation
Product Info Service
getProductInfo()
getProductInfo()

Browser/
Client

getRecommendations()
getReviews()

Front-end
server

getRecommendations()

Recommendations
Service

getReviews()

Requires
good network
performance

Review
Service
@crichardson
Product details - server-side
aggregation
Product Info Service

HTML or JSON
getProductInfo()

Browser/
Client

getProductDetails()

Front-end
server

getRecommendations()

Recommendations
Service

getReviews()

One roundtrip

Review
Service
@crichardson
Product details - server-side
aggregation: sequentially
Product Info Service
getProductInfo()

getProductDetails()

Front-end
server

getRecommendations()

Recommendations
Service

getReviews()

Higher response time :-(

Review
Service
@crichardson
Product details - server-side
aggregation: parallel
Product Info Service
getProductInfo()

getProductDetails()

Front-end
server

getRecommendations()

Recommendations
Service

getReviews()

Lower response
time :-)

Review
Service
@crichardson
Implementing a concurrent
REST client
Thread-pool based approach
executorService.submit(new Callable(...))
Simpler but less scalable - lots of idle threads
consuming memory
Event-driven approach
NIO with completion callbacks
More complex but more scalable

And it must handle partial failures
@crichardson
Agenda

The need for concurrency
Simplifying concurrent code with Futures
Consuming asynchronous streams with Reactive
Extensions

@crichardson
Futures are a great
concurrency abstraction
http://en.wikipedia.org/wiki/Futures_and_promises
@crichardson
How futures work
Main thread

Worker thread or
event-driven

initiates
Client

get

set

Asynchronous
operation

Outcome

Future
@crichardson
Benefits
Simple way for two concurrent activities to communicate safely
Abstraction:
Client does not know how the asynchronous operation is
implemented
Easy to implement scatter/gather:
Scatter: Client can invoke multiple asynchronous operations
and gets a Future for each one.
Gather: Get values from the futures

@crichardson
Front-end server design: handling
GetProductDetails request
ProductDetailsController
getProductDetails()
ProductDetailsService

Proxies

getProductDetails()
ProductInfoService
getProductInfo()

ReviewService
getReviews()

RecommendationService
getRecommendations()

RestTemplate
@crichardson
REST client using Spring @Async
trait ProductInfoService {
def getProductInfo(productId: Long):
java.util.concurrent.Future[ProductInfo]
}
@Component
class ProductInfoServiceImpl extends ProducInfoService {
val restTemplate : RestTemplate = ...

Execute
asynchronously in
thread pool

@Async
def getProductInfo(productId: Long) = {
new AsyncResult(restTemplate.getForObject(....)...)
}
}

A fulfilled Future

@crichardson
ProductDetailsService
@Component
class ProductDetailsService
@Autowired()(productInfoService: ProductInfoService,
reviewService: ReviewService,
recommendationService: RecommendationService) {
def getProductDetails(productId: Long): ProductDetails = {
val productInfoFuture = productInfoService.getProductInfo(productId)
val recommendationsFuture =
recommendationService.getRecommendations(productId)
val reviewsFuture = reviewService.getReviews(productId)
val productInfo = productInfoFuture.get(300, TimeUnit.MILLISECONDS)
val recommendations =
recommendationsFuture.get(10, TimeUnit.MILLISECONDS)
val reviews = reviewsFuture.get(10, TimeUnit.MILLISECONDS)
ProductDetails(productInfo, recommendations, reviews)
}
}

@crichardson
ProductController
@Controller
class ProductController
@Autowired()(productDetailsService : ProductDetailsService)
{
@RequestMapping(Array("/productdetails/{productId}"))
@ResponseBody
def productDetails(@PathVariable productId: Long) =
productDetailsService.getProductDetails(productId)

@crichardson
Not bad but...
class ProductDetailsService
def getProductDetails(productId: Long): ProductDetails = {
val productInfo =
productInfoFuture.get(300, TimeUnit.MILLISECONDS)

Not so scalable :-(

Gathering blocks Tomcat
thread until all Futures
complete

@crichardson
... and also...
Java Futures work well for a single-level of asynchronous
execution

BUT
#fail for more complex, scalable scenarios
Difficult to compose and coordinate multiple concurrent
operations
See this blog post for more details:
http://techblog.netflix.com/2013/02/rxjava-netflix-api.html
@crichardson
Better: Futures with callbacks
no blocking!
def asyncSquare(x : Int)
: Future[Int] = ... x * x...
val f = asyncSquare(25)

Partial function applied to
successful outcome

f onSuccess {
case x : Int => println(x)
Applied to failed outcome
}
f onFailure {
case e : Exception => println("exception thrown")
}
Guava ListenableFutures, Spring 4 ListenableFuture

Java 8 CompletableFuture, Scala Futures

@crichardson
But
callback-based scatter/gather
Messy, tangled code
(aka. callback hell)

@crichardson
Composable futures hide the mess
Combines two futures

val fzip = asyncSquare(5) zip asyncSquare(7)
assertEquals((25, 49), Await.result(fzip, 1 second))

val fseq = Future.sequence((1 to 5).map { x =>
asyncSquare(x)
})

Transforms list of futures to a future

assertEquals(List(1, 4, 9, 16, 25),
Await.result(fseq, 1 second))

Scala, Java 8 CompletableFuture (partially)

@crichardson
zip() is asynchronous
Outcome1

f1
(o1, o2)

f3 = f1 zip f2

f3

Implemented using callbacks

Outcome2

f2
@crichardson
Transforming futures
def asyncPlus(x : Int, y : Int) = ... x + y ...
val future2 = asyncPlus(4, 5).map{ _ * 3 }
assertEquals(27, Await.result(future2, 1 second))
Asynchronously transforms
future

Scala, Java 8 CompletableFuture (partially)

@crichardson
Chaining asynchronous operations
Calls asyncSquare() with the eventual
outcome of asyncPlus()

val f2 = asyncPlus(5, 8).flatMap { x => asyncSquare(x) }
assertEquals(169, Await.result(f2, 1 second))

Scala, Java 8 CompletableFuture (partially)

@crichardson
Scala futures are Monads
Two calls execute in parallel

(asyncPlus(3, 5) zip asyncSquare(5))
.flatMap {
And then invokes asyncPlus()
case (a, b) =>
asyncPlus(a, b) map { _ * 2 }
}
result onSuccess { .... }
x2

Rewrite using ‘for’
@crichardson
Scala futures are Monads
Two calls execute in parallel

val result = for {
(a, b) <- asyncPlus(3, 5) zip asyncSquare(5);
c <- asyncPlus(a, b)
} yield c * 2
result onSuccess { .... }

‘for’ is shorthand for
map() and flatMap()

And then invokes
asyncPlus()

x2

@crichardson
ProductInfoService: using
Scala Futures
import scala.concurrent.Future

Scala Future

@Component
class ProductInfoService {
def getProductInfo(productId: Long): Future[ProductInfo]
= {
Future { restTemplate.getForObject(....) }
}
}

Executed in a threaded pool
@crichardson
ProductDetailsService: using
Scala Futures
class ProductDetailsService ...

Return a Scala Future

def getProductDetails(productId: Long) : Future[ProductDetails] = {
val productInfoFuture = productInfoService.getProductInfo(productId)
val recommendationsFuture =
recommendationService.getRecommendations(productId)
val reviewsFuture = reviewService.getReviews(productId)
for (((productInfo, recommendations), reviews) <productInfoFuture zip recommendationsFuture zip reviewsFuture)
yield ProductDetails(productInfo, recommendations, reviews)

}
}

Gathers data without blocking
@crichardson
Async ProductController: using
Spring MVC DeferredResult
@Controller
class ProductController ... {
@RequestMapping(Array("/productdetails/{productId}"))
@ResponseBody
def productDetails(@PathVariable productId: Long)
: DeferredResult[ProductDetails] = {
val productDetails =
productDetailsService.getProductDetails(productId)
val result = new DeferredResult[ProductDetails]
productDetails onSuccess {
case r => result.setResult(r)
}
productDetails onFailure {
case t => result.setErrorResult(t)
}

Spring MVC
DeferredResult
≅
Future

Convert Scala Future
to
DeferredResult

result
}

@crichardson
Servlet layer is asynchronous
BUT
the backend uses thread
pools
Need event-driven REST
client
@crichardson
Spring AsyncRestTemplate
New in Spring 4
Mirrors RestTemplate
Can use HttpComponents NIO-based AsyncHttpClient
Methods return a ListenableFuture
JDK 7 Future + callback methods

Yet another
“Future”!

@crichardson
ProductInfoService: using the
AsyncRestTemplate
class ProductInfoService {
val asyncRestTemplate = new AsyncRestTemplate(
new HttpComponentsAsyncClientHttpRequestFactory())

override def getProductInfo(productId: Long) = {
val listenableFuture =
asyncRestTemplate.getForEntity("{baseUrl}/productinfo/{productId}",
classOf[ProductInfo],
baseUrl, productId)
toScalaFuture(listenableFuture).map { _.getBody

}

}
Convert to Scala Future and get entity

http://hc.apache.org/httpcomponents-asyncclient-dev/

@crichardson
Converting ListenableFuture to
Scala Future
def toScalaFuture[T](lf : ListenableFuture[T]) :
Future[T] = {
val p = promise[T]()
Creates a promise = producer API
lf.addCallback(new ListenableFutureCallback[T] {
def onSuccess(result: T) { p.success(result)}
def onFailure(t: Throwable) { p.failure(t) }
})
p.future
}
Propagate outcome to promise
Return future
@crichardson
Now everything is nonblocking :-)
We have achieved scaling Nirvana

@crichardson
WT*#*# is my code doing?
Operations initiated in one thread but fail in another
Lack of a full stack trace can make debugging difficult
Inherent problem of async/event driven programming
Futures make it very easy to forget to handle errors
someFuture.foreach { handleTheHappyPath }

Error is quietly ignored: similar to an empty catch {}
block

@crichardson
Agenda

The need for concurrency
Simplifying concurrent code with Futures
Consuming asynchronous streams with Reactive
Extensions

@crichardson
Let’s imagine you have a
stream of trades
and
you need to calculate the 15
minute rolling average price of
each stock
@crichardson
Where is the high-level
abstraction that simplifies
solving this problem?

@crichardson
Future[List[T]]
Not applicable to infinite
streams

@crichardson
Pipes and Filters
e.g. Spring Integration
+
Complex event processing (CEP)

Not bad but tends to be an external DSL,
heavy weight, statically defined, ...

@crichardson
Introducing Reactive
Extensions (Rx)
The Reactive Extensions (Rx) is a library for composing
asynchronous and event-based programs using
observable sequences and LINQ-style query operators.
Using Rx, developers represent asynchronous data
streams with Observables , query asynchronous
data streams using LINQ operators , and .....

https://rx.codeplex.com/
@crichardson
About RxJava
Reactive Extensions (Rx) for the JVM
Original motivation for Netflix was to provide rich Futures
Implemented in Java
Adaptors for Scala, Groovy and Clojure

https://github.com/Netflix/RxJava
@crichardson
RxJava core concepts
An asynchronous
stream of items
trait Observable[T] {
def subscribe(observer : Observer[T]) : Subscription
...
}

Notifies

trait
def
def
def
}

Observer[T] {
onNext(value : T)
onCompleted()
onError(e : Throwable)

Used to
unsubscribe

* Note: with v0.17 subscribe() takes a Subscriber = Observer++
@crichardson
Comparing Observable to...
Observer pattern - similar but adds
Observer.onComplete()
Observer.onError()
Iterator pattern - mirror image
Push rather than pull
Future - similar but
Represents a stream of multiple values
@crichardson
So what?

@crichardson
Fun with observables
val oneItem = Observable.items(-1L)
val every10Seconds = Observable.interval(10 seconds)
val ticker = oneItem ++ every10Seconds
val subscription = ticker.subscribe ( new Observer[Long] {
override def onNext(value: Long) = { println("value=" + value)
})
...
subscription.unsubscribe()

-1

0

1

...

t=0

t=10

t=20

...

}

@crichardson
Creating observables
Observable.create({ observer: Observer[T] =>
...
Function
observer.onNext(...)
called when
...
Observer
observer.onCompleted()
subscribes
...
observer.onError(...)
Called when observer
...
unsubscribes
Subscription{ .... }
}
})

* Note: with v0.17 create() takes a Subscriber = Observer++
@crichardson
Creating observables from
Query AWS
Scala Futures
def getTableStatus(tableName: String) = {
val future = dynamoDbClient.describeTable(new DescribeTableRequest(tableName))
Observable.create({ observer : Observer[DynamoDbStatus] =>
future.onComplete {
case Success(response) =>
observer.onNext(DynamoDbStatus(response.getTable.getTableStatus))
observer.onCompleted()
case Failure(t: ResourceNotFoundException) =>
observer.onNext(DynamoDbStatus("NOT_FOUND"))
observer.onCompleted()
case Failure(someError) =>
observer.onError(someError)
}
Subscription({})
})
}

Propagate@crichardson
outcome
Transforming observables
val tableStatus = ticker.flatMap { i =>
logger.info("{}th describe table", i + 1)
getTableStatus(name)
}
Status1 Status2
t=0

t=10

Status3

...

t=20

...

+ Usual collection methods: map(), filter(), take(), drop(), ...
@crichardson
Back to the stream of Trades
averaging example...

@crichardson
Calculating averages
class AverageTradePriceCalculator {
def calculateAverages(trades: Observable[Trade]):
Observable[AveragePrice] = {
...
}
case class Trade(
symbol : String,
price : Double,
quantity : Int
...
)

case class AveragePrice(
symbol : String,
price : Double,
...)

@crichardson
Using groupBy()
Observable[Trade]

APPL : 401

100

IBM : 405

300

CAT : 405

150

APPL: 403

300

groupBy( (trade) => trade.symbol)

APPL : 401

APPL: 403
IBM : 405
CAT : 405

Observable[GroupedObservable[String, Trade]]

...
@crichardson
Using window()
Observable[Trade]

APPL : 401

APPL : 405

APPL : 405

...

window(...)

5 minutes
APPL : 401

APPL : 405

APPL : 405

APPL : 405

APPL : 403

30 secs

30 secs

APPL : 405

APPL : 405

...

Observable[Observable[Trade]]

@crichardson
Using foldLeft()
Observable[Trade]

APPL : 402

100

APPL : 405

200

APPL : 405

200

foldLeft(0.0)(_ + _.price)
/
foldLeft(0.0)(_ + _.quantity)

APPL : 404.4

Observable[AveragePrice]

Singleton
@crichardson
Using flatten()
Observable[Observable[AveragePrice]]

APPL : 401

APPL: 403
IBM : 405
CAT : 405

...

flatten()

APPL : 401

IBM : 405

Observable[AveragePrice]

CAT : 405

APPL: 403
@crichardson
Calculating average prices
def calculateAverages(trades: Observable[Trade]): Observable[AveragePrice] = {
trades.groupBy(_.symbol).map { symbolAndTrades =>
val (symbol, tradesForSymbol) = symbolAndTrades
val openingEverySecond =
Observable.items(-1L) ++ Observable.interval(1 seconds)
def closingAfterSixSeconds(opening: Any) =
Observable.interval(6 seconds).take(1)
tradesForSymbol.window(...).map {
windowOfTradesForSymbol =>
windowOfTradesForSymbol.fold((0.0, 0, List[Double]())) { (soFar, trade) =>
val (sum, count, prices) = soFar
(sum + trade.price, count + trade.quantity, trade.price +: prices)
} map { x =>
val (sum, length, prices) = x
AveragePrice(symbol, sum / length, prices)
}
}.flatten
}.flatten
}

@crichardson
Summary
Consuming web services asynchronously is essential
Scala-style Futures are a powerful concurrency abstraction
Rx Observables
even more powerful
unifying abstraction for a wide variety of use cases

@crichardson
@crichardson chris@chrisrichardson.net

Questions?

http://plainoldobjects.com

@crichardson

More Related Content

What's hot

Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Chris Richardson
 
Events, Picos, and Microservices
Events, Picos, and MicroservicesEvents, Picos, and Microservices
Events, Picos, and MicroservicesPhil Windley
 
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQCQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQMiel Donkers
 
How to write your database: the story about Event Store
How to write your database: the story about Event StoreHow to write your database: the story about Event Store
How to write your database: the story about Event StoreVictor Haydin
 
Groovy on Grails by Ziya Askerov
Groovy on Grails by Ziya AskerovGroovy on Grails by Ziya Askerov
Groovy on Grails by Ziya AskerovVuqar Suleymanov
 
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Chris Richardson
 
Node.js Enterprise Middleware
Node.js Enterprise MiddlewareNode.js Enterprise Middleware
Node.js Enterprise MiddlewareBehrad Zari
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)Paco de la Cruz
 
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode ObjectsEWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode ObjectsRob Tweed
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersChristopher Batey
 
Post quantum cryptography in vault (hashi talks 2020)
Post quantum cryptography in vault (hashi talks 2020)Post quantum cryptography in vault (hashi talks 2020)
Post quantum cryptography in vault (hashi talks 2020)Mitchell Pronschinske
 
DDD meets CQRS and event sourcing
DDD meets CQRS and event sourcingDDD meets CQRS and event sourcing
DDD meets CQRS and event sourcingGottfried Szing
 
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"Daniel Bryant
 
Microservices: a journey of an eternal improvement
Microservices: a journey of an eternal improvementMicroservices: a journey of an eternal improvement
Microservices: a journey of an eternal improvementAnton Udovychenko
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsChristopher Batey
 
Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Christopher Batey
 
EWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode ObjectEWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode ObjectRob Tweed
 
Cassandra is great but how do I test my application?
Cassandra is great but how do I test my application?Cassandra is great but how do I test my application?
Cassandra is great but how do I test my application?Christopher Batey
 

What's hot (20)

Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
 
Events, Picos, and Microservices
Events, Picos, and MicroservicesEvents, Picos, and Microservices
Events, Picos, and Microservices
 
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQCQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
 
How to write your database: the story about Event Store
How to write your database: the story about Event StoreHow to write your database: the story about Event Store
How to write your database: the story about Event Store
 
Groovy on Grails by Ziya Askerov
Groovy on Grails by Ziya AskerovGroovy on Grails by Ziya Askerov
Groovy on Grails by Ziya Askerov
 
Byte Sized Rust
Byte Sized RustByte Sized Rust
Byte Sized Rust
 
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
Decompose That WAR! Architecting for Adaptability, Scalability, and Deployabi...
 
Node.js Enterprise Middleware
Node.js Enterprise MiddlewareNode.js Enterprise Middleware
Node.js Enterprise Middleware
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)
Serverless APIs, the Good, the Bad and the Ugly (2019-09-19)
 
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode ObjectsEWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java Developers
 
Post quantum cryptography in vault (hashi talks 2020)
Post quantum cryptography in vault (hashi talks 2020)Post quantum cryptography in vault (hashi talks 2020)
Post quantum cryptography in vault (hashi talks 2020)
 
DDD meets CQRS and event sourcing
DDD meets CQRS and event sourcingDDD meets CQRS and event sourcing
DDD meets CQRS and event sourcing
 
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"
KubeCon EU 2019 "Securing Cloud Native Communication: From End User to Service"
 
Microservices: a journey of an eternal improvement
Microservices: a journey of an eternal improvementMicroservices: a journey of an eternal improvement
Microservices: a journey of an eternal improvement
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra Applications
 
Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014Fault tolerant microservices - LJC Skills Matter 4thNov2014
Fault tolerant microservices - LJC Skills Matter 4thNov2014
 
EWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode ObjectEWD 3 Training Course Part 20: The DocumentNode Object
EWD 3 Training Course Part 20: The DocumentNode Object
 
Cassandra is great but how do I test my application?
Cassandra is great but how do I test my application?Cassandra is great but how do I test my application?
Cassandra is great but how do I test my application?
 

Similar to Futures and Rx Observables: powerful abstractions for consuming web services asynchronously (devnexus2014)

Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Chris Richardson
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)Chris Richardson
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSuzquiano
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!Guido Schmutz
 
Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Orkhan Gasimov
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 
Vertx - Reactive & Distributed
Vertx - Reactive & DistributedVertx - Reactive & Distributed
Vertx - Reactive & DistributedOrkhan Gasimov
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB
 
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...MSDEVMTL
 
The Reactive Rollercoaster
The Reactive RollercoasterThe Reactive Rollercoaster
The Reactive RollercoasterBol.com Techlab
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020Matt Raible
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenJoshua Long
 
The Windows Runtime and the Web
The Windows Runtime and the WebThe Windows Runtime and the Web
The Windows Runtime and the WebJeremy Likness
 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJoshua Long
 
Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)Chris Richardson
 
Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...Chris Richardson
 

Similar to Futures and Rx Observables: powerful abstractions for consuming web services asynchronously (devnexus2014) (20)

Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!
 
Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]
 
MvvmCross Quickstart
MvvmCross QuickstartMvvmCross Quickstart
MvvmCross Quickstart
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Vertx - Reactive & Distributed
Vertx - Reactive & DistributedVertx - Reactive & Distributed
Vertx - Reactive & Distributed
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
 
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...
Stephane Lapointe, Frank Boucher & Alexandre Brisebois: Les micro-services et...
 
The Reactive Rollercoaster
The Reactive RollercoasterThe Reactive Rollercoaster
The Reactive Rollercoaster
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
 
The Windows Runtime and the Web
The Windows Runtime and the WebThe Windows Runtime and the Web
The Windows Runtime and the Web
 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with Spring
 
Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)Microservices in Java and Scala (sfscala)
Microservices in Java and Scala (sfscala)
 
Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...
 

More from Chris Richardson

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?Chris Richardson
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternChris Richardson
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...Chris Richardson
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Chris Richardson
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsChris Richardson
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfChris Richardson
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Chris Richardson
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...Chris Richardson
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Chris Richardson
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 Chris Richardson
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureChris Richardson
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Chris Richardson
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled servicesChris Richardson
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Chris Richardson
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...Chris Richardson
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Chris Richardson
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...Chris Richardson
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationChris Richardson
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate PlatformChris Richardson
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolithChris Richardson
 

More from Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Recently uploaded

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 

Recently uploaded (20)

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 

Futures and Rx Observables: powerful abstractions for consuming web services asynchronously (devnexus2014)

  • 1. Consuming web services asynchronously with Futures and Rx Observables Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson chris@chrisrichardson.net http://plainoldobjects.com @crichardson
  • 2. Presentation goal Learn how to use (Scala) Futures and Rx Observables to write simple yet robust and scalable concurrent code @crichardson
  • 4. About Chris Founder of a buzzword compliant (stealthy, social, mobile, big data, machine learning, ...) startup Consultant helping organizations improve how they architect and deploy applications using cloud, micro services, polyglot applications, NoSQL, ... @crichardson
  • 5. Agenda The need for concurrency Simplifying concurrent code with Futures Consuming asynchronous streams with Reactive Extensions @crichardson
  • 6. Let’s imagine you are building an online store @crichardson
  • 11. Application architecture Desktop browser REST REST HTML/ JSON Product Info Service Recomendation Service REST Review Service Front end server Web Application Mobile browser Native mobile client REST API gateway JSON @crichardson
  • 12. How does the client get product details? Product Info Service getProductInfo() Browser/ Client ? Front-end server getRecommendations() Recommendations Service getReviews() Review Service @crichardson
  • 13. Product details - client-side aggregation Product Info Service getProductInfo() getProductInfo() Browser/ Client getRecommendations() getReviews() Front-end server getRecommendations() Recommendations Service getReviews() Requires good network performance Review Service @crichardson
  • 14. Product details - server-side aggregation Product Info Service HTML or JSON getProductInfo() Browser/ Client getProductDetails() Front-end server getRecommendations() Recommendations Service getReviews() One roundtrip Review Service @crichardson
  • 15. Product details - server-side aggregation: sequentially Product Info Service getProductInfo() getProductDetails() Front-end server getRecommendations() Recommendations Service getReviews() Higher response time :-( Review Service @crichardson
  • 16. Product details - server-side aggregation: parallel Product Info Service getProductInfo() getProductDetails() Front-end server getRecommendations() Recommendations Service getReviews() Lower response time :-) Review Service @crichardson
  • 17. Implementing a concurrent REST client Thread-pool based approach executorService.submit(new Callable(...)) Simpler but less scalable - lots of idle threads consuming memory Event-driven approach NIO with completion callbacks More complex but more scalable And it must handle partial failures @crichardson
  • 18. Agenda The need for concurrency Simplifying concurrent code with Futures Consuming asynchronous streams with Reactive Extensions @crichardson
  • 19. Futures are a great concurrency abstraction http://en.wikipedia.org/wiki/Futures_and_promises @crichardson
  • 20. How futures work Main thread Worker thread or event-driven initiates Client get set Asynchronous operation Outcome Future @crichardson
  • 21. Benefits Simple way for two concurrent activities to communicate safely Abstraction: Client does not know how the asynchronous operation is implemented Easy to implement scatter/gather: Scatter: Client can invoke multiple asynchronous operations and gets a Future for each one. Gather: Get values from the futures @crichardson
  • 22. Front-end server design: handling GetProductDetails request ProductDetailsController getProductDetails() ProductDetailsService Proxies getProductDetails() ProductInfoService getProductInfo() ReviewService getReviews() RecommendationService getRecommendations() RestTemplate @crichardson
  • 23. REST client using Spring @Async trait ProductInfoService { def getProductInfo(productId: Long): java.util.concurrent.Future[ProductInfo] } @Component class ProductInfoServiceImpl extends ProducInfoService { val restTemplate : RestTemplate = ... Execute asynchronously in thread pool @Async def getProductInfo(productId: Long) = { new AsyncResult(restTemplate.getForObject(....)...) } } A fulfilled Future @crichardson
  • 24. ProductDetailsService @Component class ProductDetailsService @Autowired()(productInfoService: ProductInfoService, reviewService: ReviewService, recommendationService: RecommendationService) { def getProductDetails(productId: Long): ProductDetails = { val productInfoFuture = productInfoService.getProductInfo(productId) val recommendationsFuture = recommendationService.getRecommendations(productId) val reviewsFuture = reviewService.getReviews(productId) val productInfo = productInfoFuture.get(300, TimeUnit.MILLISECONDS) val recommendations = recommendationsFuture.get(10, TimeUnit.MILLISECONDS) val reviews = reviewsFuture.get(10, TimeUnit.MILLISECONDS) ProductDetails(productInfo, recommendations, reviews) } } @crichardson
  • 25. ProductController @Controller class ProductController @Autowired()(productDetailsService : ProductDetailsService) { @RequestMapping(Array("/productdetails/{productId}")) @ResponseBody def productDetails(@PathVariable productId: Long) = productDetailsService.getProductDetails(productId) @crichardson
  • 26. Not bad but... class ProductDetailsService def getProductDetails(productId: Long): ProductDetails = { val productInfo = productInfoFuture.get(300, TimeUnit.MILLISECONDS) Not so scalable :-( Gathering blocks Tomcat thread until all Futures complete @crichardson
  • 27. ... and also... Java Futures work well for a single-level of asynchronous execution BUT #fail for more complex, scalable scenarios Difficult to compose and coordinate multiple concurrent operations See this blog post for more details: http://techblog.netflix.com/2013/02/rxjava-netflix-api.html @crichardson
  • 28. Better: Futures with callbacks no blocking! def asyncSquare(x : Int) : Future[Int] = ... x * x... val f = asyncSquare(25) Partial function applied to successful outcome f onSuccess { case x : Int => println(x) Applied to failed outcome } f onFailure { case e : Exception => println("exception thrown") } Guava ListenableFutures, Spring 4 ListenableFuture Java 8 CompletableFuture, Scala Futures @crichardson
  • 29. But callback-based scatter/gather Messy, tangled code (aka. callback hell) @crichardson
  • 30. Composable futures hide the mess Combines two futures val fzip = asyncSquare(5) zip asyncSquare(7) assertEquals((25, 49), Await.result(fzip, 1 second)) val fseq = Future.sequence((1 to 5).map { x => asyncSquare(x) }) Transforms list of futures to a future assertEquals(List(1, 4, 9, 16, 25), Await.result(fseq, 1 second)) Scala, Java 8 CompletableFuture (partially) @crichardson
  • 31. zip() is asynchronous Outcome1 f1 (o1, o2) f3 = f1 zip f2 f3 Implemented using callbacks Outcome2 f2 @crichardson
  • 32. Transforming futures def asyncPlus(x : Int, y : Int) = ... x + y ... val future2 = asyncPlus(4, 5).map{ _ * 3 } assertEquals(27, Await.result(future2, 1 second)) Asynchronously transforms future Scala, Java 8 CompletableFuture (partially) @crichardson
  • 33. Chaining asynchronous operations Calls asyncSquare() with the eventual outcome of asyncPlus() val f2 = asyncPlus(5, 8).flatMap { x => asyncSquare(x) } assertEquals(169, Await.result(f2, 1 second)) Scala, Java 8 CompletableFuture (partially) @crichardson
  • 34. Scala futures are Monads Two calls execute in parallel (asyncPlus(3, 5) zip asyncSquare(5)) .flatMap { And then invokes asyncPlus() case (a, b) => asyncPlus(a, b) map { _ * 2 } } result onSuccess { .... } x2 Rewrite using ‘for’ @crichardson
  • 35. Scala futures are Monads Two calls execute in parallel val result = for { (a, b) <- asyncPlus(3, 5) zip asyncSquare(5); c <- asyncPlus(a, b) } yield c * 2 result onSuccess { .... } ‘for’ is shorthand for map() and flatMap() And then invokes asyncPlus() x2 @crichardson
  • 36. ProductInfoService: using Scala Futures import scala.concurrent.Future Scala Future @Component class ProductInfoService { def getProductInfo(productId: Long): Future[ProductInfo] = { Future { restTemplate.getForObject(....) } } } Executed in a threaded pool @crichardson
  • 37. ProductDetailsService: using Scala Futures class ProductDetailsService ... Return a Scala Future def getProductDetails(productId: Long) : Future[ProductDetails] = { val productInfoFuture = productInfoService.getProductInfo(productId) val recommendationsFuture = recommendationService.getRecommendations(productId) val reviewsFuture = reviewService.getReviews(productId) for (((productInfo, recommendations), reviews) <productInfoFuture zip recommendationsFuture zip reviewsFuture) yield ProductDetails(productInfo, recommendations, reviews) } } Gathers data without blocking @crichardson
  • 38. Async ProductController: using Spring MVC DeferredResult @Controller class ProductController ... { @RequestMapping(Array("/productdetails/{productId}")) @ResponseBody def productDetails(@PathVariable productId: Long) : DeferredResult[ProductDetails] = { val productDetails = productDetailsService.getProductDetails(productId) val result = new DeferredResult[ProductDetails] productDetails onSuccess { case r => result.setResult(r) } productDetails onFailure { case t => result.setErrorResult(t) } Spring MVC DeferredResult ≅ Future Convert Scala Future to DeferredResult result } @crichardson
  • 39. Servlet layer is asynchronous BUT the backend uses thread pools Need event-driven REST client @crichardson
  • 40. Spring AsyncRestTemplate New in Spring 4 Mirrors RestTemplate Can use HttpComponents NIO-based AsyncHttpClient Methods return a ListenableFuture JDK 7 Future + callback methods Yet another “Future”! @crichardson
  • 41. ProductInfoService: using the AsyncRestTemplate class ProductInfoService { val asyncRestTemplate = new AsyncRestTemplate( new HttpComponentsAsyncClientHttpRequestFactory()) override def getProductInfo(productId: Long) = { val listenableFuture = asyncRestTemplate.getForEntity("{baseUrl}/productinfo/{productId}", classOf[ProductInfo], baseUrl, productId) toScalaFuture(listenableFuture).map { _.getBody } } Convert to Scala Future and get entity http://hc.apache.org/httpcomponents-asyncclient-dev/ @crichardson
  • 42. Converting ListenableFuture to Scala Future def toScalaFuture[T](lf : ListenableFuture[T]) : Future[T] = { val p = promise[T]() Creates a promise = producer API lf.addCallback(new ListenableFutureCallback[T] { def onSuccess(result: T) { p.success(result)} def onFailure(t: Throwable) { p.failure(t) } }) p.future } Propagate outcome to promise Return future @crichardson
  • 43. Now everything is nonblocking :-) We have achieved scaling Nirvana @crichardson
  • 44. WT*#*# is my code doing? Operations initiated in one thread but fail in another Lack of a full stack trace can make debugging difficult Inherent problem of async/event driven programming Futures make it very easy to forget to handle errors someFuture.foreach { handleTheHappyPath } Error is quietly ignored: similar to an empty catch {} block @crichardson
  • 45. Agenda The need for concurrency Simplifying concurrent code with Futures Consuming asynchronous streams with Reactive Extensions @crichardson
  • 46. Let’s imagine you have a stream of trades and you need to calculate the 15 minute rolling average price of each stock @crichardson
  • 47. Where is the high-level abstraction that simplifies solving this problem? @crichardson
  • 48. Future[List[T]] Not applicable to infinite streams @crichardson
  • 49. Pipes and Filters e.g. Spring Integration + Complex event processing (CEP) Not bad but tends to be an external DSL, heavy weight, statically defined, ... @crichardson
  • 50. Introducing Reactive Extensions (Rx) The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Using Rx, developers represent asynchronous data streams with Observables , query asynchronous data streams using LINQ operators , and ..... https://rx.codeplex.com/ @crichardson
  • 51. About RxJava Reactive Extensions (Rx) for the JVM Original motivation for Netflix was to provide rich Futures Implemented in Java Adaptors for Scala, Groovy and Clojure https://github.com/Netflix/RxJava @crichardson
  • 52. RxJava core concepts An asynchronous stream of items trait Observable[T] { def subscribe(observer : Observer[T]) : Subscription ... } Notifies trait def def def } Observer[T] { onNext(value : T) onCompleted() onError(e : Throwable) Used to unsubscribe * Note: with v0.17 subscribe() takes a Subscriber = Observer++ @crichardson
  • 53. Comparing Observable to... Observer pattern - similar but adds Observer.onComplete() Observer.onError() Iterator pattern - mirror image Push rather than pull Future - similar but Represents a stream of multiple values @crichardson
  • 55. Fun with observables val oneItem = Observable.items(-1L) val every10Seconds = Observable.interval(10 seconds) val ticker = oneItem ++ every10Seconds val subscription = ticker.subscribe ( new Observer[Long] { override def onNext(value: Long) = { println("value=" + value) }) ... subscription.unsubscribe() -1 0 1 ... t=0 t=10 t=20 ... } @crichardson
  • 56. Creating observables Observable.create({ observer: Observer[T] => ... Function observer.onNext(...) called when ... Observer observer.onCompleted() subscribes ... observer.onError(...) Called when observer ... unsubscribes Subscription{ .... } } }) * Note: with v0.17 create() takes a Subscriber = Observer++ @crichardson
  • 57. Creating observables from Query AWS Scala Futures def getTableStatus(tableName: String) = { val future = dynamoDbClient.describeTable(new DescribeTableRequest(tableName)) Observable.create({ observer : Observer[DynamoDbStatus] => future.onComplete { case Success(response) => observer.onNext(DynamoDbStatus(response.getTable.getTableStatus)) observer.onCompleted() case Failure(t: ResourceNotFoundException) => observer.onNext(DynamoDbStatus("NOT_FOUND")) observer.onCompleted() case Failure(someError) => observer.onError(someError) } Subscription({}) }) } Propagate@crichardson outcome
  • 58. Transforming observables val tableStatus = ticker.flatMap { i => logger.info("{}th describe table", i + 1) getTableStatus(name) } Status1 Status2 t=0 t=10 Status3 ... t=20 ... + Usual collection methods: map(), filter(), take(), drop(), ... @crichardson
  • 59. Back to the stream of Trades averaging example... @crichardson
  • 60. Calculating averages class AverageTradePriceCalculator { def calculateAverages(trades: Observable[Trade]): Observable[AveragePrice] = { ... } case class Trade( symbol : String, price : Double, quantity : Int ... ) case class AveragePrice( symbol : String, price : Double, ...) @crichardson
  • 61. Using groupBy() Observable[Trade] APPL : 401 100 IBM : 405 300 CAT : 405 150 APPL: 403 300 groupBy( (trade) => trade.symbol) APPL : 401 APPL: 403 IBM : 405 CAT : 405 Observable[GroupedObservable[String, Trade]] ... @crichardson
  • 62. Using window() Observable[Trade] APPL : 401 APPL : 405 APPL : 405 ... window(...) 5 minutes APPL : 401 APPL : 405 APPL : 405 APPL : 405 APPL : 403 30 secs 30 secs APPL : 405 APPL : 405 ... Observable[Observable[Trade]] @crichardson
  • 63. Using foldLeft() Observable[Trade] APPL : 402 100 APPL : 405 200 APPL : 405 200 foldLeft(0.0)(_ + _.price) / foldLeft(0.0)(_ + _.quantity) APPL : 404.4 Observable[AveragePrice] Singleton @crichardson
  • 64. Using flatten() Observable[Observable[AveragePrice]] APPL : 401 APPL: 403 IBM : 405 CAT : 405 ... flatten() APPL : 401 IBM : 405 Observable[AveragePrice] CAT : 405 APPL: 403 @crichardson
  • 65. Calculating average prices def calculateAverages(trades: Observable[Trade]): Observable[AveragePrice] = { trades.groupBy(_.symbol).map { symbolAndTrades => val (symbol, tradesForSymbol) = symbolAndTrades val openingEverySecond = Observable.items(-1L) ++ Observable.interval(1 seconds) def closingAfterSixSeconds(opening: Any) = Observable.interval(6 seconds).take(1) tradesForSymbol.window(...).map { windowOfTradesForSymbol => windowOfTradesForSymbol.fold((0.0, 0, List[Double]())) { (soFar, trade) => val (sum, count, prices) = soFar (sum + trade.price, count + trade.quantity, trade.price +: prices) } map { x => val (sum, length, prices) = x AveragePrice(symbol, sum / length, prices) } }.flatten }.flatten } @crichardson
  • 66. Summary Consuming web services asynchronously is essential Scala-style Futures are a powerful concurrency abstraction Rx Observables even more powerful unifying abstraction for a wide variety of use cases @crichardson