Venue: GOTOcon Amsterdam
Eberhard Wolff talks with Jürgen Höller about Reactive Spring. Reactive programming is a hot topic, but adoption has been slow in the enterprise. Spring 5 incorporates Reactor and the RxJava API to help Java developers build scalable high-performance web applications. The discussion explores architectural challenges, transactions, porting existing applications, and increased code complexity.
Show Notes
Related Links
- Episode 82 – Organization of large code bases with Jürgen Höller (founder of Spring) https://www.se-radio.net/2008/01/episode-82-organization-of-large-code-bases-with-juergen-hoeller/
- Episode 145 – Spring in 2009 with Ebehard Wolff https://www.se-radio.net/2009/09/episode-145-spring-in-2009-with-eberhard-wolff/
- Episode 160 – Spring AOP with Ramnivas Laddad https://www.se-radio.net/2010/04/episode-160-aspectj-and-spring-aop-with-ramnivas-laddad/
- Spring Guides
- Spring Reactive (GitHub)
- Blog about Reactive Spring
- Reactive Streams
- Reactor
- Presentation about Reactive Spring
Transcript
Transcript brought to you by innoQ
This is Software Engineering Radio, the podcast for professional developers, on the web at SE-Radio.net. SE-Radio brings you relevant and detailed discussions of software engineering topics at least once a month. SE-Radio is brought to you by IEEE Software Magazine, online at computer.org/software.
* * *
Eberhard Wolff: [00:00:33.28] Welcome to our show about Reactive Spring. This is Eberhard Wolff and I’m sitting here with Jürgen Höller. He is from Austria and the lead engineer of the Spring framework, pretty much from the very beginning. I’m happy to meet him here at GOTOcon Amsterdam.
What we are going to talk about is how Reactive programming will be integrated into the Spring framework. Jürgen, welcome to the show first of all.
Jürgen Höller: Thanks, happy to have the opportunity.
Eberhard Wolff: [00:00:59.01] One of the things that I understand is that all the code that goes into the framework has to be organized, so I was wondering what that actually means.
Jürgen Höller: [00:01:07.05] I have a certain tendency to find well-sourced codes and just polish it. My own term of word is actually polishing – it’s my process of revisiting certain parts of the codebase, contributions to the core frame of codebase and to fine-tune them, both in terms of source code style and in terms of the actual implementation.
I pay a lot of attention not only to the style – although I do remove spaces, I do inline javadoc, I do all those things, but I in particular pay attention to the efficiency of the implementation, reuse of state, for example, optimize concurrent access to shared state. That sort of attention to the detail is what others have coined the term for, and they call it “jürgenized”, because I tend to do it to pretty much all the code in the codebase, whether it’s originated with myself or whether it was an external contribution from within the team or outside the team. I do it to everybody’s code, and I guess that’s part of the meaning, as well.
Eberhard Wolff: [00:02:07.14] Can you say a few words about Spring and what Spring’s goals are? Quite a few listeners are familiar with it, but maybe someone didn’t use it so far.
Jürgen Höller: [00:02:16.12] I suppose so. In all brevity, Spring as an application framework has the ambition of providing a comprehensive programming model for the challenges in Java application development today. “Today” is actually an ongoing kind of today. We pay a lot of attention to evolved framework towards where the challenges are and the challenges will be in Java programming.
We are usually very forward-looking. The application framework itself has quite some history in the meantime (it dates back to 2002-2003 in its origins), but at the same time it is a very up to date, very 2016-era framework. It’s in particular this evolution and adaptability of the framework towards modern day challenges that we are most proud of.
Eberhard Wolff: [00:03:07.10] Spring has a tool ecosystem; there are quite a few other frameworks and tools, too. One of the more recent tools is Spring Boot, and it seems to be one of the tools that is the most popular right now. Can you say a few words about that and what it actually is?
Jürgen Höller: [00:03:21.20] Indeed, the ecosystem is quite extensive in the meantime, and Spring Boot is just a great entry point into the ecosystem. Spring Boot is quite a few things: it is an entry point in terms of dependency management, as well. You start with a particular Spring Boot version, you get a pre-chosen version of the cool framework of Spring Data, of several other Spring projects and external partner-projects selected for you. Spring Boot just brings them in in a pre-tested, pre-integrated form.
That’s one of its merits, but at the heart of the Boot effort is an auto-configuration framework. Boot is an autoconfig story where with very minimal configuration — even zero configuration — you just get started with Spring web applications in particular, but also other kinds of Spring apps in a very minimal form.
A third angle is the notion of embedded bootstrapping and special deployment arrangements like fat JAR deployment, where Spring Boot has a sweet spot in how it allows you to deploy and start your Spring application in rather non-traditional ways. This is where it connects really nicely to microservices’ idea, the microservices architecture.
Spring Boot, at the heart of what it does, is not really a microservices framework in a particularly narrow sense, but it turns out to be a very fine match with what microservices’ architectures demand, both in terms of the deployments of smaller units and in terms of the autoconfiguration effort. If you have several deployments in mind, each of them might have its particular external services to integrate with, and Spring Boot’s management of the particular dependencies of each of those deployment units is also a sweet spot.
Spring Boot is many things to many people, but it turns out to be a very popular part of the modern-day Spring ecosystem.
Eberhard Wolff: [00:05:25.03] The other part about it is Reactive programming. We already did a show about Reactive programming with Vaughn Vernon (episode 249), but to get us started here, can you say a few words about what Reactive is in your opinion?
Jürgen Höller: [00:05:39.28] From my perspective, Reactive is a very overloaded term. Depending on who you ask, you can get quite different impressions. From my own perspective and from our Spring-oriented perspective, Reactive is an infrastructural challenge. Our modern day infrastructure is actually very capable of the efficient use of resources at runtime. However, we need to allow it to operate efficiently.
Our programming models tend to make assumptions about the use of resources that prevent the random infrastructure from managing them efficiently. It starts with threads where our programming models tend to occupy a thread, do its work as long as it takes, even with external calls to external systems – data stores and data collaborating systems – and at some point release the thread when you’re done processing your current request. This is a very resource-intensive arrangement. You have to have a thread pool actually allowing for such long-running request processing on any given thread.
Reactive turns the idea around and suggests programming models where your processing algorithm is being specified in the form of callbacks, allowing the runtime to call you back when the resources allow for processing, when the streams allow for reading, when your output arrangement allows for streaming output data back. You’re not making assumptions about always being able to talk to your resources, you react to the availability of your resources, both on the incoming end and on the outgoing end.
From my perspective, it is primarily driven from this infrastructural need, and some of the technologies out there — the low-level technologies — are very capable of allowing us to do this. The shortcomings are rather at the programming model levels. This is not a transparent upgrade underneath the covers and everything just magically happens; it requires us as application developers to rethink the way that we are going about some of our processing arrangements. We need to reconsider web endpoint arrangements, HTTP request processing arrangements, and to some degree data store access in general, the use of transactions. There are many implications that follow from this.
Eberhard Wolff: [00:08:09.25] What you are saying at the core is that if an HTTP request comes in, the old model would take a thread and block it forever, while with a Reactive model an HTTP request (or even a multiple HTTP request) would be handled by one thread of they enter the system; or if new data from a data store comes in, then the system would react, and that single thread would handle all of those requests.
How do you develop Reactive applications in Java? We are all familiar with the software model and all the other models, where you would get a request that comes in and do your stuff in a linear fashion. If you look at what you said, then we would need to have something to react to data coming in from the database, an HTTP request that comes in, and so on. What’s the impact on the programming model?
Jürgen Höller: [00:09:00.08] The easiest way to illustrate this is the common examples out there, for example RxJava. The idea there is to have certain common operators, like map, flatMap operations that allow you to express processing arrangements for pieces of incoming data as they come in.
There’s a very close relationship to the ability to nicely cruft callbacks. Java 8 lambdas are a really nice fit. The entire programming model suggested by RxJava & co works much better on Java 8 than it ever did before. It does not change the fundamental arrangement, though. You are being called back by a thread chosen by the runtime for processing a particular piece of data that just came in or that is about to be written, so you cannot make any assumptions about the state of the thread. You can’t just set up locals or have ongoing transactions carried over as you maybe thought you could do, based on the heritage of the servlet programming model.
[00:10:05.22] This is a situation where there are benefits to each of the models, so it’s not just a step forward in every possible sense. The transactional model that we’re used to work with does make a lot of sense for certain kinds of applications, whereas Reactive programming basically requires you to drop the entire notion of longer-running transactions. You interact with resources in very short, small steps and you’re going to be eventually consistent at some point, but you can’t just have transactions of several seconds providing those consistency guarantees to you anymore.
[00:10:48.03] The Reactive programming model landscape in Java is very diverse. There are a lot of things, not just RxJava out there. They are very distinct approaches, like the Actor model in Akka, there’s Vert.x… There are plenty of framework architectures that are suggesting a Reactive model all the way through, whereas our perspective is a little bit more balanced. We look at the space from a more pragmatic angle.
The experience level of a Java or Spring development team is a very important factor in its own rights. Reactive programming can be uncomfortable. It can even be messy to some eyes, at least. It is a different way to tackle a particular problem space with implications that are not necessarily of everybody’s taste.
Eberhard Wolff: [00:11:44.14] You said there are some issues around transactions in Reactive. Can you elaborate on that? When I get an HTTP request and I do some work on the database, and then again I do some work on the database there seems to be something that I should encapsulate in one transaction if I have several different parts of stuff that is done on the database, at least for relational databases. Would you say that this is not the case anymore for Reactive applications? What’s your point there?
Jürgen Höller: [00:12:13.12] I would argue it is not a fit for the fundamental idea of using resources within a short callback. Programming reactively at the entry point level and then going down to the data store, asking the data store to have a connection reserved for you goes against the grain; it doesn’t work aligned with a thread pool management. From my perspective, it needs to be efficient all the way through. You need to have efficient use of you thread pool, you need to have equally efficient use of your resource pool, your connection pool underneath.
You might be forced, because of some external constraints of the external data store not allowing you to interact any other way; you might be forced to do it in some corners of your system. In a Reactive world, you’re typically passing such long-running indirection work off to worker threads, not constraining the availability of your system overall.
This is one of the greatest shortcomings of the servlet world – one pool for all HTTP servlet requests. If some of them block against data stores, they are not available to incoming requests anymore, even if those incoming requests could be perfectly handled in a very efficient way with cache responses returned. You basically sacrifice the availability and responsiveness of your system if your target data stores block in some form. It is unfortunately a consequence of a truly reactive architecture that the direction with your data stores needs to be rethought, as well. You cannot just talk to your relational database as you used to, and the notion of a longer-running interaction with the data store can be translated to some degree, but consistency guarantees where you’re asking your data store to create locks on tables and rows for you is exactly what we’re trying to avoid here. Because the next thread is just going to come along and have to wait for that lock to be released, which isn’t any better than waiting for a thread pool to release a thread to you.
[00:14:23.24] My own perspective on it is that if you really want to do reactive, do it all the way through, down to the data store level.
Eberhard Wolff: [00:14:31.09] Listening to what you said, it seems that the most important reason for doing reactive programming is efficiency and performance. Would you agree, or is there any other reason why you would do it?
Jürgen Höller: [00:14:44.13] It is the primary reason, with the consequences of improving the availability and responsiveness of your system, because the runtime arrangement always has threading resources available for incoming requests in some form, allowing the architecture to differentiate between requests that are very easy to satisfy and others that are more demanding. If you’re waiting for a data store, basically you’re waiting while your thread is being released back to the pool in order to serve somebody else’s incoming request, which might be more efficient to create a response for.
Given that both in the JVM world and in operating systems in general we have limitations on the resources available – you can’t just have an arbitrary number of threads; you have to live with some limit being imposed on you in terms of the number of threads. In particular for applications with highly concurrent loads, there is no other way to scale them without sacrificing availability and responsiveness, other than going reactive at some point. Not every application falls into this category, but quite a few applications, or certain parts of common applications out there – the public-facing ones, openly accessible without any login or authentication, where anybody can send any number of requests at any time to those facades. Those are basically the parts of the system that will benefit most. Informational systems, user-facing systems, and systems with a very high number of users in general.
Eberhard Wolff: [00:16:21.23] You’re working on [unintelligible 00:16:23.03] Why did you start that project?
Jürgen Höller: [00:16:26.22] Our Reactive efforts have started quite a while back. There were several factors involved. There was an interest in the team in general, we were very aware of what was going on already in RxJava land, and admirers of some other efforts in the JVM space and in the reactive angle. In terms of our own efforts, we have been asked. We reached out to people and it turned out in conversations that people are facing deconstraints, resource constraints in some parts of the systems. Some of those conversations turned pretty concrete; people were already doing RxJava in Spring (there are already Spring apps out there as we speak here), doing Reactive in a Spring context, in a Spring application environment, using RxJava, some of them even using our own Reactor effort, but in a handcrafted style, without any first-class support from the framework itself.
[00:17:26.19] Some of those discussions lead to very concrete suggestions that there could be first-class Reactive support in quite a few parts of the Spring ecosystem, starting from the core framework. Some of the core abstractions that we have at the moment make assumptions about how they are being used, the use of blocking input and output streams and the use of thread locals.
The Reactive spin leads to variants of some of those abstractions so they’re more openly designed towards a callback style, towards back pressure, towards the non-use of thread locals. This turned out from a couple of those corners into an effort where we thought, “Alright, let’s do some [unintelligible 00:18:10.11]. Let’s see what a Spring web endpoint model (a Spring MVC-like model) could look like with a Reactive engine underneath, using some of those newly created abstractions underneath, using the Reactive Streams’ APIs as a foundation for the interaction model”, and just seeing what it feels like. Something like Spring MVC on Reactive.
Eberhard Wolff: [00:18:37.20] You mentioned RxJava quite a few times. Can you say a few words about what that is and how it relates to Spring?
Jürgen Höller: [00:18:45.10] RxJava is probably the best-known library for Reactive programming in Java. It was largely developed at Netflix; it originated as part of a larger effort with several language bindings, but the RxJava has an established role as a common library. It is already a little bit dated in the meantime, since it actually predates Reactive Streams.
The Reactive Streams effort, which is a collaboration between several industry stakeholders, created a very minimal set of interfaces that we call the Reactive Streams API, and RxJava to this day is not based on Reactive Streams, it just has Reactive Streams adapters. It is an early generation programming library, but it is the common reference out there, and in our Reactive Spring efforts, in our initial goals and to this day we aim to support RxJava as a programming model for the user-declared application endpoints. The RxJava Observable type, the RxJava Single type can be used in the endpoint signatures, but as we move forward with this, there are more modern-minded alternatives to the RxJava types, coming for example from our own Reactor project.
Eberhard Wolff: [00:20:10.10] What are the features of RxJava? You mentioned Observables; it has to have some callback mechanism.
Jürgen Höller: [00:20:16.11] Most importantly it is a composition library. It has a ton of composition operators on Observable where you can combine the outcome of one of your callback operations with other operations. You can create whole sequences of processing steps that consume each other’s output, whole chains of processing that are fed to an underlying runtime, and where just a whole sequence of callbacks produces the outcome in the end.
Observable is a huge piece of API [unintelligible 00:20:48.08] composition methods to all those operators. Reactor is coming from a similar angle. The Reactor Flux type and Mono type are sort of similar to Observable in Mono. They are kind of RxJava rethought from a Reactive Streams-based perspective and a little bit more focused set of operators that are sufficient for the 80-90% use case.
In the end, RxJava is an admirable effort, and when it started and what it did since, we just believe that for a forward-looking perspective, RxJava 2 is highly anticipated. They have a plan for RxJava 2. It is intended to be based on Reactive Streams as well, just didn’t make any concrete progress yet. Our Reactive project to this day is the most advanced Reactive Streams-based composition library out there.
Eberhard Wolff: [00:21:46.19] Reactor is a project that was found by Pivotal, just like Spring.
Jürgen Höller: [00:21:51.03] Indeed. It is an independently-minded effort on ProjectReactor.org (ProjectReactor.io), but they’re very aligned with what Spring is doing. It is used by quite a few projects within the Spring ecosystem and within the wider Pivotal portfolio as well, and it is our preferred composition library for the purposes in the Reactive Spring programming model. We expect a Reactor 3.0 release to go with Spring framework 5 next year, so it is very aligned in that perspective.
Eberhard Wolff: [00:22:27.14] You mentioned Reactive Streams. Can you say something about that? How does it relate to React and RxJava? What is it, what features does it provide?
Jürgen Höller: [00:22:36.08] Reactive Streams is more of an integrational effort. It’s not really user-facing. A very minimal set of interfaces with a publisher/subscriber subscription type, allowing to interact a publisher and a subscriber with some basic means of back pressure, where a subscriber actually request the pieces of data from a publisher, and the publisher only starts generating them on demand as a subscriber is able to handle them, to digest them.
It focuses on a particularly important part of reactive indirection, the idea being that those pieces come from different angles, different vendors. Application-level pieces, data store drivers, web framework endpoints interact through those common abstractions provided by Reactive Streams. It is an effort much larger than Reactive Spring. We are working with quite a few of the stakeholders in the Reactive Stream space, both the other framework vendors, but in particular web server implementers and data store companies, for example Couchbase.
There’s even a Postgres effort in that direction… There’s quite a bit going on, where the vendors themselves would provide Reactive Streams-enabled data store drivers, naturally allowing for being composed into processing chains that are based on the Reactive Streams API. The overall promise of our Reactive Spring efforts rely on this happening. We cannot solve the Reactive programming challenges on our own, we can only really solve them in collaboration with the teams behind Tomcat, Jetty, Undertow, Netty. But also the data store drivers over there, for example Couchbase and others.
Eberhard Wolff: [00:24:32.01] Will Reactive Spring be based on RxJava and Reactive Streams? Is that what you’re aiming for?
Jürgen Höller: [00:24:40.06] Let me fine-tune the wording. It goes in that direction, of course. It is based on Reactive Streams very fundamentally. The [unintelligible 00:24:46.04] APIs are literally at the heart of our abstractions. The other foundation that we build on, our user programming model, the Spring MVC-like reactive web endpoint model supports RxJava in the user level signatures; we don’t internally use RxJava there. We understand user signatures, basically the application programmer using RxJava in the callback signatures, and naturally bind to it. So we see, “Oh, an RxJava Observable.”
Underneath the covers we are Reactive Streams-based, using React as our internal composition library, so we understand “Oh, there’s an Observable” and we can adapt to it. We can interact with RxJava composition APIs as the user chooses to use them. We are not RxJava-based. The prototype has first-class support for RxJava as a user-level choice of APIs in the callback signatures.
Eberhard Wolff: [00:25:42.19] Reactor would be just be internal, or is it something that I could use or should use on the user level?
Jürgen Höller: [00:25:47.08] Initially, Reactive was primarily used for our own purposes internally. We need to have some composition library to implement the Reactive web stack on our own end. However, in the meantime, with the effort that is currently Reactor 2.5 and moving towards Reactor 3.0, Reactor has Flux and Mono types, those two primary pieces of API that are very suitable for user-level use. They are direct equivalents of the common RxJava Observable and Single types.
We are still in late R&D, early productization stages here, but my current prediction is that the primary user-level choice for newly started code will be the Reactor types in the end. We will also support RxJava 2 as it happens, but I see RxJava as more of a transitionary phase. For newly started code in 2017 and onwards it’s probably going to be Reactor or possibly RxJava 2 as it matures.
Eberhard Wolff: [00:26:55.11] There are other programming models for Reactive applications. For example, there are [unintelligible 00:26:59.16] How does what you wanna do in Reactive Spring to Actors?
Jürgen Höller: [00:27:06.00] Actors are fundamentally a different architectural approach towards the same problem space. I have quite a long history looking at Akka and spending a bit of time with the people behind Akka. Akka is a fine piece of engineering. The Ecto model is a fundamental choice that they made at some point initially, and it seems to be attractive to a certain architectural mindset.
From our own perspective, this is a fine choice if it fits their purposes, but we focus on a more traditional style, a more Spring-oriented style in the end, where your reactive web endpoint would be a Spring controller type with request mapping callback methods. The difference is almost only noticeable when you look closer. The signatures of those handler methods don’t expect a pre-bound object, a pre-converted payload as an incoming argument, and they don’t return a fully computed response output at the end. They rather have an incoming RxJava Observable for example, or a Reactor Flux, and they happen to return an Observable or a Flux. They are designed to interact with a hot stream, an incoming stream that has not been fully processed yet, and an outgoing stream that is being processed with callbacks coming in as we are able to write further data to the servlet output or to the HTTP container output.
The adaptability of that model is one of the sweet spots, because we can adapt it to a server 3.1 [unintelligible 00:28:49.10], it just isn’t as efficient as it could be. Exactly the same programming model can also be run on a Netty runtime underneath, with the full exploit of the efficiency that you can possibly get from the model.
We are designing a programming model in a way where it can be run on several engines with a certain focus on Netty, admittedly — it’s just a common choice out there for highly efficient network stacks — but also with the ability to run in a servlet container world even on standard 3.1 containers. However, we have an effort going on where we spend time with the Tomcat guys and the Jetty guys, creating more efficient ways of interacting with a servlet-based container. There’s a Reactive Streams common effort towards a servlet bridge where we can obtain efficient handles from a given servlet request, allowing us to interact with it through the Reactive Streams APIs. There’s quite a bit of interesting industry collaboration going on here, trying to avoid artificial barriers for efficient processing, allowing us and others to provide common programming model elements, common programming model styles without making assumptions about the particular runtime, in the sense of “Oh, I’m bound to Netty” or “I’m bound to Jetty or Tomcat here.” A common, reactively oriented programming model for web endpoints that can be adapted to those several engines. We’re back to a very Spring-oriented perspective. There is a little bit of deployment abstraction going on here of designing your application components once and being able to reuse them in different kinds of deployment arrangements. We’re back to a very original Spring promise for the purposes of reactive programming here.
Eberhard Wolff: [00:30:49.11] How would that be different if you would be using Actors?
Jürgen Höller: [00:30:53.14] Reactor is architecturally a very unique style. It’s a message-passing model with Actors being able to hold state for you. You can have an Actors-like arrangement with Spring as well, I’m sure people do this in some form, but the we don’t see Actors as an option that’s particularly attractive to the mainstream.
We are very mainstream focused in, I hope, a positive sense. Whatever we do, we aim to do it in a way that at least can be attractive to a wide range of developers, in particular enterprise developers out there.
My own experiences, and also the experiences from others I’ve been talking to is that the Actor model is attractive to a particular quarter of the space, to particular processing architectures where message passing is just a natural way of interacting between the components of your system to begin with, where it fits your architectural understanding of your own system, but it is not necessarily an ideal match for where most people come from.
[00:32:06.21] In terms of the Spring audience or the wider Java Enterprise audience, many of them do REST indirection with JSON payloads or custom payloads. Some of them do messaging on websockets, for example – particular messaging styles, but not really Actor message passing, more like message protocol payloads on the websocket channel, bound to websocket resources.
We know where people come from, and in terms of our own reactive efforts, we want to take them where they are, so keep being focused on REST endpoint architectures, REST payload processing, just any reactive style. We are not trying to turn them into a completely different architectural model. We allow them to rethink the architecture, but the idea is that you preserve a lot of the architectural investment that you already have, or the architecture understanding of your own system that you already have, and you start using reactive programming model elements in your architecture to solve particular hotspot problems that you may already have, or that you expect to be having as a kind of defensive measure, particularly nice fit with a microservices architecture where some of the microservices would benefit from a reactive approach, whereas others may be just happy with where they are, and keep being happy for years to come, in a more traditionally architected way. There’s nothing wrong with that from our perspective.
Eberhard Wolff: [00:33:31.25] You’ve been talking already about what it means for developers. You were talking about how there is a different model for Spring MVC, for the traditional web framework. Is Reactive Spring only for web applications?
Jürgen Höller: [00:33:43.08] As our initial goal that we’re working towards, it is very focused on web and print processing. However, it is by no means exclusively designed for it. We spend a lot of time rethinking our lower-level abstractions: resource direction, stream abstractions that are perfectly applicable to non-web scenarios.
As kind of a second step, we have our own messaging abstractions already. We have quite an audience out there doing message-oriented architectures with Spring, and reactive programming model elements coming in there, maybe just as highly demanded as for the web. But our initial stakeholders, the people that we’ve been talking to, early adopters, people expressing an interest in early adoption here – they are primarily interested in efficient HTTP endpoint processing. It’s a very programmatic choice for us to initially focus on it.
The wider effort, in the longer Sprint 5.x evolution will have other first-class scenarios in mind that we’re applying the same principles to. Very much in a Spring mindset, where we reuse stylistic elements across different endpoint models; we’re just going to do the same here as people would expect us to.
Eberhard Wolff: [00:35:02.03] You already said that the model will be very much like the old model, where you have add request mapping to [unintelligible 00:35:09.03] methods to certain HTTP requests, and you would just have a different signature. Is that it? Is that how the model is different, or are there any more details that are different?
Jürgen Höller: [00:35:19.02] Let’s just clarify, to avoid a misunderstanding. We’re reusing stylistic elements from our programming model. This is not running on the same engine as Spring MVC, and it does not have the full set of identical capabilities. It reuses a lot of the common elements – its controller classes with instant state, request mapping for the bindings to methods. There are quite a few common things you can express in your [unintelligible 00:35:47.05] signatures that you can also use in traditional Spring servlet MVC, but there are also limitations to what you can do. JSP rendering, for example, just does not make any sense in a reactive web endpoint model.
You know that you’re working with reactive web endpoints. You’re not working with an abstract model. You’re working with a reactive web endpoint model that makes a common stylistic impression because it reuses stylistic elements that you know from traditional Spring MVC and Data Spring endpoint models. But you know that you’re working with a reactive engine, with certain constraints in mind, certain things you can do here that you couldn’t do in Spring MVC and the other way around.
[00:36:28.19] It’s also technically two different stacks. Even in Spring 5 there’s going to be a traditional Spring servlet MVC stack, which is an evolution of what we have now, but it is its own little thing. We’re not going away from the power of the servlet model and the power of the existing servlet-based libraries out there. You can keep doing what you’re doing on Spring servlet MVC without any compromises.
[00:36:52.02] In parallel to that, there’s a reactive web stack that’s independent, both codebase-wise and in terms of its runtime characteristics. They really come together at the top end, at the programming model level. That’s where the commonalities appear again. We’re doing this with a particular vision that we have in mind here, and we’re going to have to have quite a few tutorials, nicely arranged documentation, pieces that are just illustrating both the common parts between those worlds and the strong differences, in particular in terms of runtime assumptions that you can make.
Eberhard Wolff: [00:37:28.22] I think I would also add the Spring guides to the links for the show, because they are nice to get some hands-on experience with Spring technologies. Why can’t you do JSP rendering in a reactive application?
Jürgen Höller: [00:37:41.18] For a start, there’s not necessarily a servlet contained underneath. I’ve mentioned before that we can adapt the Spring reactive web endpoint model onto servlet 3.1 containers, but the servlet model does never shine through. We are not making any assumptions about servlet characteristics. JSP is strongly tied to servlets, so there’s no way to go without.
You will be able to render templates, like trigger a free marker or a [unintelligible 00:38:08.16] render step. At the moment, that’s a blocking operation because the template engines don’t allow us to direct with them in a back pressure-driven way, but there’s still some way to go. As we evolve with this, I’m sure there will be [unintelligible 00:38:25.18] ways of talking to them in a more reactively-minded style, in a non-blocking style, callback-driven style.
[00:38:37.24] We see those pieces coming together, but even initially, if your template rendering step is very efficient, you’re only blocking for a very short period in the end. If the payload is not too large, there might not be that much negative effect to begin with.
This is part of where a reactive web application will differ from a traditionally minded one. You’re going to be very focused on also the size of your payloads and whether they’re even worth decomposing, whereas traditional JSP or template-based apps, they often just render enormously long responses out, without even worrying. We are aiming for a balance here, where people have to be very aware of what they’re doing in the reactive world to get the benefits. It is way to easy to code sort of reactively and not get too much benefit out of it. That’s a bad compromise to have, because you are spending a lot of energy rethinking the architecture, adapting to the reactive mindset, coding in a different way; you’re giving up on quite a few things, starting from longer-running transaction boundaries. You want to get some benefits out of it, so the worst possible scenario is doing it in a half-baked fashion.
[00:39:53.23] We’re really trying to do it in a way where we Spring traditional servlet MVC remains attractive to an audience wanting those benefits, that compromise, that style. My own perspective is that in the years to come a lot of new code will be written with the traditional Spring MVC model, the traditionally Spring servlet-based MVC model. There’s nothing wrong with that. As I mentioned, in the microservices world you may choose to use the reactive endpoint style in some of your microservices, but not in others. Maybe 80% are traditionally coded and 20% are reactively architected.
Eberhard Wolff: [00:40:25.29] Would it make sense to port over a servlet-based Spring MVC application to the new model?
Jürgen Höller: [00:40:32.19] With that perspective in mind that we’ve just been talking about, I would argue towards no. I would not just port it. If you want to rearchitect a particular web endpoint arrangement, a particular microservice that you have, if you want to rearchitect it towards a reactive arrangement, that’s not really a port; it’s a kind of rearchitecting of the entire service. As part of that, you may also recode your web layer towards the reactive Spring web style, that’s perfectly fine.
[00:41:00.03] Porting suggests that you take the code and with very little measures you’ve got something that delivers benefits in the other world, and it’s not quite like that. You could try to do it for very rest-oriented architectures, but if everything else remains the same, in particular your data store indirection remains the same, you might not get as much benefit out of it as you would think. In that sense, you might be better off keeping it a traditional way until you have a problem, an actual demand that suggest that a reactive rethinking of the entire service will deliver significant benefits. That’s when you should touch your web endpoints.
Eberhard Wolff: [00:41:38.15] You said that one of the reasons why you would use the new model is performance and scalability. When would you rather use the old Spring MVC model even in your applications in the future?
Jürgen Höller: [00:41:50.16] In services, in certain parts of an application where your web interaction is not a bottleneck. You won’t get much benefit out of reactive web interaction model, since it’s simply not a bottleneck. If your web requests just go in, go to a JPA layer underneath and spend a lot of time talking to a database and a lot of CPU cycles on translating the results of the database back to objects – if that’s where your bottleneck is, I’d rather spend the time rearchitecting the data store part of the system, whereas if you know that your hotspots are actually at the web layer, you may of course touch it selectively even there.
[00:42:30.18] A lot of enterprise applications are more traditionally structured, traditionally architected; CRUD applications with object relational mapping underneath. For those kinds of services you’re probably better off keeping them on the Spring servlet MVC model, or even if new services are being created architecting them on that model, as long as the rest of the architecture further down the call stack is equally traditional. There’s nothing wrong with that at all, it is a very consistent arrangement, a very consistent mindset in terms of transaction scopes and everything else. It is a benefit overall.
[00:43:05.06] I’m very much a believer that a particular service or a particular part of an application needs to make architectural sense wholesale, from top to bottom.
Eberhard Wolff: [00:43:14.27] We already spoke about how some databases are supporting reactive streams. However, if I look at JDBC, that’s obviously a blocking model, so what about non-blocking JDBC? Is that something that we can be looking forward to?
Jürgen Höller: [00:43:29.05] It is something that we can hope for being invested in by most stakeholders. The one effort that I’m familiar with is in Postgres land. It’s not really JDBC-based, it’s an alternative Java database driver, reactively minded. We are going to see more of those efforts for sure for databases where the backend, the DBMS itself and the network protocol allow for reactive implementation style. It’s very dependent on whether the backend of the database can efficiently satisfy reactive demands and backpressure oriented indirection, but we’re going to see some of this. Unfortunately, it’s not just the driver style in a traditionally-minded relational database world. You also have strong transaction assumptions in there; you expect roads to be locked for you with certain [unintelligible 00:44:25.07]. There are quite a lot of elements in the relational database world that are not an ideal fit for a reactive data store indirection model.
Eberhard Wolff: [00:44:36.01] There is a demo somewhere and the databases that you’re supporting there are CouchDB and Postgres. Or is there anything else?
Jürgen Höller: [00:44:44.22] There are quite a few ongoing efforts. This is also a particular thread of thinking here – we want to do things at the right time. We don’t want to be too early, where nobody else has reactive streams efforts ready. We hope that by next year, which is our [unintelligible 00:45:00.21], by that time I hope that more of those efforts actually reach GA status, or at least very close to it, where it becomes a more attractive model overall.
Eberhard Wolff: [00:45:13.26] What about other technologies? For example, there is JPA, the object relational mapping in the Java space, that is based on JDBC, so you can’t do JPA in a reactive application?
Jürgen Höller: [00:45:27.09] It is based in JDBC for a start, but it’s also even stronger in terms of its transactional assumptions. If you wanna make any modifications to your model being written to the datastore, you have to do them within a transactional scope. You have to load the objects within the same scope that you’re modifying them in, or you have to merge them back in. It’s almost by design not meant to be used for very short, efficient interactions with your target data store. It’s more meant for a servlet-oriented model where you’re taking a request, you know the entire amount of changes that you want to do, you start a JPA transaction, you load all the objects that need to be modified. It’s only really efficient if you do all the operations within combined transactions a little bit longer lived for that reason.
[00:46:15.14] In a transitionary phase in particular, or in architectures where only some of the requests actually go down to the datastore level to begin with, it may be perfectly alright if some of those requests then just do JPA as blocking operations in return. In a very CRUD-oriented system where almost all the requests go down to the JPA level, I would argue it’s not a great fit. If you want to do a reactively-oriented web architecture on top of it, you’re not going to be happy with the outcome.
Eberhard Wolff: [00:46:45.08] What about HTTP/2? What’s the impact of HTTP/2 on Spring, Spring MVC and the whole framework?
Jürgen Höller: [00:46:51.08] I tend to refer to HTTP/2 quite often, in particular as a theme for Spring 5 in its own right. I admit it’s more of an ongoing theme already. I strongly believe that we need to embrace HTTP/2. There’s no way we can keep doing things the traditional way in Java land without at least going HTTP/2 for a start. All the servlet containers, all our servlet-based architectures at least need to make the move towards HTTP/2 for a start, in particular in order to allow the container to do the best possible job, given the servlet model, because it works quite nicely. The impact on application developers is actually not too strong. HTTP/2 support in the servlet world is largely transparent to the application. It is a change in terms of the servers own architecture, it is a change in terms of the configuration style for the server to some degree, but the application components themselves, they can keep receiving servlet-oriented requests as they are used to. It is a very straightforward step to take – upgrade to Jetty 9.3 or Tomcat 8.5 or Undertow 1.3 or higher, configure them to use HTTP/2 underneath the covers, which is not entirely trivial, but it’s an effort you should be willing to go through. Then deploy your existing applications on top of it. If the rest of your IT infrastructure (proxies, etc.) is also HTTP/2 capable, you might benefit from HTTP/2 very quickly without having to touch your application code much.
[00:48:23.12] It’s almost the inverse situation from the reactive programming benefits. With reactive programming, you have to rearchitect your code in order to get the benefits. With HTTP/2 you can leave your code as it is, and through configuration and infrastructure updates get almost all of the benefits. In that sense it’s a no-brainer, and this is a callout to everybody with existing Spring web applications out there – please consider the HTTP/2-enabled options: Tomcat 8.5 and Jetty 9.3 in particular.
Eberhard Wolff: [00:48:54.18] Reactive Spring is probably one of the major new features in Spring 5. What else is planned for Spring 5?
Jürgen Höller: [00:49:01.23] One of our original themes for Spring 5 was JDK 9. It still is, but it’s being a little de-emphasized compared to the reactive theme. In terms of the programming model impact, our reactive programming model efforts in the underlying abstractions, the reactive Streams alignment, the preparations for Spring data, Reactive Streams support in a [unintelligible 00:49:21.21] all of those things fact back into the core framework; the core framework needs to enable all of this, so this is our widest, broadest and deepest theme. Next stop is JDK 9, it’s number two now in the theme list, not number one anymore.
[00:49:40.01] There are quite a few nice things we can do with JDK 9. JDK 9 actually is the first JDK to ship in HTTP/2-enable web stack out of the box as support for LPM protocol, an HTTP/2-enabled alternative to the good old URL connection client… We’re going to embrace all of this, force bring applications running on JDK 9. More importantly, we see ourselves recommending the use of Spring 5 in JDK 9 quite a bit for the JVM level benefits: compact strings, the revisions to the G1 Garbage Collector… There are a lot of nice improvements to the runtime in JDK 9 that Spring applications — in particular microservices oriented applications — are going to benefit from very immediately. Even without using any of the programming level features in JDK 9, there are going to be a lot of benefits to deploying a Spring 5 application on JDK 9.
[00:50:38.12] It is an important theme. We’re still tracking our efforts towards Jigsaw the Module System, but at the moment Jigsaw is not an ideal fit for our vision of what a configuration story needs to look like, so we’re not focusing on Jigsaw at the moment. Timeline-wise, at this point it looks like Spring 5 will become generally available before JDK 9, but we have had that situation before with Spring 4 and JDK 8. We’re going to ship best effort early support for JDK 9. We will basically go JDK 8 first and declare the JDK 9 support not production-quality yet, but we are likely to build on JDK 9 already, and you will be able to use Spring 5 on JDK 9 or release candidate builds at that point. There’s nothing wrong with the timelines not matching, however it is still an important theme.
[00:51:27.27] HTTP/2 we already discussed, it’s an ongoing theme that has a connection to Servlet 4.0. Servlet 4.0 unfortunately doesn’t make as much progress as we would like it to, but if it starts moving forward again towards a Tomcat 9 being based on it, we will also embrace Servlet 4.0 to the best possible degree. A couple other ideas towards alternative configuration styles in Spring, so there’s quite a lot of thinking of what we consider doing, but since we’re not even in the milestone phase yet, there haven’t been any hard decisions outside of the key themes. There will be the reactive story, there will be early JDK 9 support, there will be a strong HTTP/2 focus. As we’re going for the milestone phase, we’re going to see what else makes it in.
Eberhard Wolff: [00:52:15.06] Okay, thanks a lot for the interview, it was very interesting.
Jürgen Höller: Thanks for having the opportunity, and let’s see what everything turns out to in the course of this year. I’m looking forward to it myself.
Eberhard Wolff: Yes, thank you.
* * *
Thanks for listening to SE Radio, an educational program brought to you by IEEE Software Magazine. For more information about the podcast, including other episodes, visit our website at se-radio.net.
To provide feedback, you can write comments on each episode on the website, or write a review on iTunes. Mention or message us on Twitter @seradio, or search for the Software Engineering Radio Group on LinkedIn, Google+ or Facebook. You can also e-mail us at [email protected]. This and all other episodes of SE Radio is licensed under the Creative Commons 2.5 license. Thanks again for your support!
It could be helpful to also add a link tot he Episode 249 mentioned in podcast: http://www.se-radio.net/2016/02/se-radio-episode-249-vaughn-vernon-on-reactive-programming-with-the-actor-model/