how to bake reactive behavior into your java ee applications
TRANSCRIPT
PowerPoint Presentation
Click to edit Master title style
Click to edit Master title style
Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline LevelClick to edit Master text stylesSecond levelThird levelFourth level
Fifth level
6/14/16
Click to edit Master title style
Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline LevelClick to edit Master text stylesSecond levelThird levelFourth level
Fifth level
Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline Level
Seventh Outline LevelClick to edit Master text styles
Second level
Third level
Fourth level
Fifth level
6/14/16
Click to edit Master title style
6/14/16
Click to edit the title text format
Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline Level
@OMihalyi
Click to edit Master title style
Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline LevelClick to edit Master text styles
6/14/16
How to bake reactive behavior into your Java EE applications
Ondrej Mihlyi@OMihalyi
Agenda
What is a reactive app
Support in Java EE 7
Java 8 joins the game
Payara Micro additions
Live demo
Common pitfalls
Ondrej Mihlyi
Web:
itblog.inginea.eu
Twitter: @OMihalyi
Payara suppor engineer
Java EE developer
Java EE lecturer
Java blogger
Scrummaster
dfds
Reactive application
Why apps are not inherently like this? - because of traditionally blocking API and monolithic architectures - because it is hard (for programmers)
Solutions - Completely new frameworks (Vert.x) - learn everything from scratch - not easy to reuse knowledge - Improve existing approaches - add non-blocking API - continuous improvements where it adds most value
Possible in Enterprise?
New tools and frameworks
High risks and costs
Fully reactive approachHigh cost of development
Harder to avoid and track bugs
Advice reactive where its worth
leave the door open for future
Java EE leaves the door open
Established and wide-spreadBuilt with resilience in mind (Transactions)
Messaging is first-class citizen (JMS)
Continuous improvementsAsynchronous API, thread-management
Scalability improvements (JCache)
Portable CDI extensions
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0 simplified API, managed executor)
Traditional approach
Request started external resource required (DB, WS, files) request external resource external resource is slow what do we do?
We SIMPLY wait
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Traditional approach
We SIMPLY waitSimple
Thread-safe
Sufficient when waiting time is negligible
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Traditional approach
Blocking calls:
JDBC:ResultSet rs = stmt.executeQuery(q);
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Traditional approach
Blocking calls:
JPA:List r = query.getResultList();Servlet:response.getWriter() .print(s);
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Traditional approach
Blocking design:Servlet filters
Interceptors
JSF lifecycle
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Spawn a separate thread
Idea: Blocking call in a new thread
Do something while waiting
Join the thread and retrieve results
Fail after timeout vs. block infinitely
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
java.util.concurrent.Future
Solution in Java world (since Java 5)
@Asynchronous methods since Java EE 6Solves the problem for fire-and-forget
Still drawbacks when result neededComplexity keep asking Are you ready?
Requires one more threadblocked when nothing to do while waiting
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
@Asynchronous
Any EJB method or all methods of an EJB
Executes in another thread in pool
Fire-and-forget with void result
Return result as a FutureFuture not efficient enough, well improve later
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
@Asynchronous - Fire-and-forget
@Asynchronousvoid fireAndForget (String message) { // long-running task}
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API in Java EE 7
AsyncContext in Servlet (since 3.0, Java EE 6)
// get context for another threadAsyncContext ctx = req.startAsync();AsyncContext .getResponse() .getOutputStream()ctx.complete();
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API in Java EE 7
AsyncContext in Servlet
AsyncContext ctx = req.startAsync();AsyncContext // build response (in any thread) .getResponse() .getOutputStream() // finish (in new thread)ctx.complete();
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API in Java EE 7
AsyncContext in ServletRequires to turn on async supportUsing @WebServlet annotation
In web.xml descriptor
@WebServlet (asyncSupported=true)
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API in Java EE 7
Async IO in Servlet 3.1 (Java EE 7)Non-blocking reading of multi-part form
Non-blocking writing of response body
Non-blocking IO in Java (NIO)to read HTML from files
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API
JAX-RS AsyncResponse @Suspended
@GETvoid get(@Suspended AsyncResponse r) // in another thread response.resume("OK");
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API
JAX-RS AsyncResponse @Suspended
void get(@Suspended AsyncResponse response) // in another threadresponse .resume("OK");
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Non-blocking API
JAX-RS async client
resourceTarget .request(MediaType.TEXT_PLAIN) .async() .get(new InvocationCallback() { });
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
CDI events + @Asynchronous
CDI events decouple componentsone-way communication
handlers triggered in the same thread
emitter is blocked
Handlers are asynchronous EJB methodstriggered in anyther thread emitter not blocked
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
@Inject Event ev; ev.fire(new MyEvent()); @Asynchronousvoid handle(@Observes MyEvent ev) { }
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Summary of approaches
Traditional blocking APIEasy to use, halts execution until finished
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Summary of approaches
Traditional blocking APIEasy to use, halts execution until finished
Asynchronous call with Futurenot blocking, +1 thread
Asynchronous call with callbackNot blocking, 1 thread at a time, callback hell
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Java 8
CompletableFuture (CompletionStage)Chain callbacks (like promises)
Execute in the same or another threadthenRun(), thenRunAsync(),
thenCompose(),
Complete execution in any thread at any timecompletableFuture.complete()
thenComposeAsync()
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
thenComposeAsync()
CompletableFuture cf = new CompletableFuture(); cf.thenComposeAsync( r -> return callThatReturnsCF(r);), executor) cf.complete(awaitResult())
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
thenComposeAsync()
cf.thenComposeAsync( r -> returnsCF(r) ), executor) .thenComposeAsync( cf.complete(r);
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Java EE + Java 8
Future CompletableFuture ?No, not compatible
Callbacks CompletableFuturecallback triggers cf.complete()
Pass CF as additional parameter
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Pass CF as additional parameter
void asyncCall(CompletableFuture cf) { cf.complete(result);}
cf = new CompletableFuture();asyncCall(cf);cf.thenComposeAsync( result -> , executor);
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Use managed executors
CF async methods use ForkJoinPoolNot managed by Java EE
Always use a managed executor
@ResourceManagedExecutorService executor;
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Other parts of being Reactive
Weve shown responsive API
The other 3 reactive concepts:Resilience
Messaging
Elasticity
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Resilience
Responsive in the face of failures
Server clusters and transaction isolation
Load balancer in front
Microservices (embedded server)
reduce single points of failure
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Payara Micro
Application server as executable JAR
Runs WAR apps from command line
automatic and elastic clustering
spawn many micro services dynamically
replication using distributed cache
shared 60MB runtime, 40MB in heap
www.payara.fish
V
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Messaging in Java EE
JMS traditional solutionTopics, Queues, Persistence, Transactional, Repeated delivery
Simplified API in Java EE 7some bioler-plate still necessary
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Why not make it even simpler?
@Inject @OutboundEvent ev;
// handle in different JVM void handle(@Observes @Inbound MyMsg ev) { }
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Payara Micro event bus
events handled by any distributed nodeAsynchronous (reactive) micro services
No need for service registry
On top of CDI events, just 2 qualifiers@Outbound event, @Inbound observer
Uses Hazelcast distributed executor
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Elasticity in Java EE
Weakest point of Java EE specsClusters do not scale dynamically
Many provider-specific solutions
JCache JSR targets Java EE 8
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
JCache
Standard Java API for caching
Distributed
API and CDI binding
Supported by many cache providers
Built in to Payara Server and Payara Micro
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
@Inject MyCache cache; value = cache.get(key); @CacheResultObject get( @CacheKey Object key)
JCache CDI binding
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
mycache.put(key, value); @CachePutvoid put( @CacheKey Object key, @CacheValue Object v) { // body can be empty }
JCache CDI binding
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Dynamic scaling
Just run repeatedly
binds to a free port to avoid port collisions
All instances autoconnect to a clusterEven across network (multicast)
java -jar payara-micro.java --deploy app.war --autoBindHttp
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Payara Micro example
web service on single node, computation service scaled to multiple nodesWeb service fires an @Outbound event
Computation started on a computation nodeSynchronisation using Jcache API
An event with result fired
Observed by web service and returned
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Fully reactive comes at a greater costDealing with threads, hard to track origin, communication overhead
Dont over-engineer, but leave doors open
Java EE enables gradual improvement
General advice
Established small costs of upgrade or redesign
Improvements simplifications (EJB3, CDI, JMS 2.0, managed executor)
Questions?
Thank you