Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

How to bake reactive behavior into your Java EE applications

729 views

Published on

Reactive applications are flexible and robust. Reactive programming is already an established concept and there are many modern frameworks and tools which support it. You need to understand the concept in order to build truly reactive applications. But you do not need to switch from what you already know to build them. With standard Java EE you have wide range of options to add reactive behavior to new and even existing applications.

Java EE is a modern and evolving framework, which supports reactive concepts. The latest versions of JDK and Java EE add even more asynchronous API to write fully reactive applications. On top of asynchronous processing in servlets, REST services and EJBs, there is asynchronous IO, managed multithreading and CompletableFuture with its promise­-like API to tackle callback hell. Several Java EE implementations, like Payara Micro, go even further and provide extensions to scale your applications in natural way.

Published in: Software
  • Be the first to comment

  • Be the first to like this

How to bake reactive behavior into your Java EE applications

  1. 1. How to bake reactive behavior into your Java EE applications Ondrej Mihályi @OMihalyi
  2. 2. @OMihalyi AgendaAgenda ➢ What is a reactive app ➢ Support in Java EE 7 ➢ Java 8 joins the game ➢ Payara Micro additions ➢ Live demo ➢ Common pitfalls
  3. 3. @OMihalyi Ondrej Mihályi Web: itblog.inginea.eu Twitter: Ondrej Mihályi Web: itblog.inginea.eu Twitter: Payara suppor engineer Java EE developer Java EE lecturer Java blogger Scrummaster
  4. 4. @OMihalyi Reactive applicationReactive application
  5. 5. @OMihalyi Possible in Enterprise?Possible in Enterprise? New tools and frameworks ➔ High risks and costs Fully reactive approach ➔ High cost of development ➔ Harder to avoid and track bugs Advice → reactive where it’s worth → leave the door open for future
  6. 6. @OMihalyi Java EE leaves the door openJava EE leaves the door open Established and wide-spread – Built with resilience in mind (Transactions) – Messaging is first-class citizen (JMS) Continuous improvements – Asynchronous API, thread-management – Scalability improvements (JCache) – Portable CDI extensions
  7. 7. @OMihalyi Traditional approachTraditional approach Request started → external resource required (DB, WS, files) → request external resource → external resource is slow → what do we do? We SIMPLY wait…
  8. 8. @OMihalyi Traditional approachTraditional approach We SIMPLY wait… Simple Thread-safe Sufficient when waiting time is negligible
  9. 9. @OMihalyi Traditional approachTraditional approach Blocking calls: JDBC: ResultSet rs = stmt.executeQuery(q);
  10. 10. @OMihalyi Traditional approachTraditional approach Blocking calls: JPA: List r = query.getResultList(); Servlet: response.getWriter() .print(s);
  11. 11. @OMihalyi Traditional approachTraditional approach Blocking design: – Servlet filters – Interceptors – JSF lifecycle
  12. 12. @OMihalyi Spawn a separate threadSpawn 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
  13. 13. @OMihalyi java.util.concurrent.Futurejava.util.concurrent.Future Solution in Java world (since Java 5) @Asynchronous methods since Java EE 6 – Solves the problem for fire-and-forget – Still drawbacks when result needed ● Complexity – keep asking “Are you ready?” ● Requires one more thread – blocked when nothing to do while waiting
  14. 14. @OMihalyi @Asynchronous@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 Future – Future not efficient enough, we’ll improve later
  15. 15. @OMihalyi @Asynchronous - Fire-and- forget @Asynchronous - Fire-and- forget @Asynchronous void fireAndForget (String message) { … // long-running task }
  16. 16. @OMihalyi Non-blocking API in Java EE 7Non-blocking API in Java EE 7 AsyncContext in Servlet (since 3.0, Java EE 6) // get context for another thread AsyncContext ctx = req.startAsync(); AsyncContext .getResponse() .getOutputStream()… ctx.complete();
  17. 17. @OMihalyi Non-blocking API in Java EE 7Non-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();
  18. 18. @OMihalyi Non-blocking API in Java EE 7Non-blocking API in Java EE 7 AsyncContext in Servlet – Requires to turn on async support ● Using @WebServlet annotation ● In web.xml descriptor @WebServlet (asyncSupported=true)
  19. 19. @OMihalyi Non-blocking API in Java EE 7Non-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
  20. 20. @OMihalyi Non-blocking APINon-blocking API JAX-RS AsyncResponse @Suspended@GET void get(@Suspended AsyncResponse r) … // in another thread response.resume("OK");
  21. 21. @OMihalyi Non-blocking APINon-blocking API JAX-RS AsyncResponse @Suspendedvoid get(@Suspended AsyncResponse response) … // in another thread response .resume("OK");
  22. 22. @OMihalyi Non-blocking APINon-blocking API JAX-RS async client resourceTarget .request(MediaType.TEXT_PLAIN) .async() .get(new InvocationCallback () { … });
  23. 23. @OMihalyi CDI events + @AsynchronousCDI events + @Asynchronous CDI events decouple components – one-way communication – handlers triggered in the same thread → emitter is blocked Handlers are asynchronous EJB methods – triggered in anyther thread → emitter not blocked
  24. 24. @OMihalyi @Inject Event<MyEvent> ev; … ev.fire(new MyEvent()); … @Asynchronous void handle(@Observes MyEvent ev) { … }
  25. 25. @OMihalyi Summary of approachesSummary of approaches Traditional blocking API – Easy to use, halts execution until finished →→
  26. 26. @OMihalyi Summary of approachesSummary of approaches Traditional blocking API – Easy to use, halts execution until finished Asynchronous call with Future – not blocking, +1 thread Asynchronous call with callback – Not blocking, 1 thread at a time, callback hell
  27. 27. @OMihalyi Java 8Java 8 CompletableFuture (CompletionStage) – Chain callbacks (like promises) – Execute in the same or another thread ● thenRun(), thenRunAsync(), … ● thenCompose(),… – Complete execution in any thread at any time ● completableFuture.complete() thenComposeAsync()
  28. 28. @OMihalyi thenComposeAsync()thenComposeAsync() CompletableFuture<String> cf = new CompletableFuture<>(); … cf.thenComposeAsync( r -> return callThatReturnsCF(r); ), executor) … cf.complete(awaitResult())
  29. 29. @OMihalyi thenComposeAsync()thenComposeAsync() … cf.thenComposeAsync( r -> returnsCF(r) ), executor) .thenComposeAsync(… … cf.complete(r);
  30. 30. @OMihalyi Java EE + Java 8Java EE + Java 8 Future → CompletableFuture ? – No, not compatible Callbacks → CompletableFuture – callback triggers cf.complete() Pass CF as additional parameter
  31. 31. @OMihalyi Pass CF as additional parameterPass CF as additional parameter void asyncCall(CompletableFuture cf) { … cf.complete(result); } … cf = new CompletableFuture<String>(); asyncCall(cf); cf.thenComposeAsync( result -> … , executor);
  32. 32. @OMihalyi Use managed executorsUse managed executors CF async methods use ForkJoinPool – Not managed by Java EE Always use a managed executor @Resource ManagedExecutorService executor;
  33. 33. @OMihalyi Other parts of being ReactiveOther parts of being Reactive We’ve shown responsive API The other 3 reactive concepts: – Resilience – Messaging – Elasticity
  34. 34. @OMihalyi ResilienceResilience Responsive in the face of failures Server clusters and transaction isolation Load balancer in front Microservices (embedded server) … reduce single points of failure
  35. 35. @OMihalyi Payara MicroPayara 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
  36. 36. @OMihalyi Messaging in Java EEMessaging in Java EE JMS – traditional solution – Topics, Queues, Persistence, Transactional, Repeated delivery – Simplified API in Java EE 7 ● some bioler-plate still necessary
  37. 37. @OMihalyi Why not make it even simpler? @Inject @Outbound Event<MyMsg> ev; // handle in different JVM void handle(@Observes @Inbound MyMsg ev) { … }
  38. 38. @OMihalyi Payara Micro event busPayara Micro event bus events handled by any distributed node – Asynchronous (reactive) micro services – No need for service registry On top of CDI events, just 2 qualifiers – @Outbound event, @Inbound observer Uses Hazelcast distributed executor
  39. 39. @OMihalyi Elasticity in Java EEElasticity in Java EE Weakest point of Java EE specs – Clusters do not scale dynamically Many provider-specific solutions JCache JSR – targets Java EE 8
  40. 40. @OMihalyi JCacheJCache Standard Java API for caching Distributed API and CDI binding Supported by many cache providers Built in to Payara Server and Payara Micro
  41. 41. @OMihalyi @Inject MyCache cache; … value = cache.get(key); … @CacheResult Object get( @CacheKey Object key) JCache CDI bindingJCache CDI binding
  42. 42. @OMihalyi mycache.put(key, value); … @CachePut void put( @CacheKey Object key, @CacheValue Object v) { // body can be empty } JCache CDI bindingJCache CDI binding
  43. 43. @OMihalyi Dynamic scalingDynamic scaling Just run repeatedly – binds to a free port to avoid port collisions All instances autoconnect to a cluster – Even across network (multicast) java -jar payara-micro.java --deploy app.war --autoBindHttp
  44. 44. @OMihalyi Payara Micro examplePayara Micro example web service on single node, computation service scaled to multiple nodes – Web service fires an @Outbound event – Computation started on a computation node ● Synchronisation using Jcache API – An event with result fired – Observed by web service and returned
  45. 45. @OMihalyi Fully reactive comes at a greater cost – Dealing with threads, hard to track origin, communication overhead Don’t over-engineer, but leave doors open Java EE enables gradual improvement General adviceGeneral advice
  46. 46. @OMihalyi Questions?Questions? Thank you

×