 Okay. Good afternoon everybody. My name is Ben Hale. I'm a pivotal employee and I am the lead of the Cloud Foundry Java experience, which basically means that if you want to run Java applications on Cloud Foundry, I sort of oversee all of the teams that are responsible for doing that. And my name is Paul Harris. I'm the lead of the Cloud Foundry Java client. I've been working in tech for about 20 years now, the last three of it as a developer. So I'm relatively new to this and will be relatively gentle with you all. Great. So today we're going to be doing a talk called Designing, Implementing, and Using Reactive APIs. This talk was originally supposed to be an hour long, so strap in. This is going to be pretty fast. I am in protest so I will not read this next slide. Would you like to? Exits. There's probably an exit here as well. If you see me running, just follow. I think that's the basic message. Okay. So we're going to talk about reactive programming today, but the term reactive has been just vastly overused. It's been hijacked to me in a bunch of different things. For the purposes of the discussion today, we want to define reactive programming as something that is a way to broadly define event-driven systems. So we effectively want to take code that you've already written or code that you would know how to write imperatively, and we want to move it to a foundation that is asynchronous primarily, and this is probably the biggest thing that you want to take away from it, non-blocking. And we'll talk a little bit about why this is really important. A functional style code base, so you're going to see sort of different things. You're going to see a lot more use of closures and things like that that you may not have normally used. But the whole goal behind doing reactive programming is to give us stable, scalable access to external systems or inside of our own system. The goal is to take what is an imperative programming that can potentially get you into trouble, things like exploding thread pools, things that block for way too long, blocking all incoming connections, to sort of give you a programming model that removes that kind of behavior. And so the way we're going to do this is we're going to talk about the Cloud Foundry Java client. We give this talk in a lot of places that are not Cloud Foundry summits, which means that we have to explain what Cloud Foundry is, the fact that it's composed of about 550 different restful APIs secured by OAuth, but you all know that. There's normally a slide in here that says, don't worry that you don't understand these Cloud Foundry concepts. The names will be self-explanatory. I don't have to give that today because you all know all of these Cloud Foundry concepts. And so what we take away when it comes to writing the Java client is that we have these really, really low-level APIs. They often need to be orchestrated. So I don't know if anybody has ever looked under the hood of what CF push is. Paul will be happy to tell you CF push is at minimum 13 different network requests trying to get all of this stuff coordinated. So the Java client itself has become the preferred language for orchestrating Cloud Foundry. More than any other orchestration tool, we find that things as varied as Spinnaker, the tool from Netflix that's used to sort of orchestrate pushing applications to different Cloud platforms to something like Spring Cloud Dataflow uses this. We see it in different customers as well. We have everybody from like internally inside a Pivotal. We have an internal version of Cloud Foundry called PEZ, and they do a bunch of orchestration there. We see other clients outside doing orchestration and automating access to their Cloud Foundry footprint for their customers using the Cloud Foundry Java client. The problem ends up being that when people first started trying to do this orchestration, just making rest call response, rest call response, and knowing which of the 550 different APIs to call and what the payloads are supposed to be was really, really problematic, that kind of generic access, something like this, where you might have a map of string object and you need to pass a bunch of stuff and make this particular request really, really problematic to know that you got it right to be able to test it extensively. So what we wanted to do was write a Java client on top of it, effectively a language binding that makes things much more strongly typed, much more obvious exactly what's going on, so now you know what name should be. You don't even need to know what the payload key is. We'll take care of that for you, but you write code that is much, much more understandable, and you can do things with it that's a little bit clear to read. I want to push this particular application located here, name this thing using this build pack, and I want to map that response back, getting its ID so that I can do something. So we knew that we wanted to write a language binding for this kind of thing, but we were still toying around with what it meant, like what that API needs to look like, and it turned out that the high-latency network interaction is a really, really good fit for reactive design. There are a number of places that reactive design works really well, but as a sort of first rule of thumb, if you go over a network, you really, really want to use reactive programming, simply because it allows you to write asynchronous, non-blocking kind of operations, really, really simple. So we partnered with something that came out of the Spring team called Project Reactor really early on. We drove their design, they drove our design, and we came out with something that we think is really, really good. So what does it mean? As I said, when should we use reactive? So networking is always a really, really good example of a place to use reactive programming, because it has certain features, things like high latency. If you take a look at sort of imperative programming, whether it's the servlet model or even something like Spring's HTTP client, what you end up with is a network request goes out, but it holds open a thread. There is this binding from one thread to one request, and threads are really expensive. I mean, they're lighter weight than processes, obviously, but there is a very small finite number of threads that a JVM can feasibly keep. Maybe it's 200, maybe it's 2,000. It doesn't matter really what the number is, but effectively, if you hold one of these very scarce resources for an extended period of time, just blocking, waiting for something to come back, you are wasting it in a very bad way. We also see going across network things like failures, intermittent network failures, and what it means when the server on the other side starts sending you a huge amount of data, way more data than you can actually process. All of these things are really good indicators that reactive programming is good for going over the network. We also have anything that requires highly concurrent operations, so if you have something that can be sort of scattered, gathered very broadly, that's really good. So a good example of this was someone asked in the Java client GitHub issues the other day, how would I enumerate the tuple, org name, space name, application name for everything on my entire platform, right? And you can imagine platforms having thousands of orgs and tens of thousands of applications and things like that. If you tried to do something like this sequentially, or even if you tried to coordinate it directly yourself using fork join or something like that in Java and imperative programming, those APIs aren't great, right? And so reactive programming gives you a way to sort of declaratively say, I want these things to happen sequentially, and I want these things to happen parallely, and I can stack them together, right? So I want to, I need to enumerate all of, I need to enumerate an org before I can enumerate its spaces, before I can do its applications. But once I'm inside of an org, I can enumerate all of its applications in parallel on each one of those spaces, all of their applications in parallel as well. And you never have to manage that multi-threading, that concurrency, the framework, the reactive framework takes care of it for you. And then finally we talk about scalability. Scalability, anything that you need to handle a huge amount of data or a huge number of connections or a huge amount of load, reactive programming by its very nature of not doing blocking and doing things asynchronously is another place that's a really, really good fit. So we're going to talk a little bit about the API that we designed is based on, as I said, project reactor. And so the types that you're going to see in here are going to be reactor types, something called flux and mono. But everything that we talk about here is effectively in all reactive frameworks. So if you're using something like RxJava or Vertex or something like that, all of the concepts translate over. We just happen to use this set of names. So reactive APIs, the first fundamental difference of a reactive API from a normal imperative API is that a reactive API always returns something. It's basically what we would call a flow of values of some kind. And there are two major variants. In truth, there's really only one. There's this concept of a flux. Zero to N values are going to be returned. We also specialize. It turns out it's really useful to know if it's going to be zero or one versus zero to N. And so we have a specialization of flux called a mono. So we're going to see in examples like this, something like this. If I want to list a set of applications, listing that set returns me a flux of those applications. So I can list and then I can take that list of all those applications and I can map something out of it. So effectively what this says is for each application flowing through that flux, I want to get its name and then at the bottom we see where we subscribe. I want to print that particular name out. So you start seeing this composability where at any given line, any given operation behaves on one single element flowing through. In the end, all of the elements will flow through and each one of them will get its name and each one of them will be printed out. But one of the key differences between sort of imperative programming and reactive programming is this idea that each one of these little atoms, each one of these little operators behaves on a single element flowing through. Mono response works very similarly except it only does one. And so we see listing applications again. We get all the names. But you'll notice the next thing we do is we collect all of those names as a list. We wait until every single element has come through that flux, put them all as a list. And now I have a mono that just contains a list, which I may check, does an application name exist in that list itself, right? So it works very similarly in that data is flowing through but in the mono the big difference is only a single piece of data. And what you'll see certainly inside the Java client API is it's very, very common to sort of have a stream of stuff that gets collected into the list. And then that list is then inside of a mono. That is the one thing that flows through because something like testing whether or not a name exists, an application name, is very difficult to do if it's just sort of data going by. It's much, much more efficient to just collect all those names and use a standard invocation name contains or something like that. There are ways to do this without converting it. But in a lot of cases actually having an entire list is the most efficient way to understand everything that's gone through. So as we said every method must return something. Void is not a valid return value when you're talking about reactive programming. And the reason is because when we take a look at code a reactive flow is basically a map of execution but it is not executed yet, right? So if we take a look at this imperative operation, when I call delete passing in a string ID it executes this thing, the rest template goes off, goes and deletes something and when it returns that deletion has completed, right? So before it can get out of that delete method and get back into cleanup you can be sure that something has happened, that an operation has been completed. But in reactive programming this is not true. So in this particular case when you call delete it basically sets up a framework that says when someone is finally ready to execute then I will go delete something. So that method returns instantly back to cleanup. Only on this subscribe call here does the delete actually begin. So subscribe basically means start and I want you to hand me some information. In this particular case the use of mono void that you see up there is basically a shorthand way of saying just tell me when you're done. I don't expect you to return anything but you do need to signal me that you are complete or that you have an error. You know? Okay thanks very much Ben. So we've looked at the details that Ben's gone over now. We're going to look at a little bit at the implementation, how we've been implementing stuff reactively. So the first thing, sequential and parallel coordination. So as Ben's been saying there's a lot of benefit here in being able to parallelize things. The project reactor people will tell you most vehemently that this is not about performance, it's about managing loads and things like that. But the fact is if you can parallelize dozens of calls that you would normally do sequentially then clearly there's going to be a performance benefit there. Unfortunately doing things concurrently can be very hard to do. You've got to manage thread pools and all the other problems that Ben's mentioned. Fortunately something like project reactor and various other frameworks that are available will allow you to define sequential and parallel operations and the relationships between them in a pretty simplistic way so that you can concentrate on the code that you need and you can leave it to the framework to do the hard lifting of managing those thread pools etc. So if we take a look at a little example here this is about retrieving some list application information. We have the first method is a get page and all it does is make a call and say give me a page defined by the page number that we've given it. So underneath that we have the main method that starts very simply. It says give me the first page and when it gets that first page back there's a bunch of resources on there but there's also information about the payload that we're requesting. One of the information items on that payload is the total number of pages so it could be two, ten, whatever. So what we're going to do is we're going to extract that information out and we're going to have this thing a flux range so flux a bit like a stream in Java 8. It's going to say give me a list of numbers from two to whatever the total number of pages and for each of those numbers I'm going to do a request to get page. So that flat map says I want you to do all of those at the same time so it will do get page for page two, get page for page three and so on. It will make all of those requests, it will put them together with the that start with there just says don't forget about the first page that we've already got and it will put all of that information together and well in this case sys out obviously not terribly useful but a good example. So the key thing there is we started with a single operation and then everything else, every other request from there happened in parallel, big performance gain potentially. So as well as just defining simple flows like that we can do various sorts of conditional logic. It won't surprise you to hear that we can do the standard things and branching and so on but there are a couple of slightly more unusual things that we can do as well. One of those is we first need to understand that in reactive programming an error is just a value that can be passed on the same as any other value. That means that we can pass it on to the consumer if it's something that we don't particularly know about we can just say here this error happened. We can change behavior, we can generate new values based on that error as well, potentially if it's something that we're expecting to see. So if we look at this example we're going to do an application statistics request so we want to, for a particular application we want to know it's uptime memory usage, things like that. In the normal run of things we give it the application request and we say based on this ID retrieve this information for me it will go and take a look and say here you go here's the information you were after uptime etc. But we may get an error back and one of the errors that we could get back is an application stopped error and what that says is there's nothing wrong everything's working fine it's just that the application is stopped because it hasn't been started for some reason. So in that case we do an on error resume so we've got an error but we don't want to stop we want to resume we want to continue processing and in this case we're going to return an empty object that says I checked there was no information but you can carry on normally and use that information. What it doesn't do it's not a catch all for errors so we've specified that is an application stopped error if anything else comes up then somebody else is going to have to handle that we'll pass it on however we decide to process it. As Ben mentioned earlier not everything will return a particular value sometimes it will just return a complete to say I did the thing you asked me to do and now I'm done and we can use those indicators in the same way that we were using the errors we can again use logic from them we can pass them straight on as just here's the value that came out. So if we take a look at an example of that with this empty logic something that may be familiar to you if we're trying to find a domain based on its name we don't necessarily know if it's a private domain or a shared domain so we have to check both places. So we start here by saying get the private domain ID based on a name and it may return a value in which case we'll pass that on as a string is the ID. If we don't get a result from that if we get an empty that says I checked and there was nothing there then we switch based on that empty and we go and check the shared domains and we do a query and we get back a result and again we may get a positive result we'll pass back the ID but it may come back again saying I checked I still don't have anything for you in which case we now have a problem because we've checked shared domains we check private domains we don't know this name that you've given us and in that scenario we've got an error and we will report that as an illegal state exception so you can see here we've changed logic based on whether we got a return back and then eventually we've actually changed the return type or the return value by generating an error. Okay that's a little bit about processing now we've got some testing which I'm sure you'll all be wanting to do. One of the problems we face when we're testing is that most useful flows will be asynchronous that's what we're about we're trying to use this asynchronous to speed things up to make more efficient use of our resources. Unfortunately in this scenario most testing frameworks are aggressively synchronous so they run the test then shut down as soon as possible and that gives us a problem because we are waiting for something to happen asynchronously that the test will not wait for so what we need to do is to block the main thread and make test assertions in the asynchronous thread and we've got a little example of that here. So I'm going to generate a single value alpha just one value I'm going to subscribe to it and then I'm going to assert that the value I get equals bravo now fairly clearly that should fail and sure enough when I run it it's actually passed and the reason it's passed is because the processing that did the assert equals happened on a secondary thread but whilst that was off doing its thing the test looked for completion didn't see any failure because the assert equals didn't generate anything on the main thread completed and as far as it's concerned everything's passed fortunately project reactor gives us a way of dealing with this and that's to use something called the step verifier the step verifier has a number of other benefits as well as just handling that blocking which would be enough it allows us to do things like multiple value assertions expected error assertions unexpected errors if there's something that we didn't actually know was coming back we can still handle it so if we look at an example of just one of those things the multiple values we're generating a flux here so we're going to have two values emitted alpha and bravo we subscribe to it using a step verifier and then we're going to say we're asserting in effect three things we expect that an alpha will come out and the alpha will be first we expect that bravo will come out and that will be second and then the third thing we're saying is that that's all that we will get back so the next signal that we get is an expect complete give it a duration of five seconds because this is asynchronous which means we don't know how long it's going to take but we know we don't want to wait forever and I don't have a slide to prove it but trust me that works okay so that's implementation that's here's a little bit about how we've been using it and how we expect other people to use it as well one of the big problems that we see a lot of people facing is that the reactive framework can only coordinate its own operation it doesn't know about the environment around it so whilst it's managing its own threads etc what's happening underneath is not visible to it now a lot of the time that doesn't matter if you're running in a servlet container for example it's effectively long-lived and the reactive framework doesn't care what's going on but there are situations where it can cause problems and obviously one of that in addition to the testing we just looked at is if you're running in a main method which we'll try to complete as soon as possible so if we have a look at that happening and what goes wrong I'm going to emit a single value here alpha I'm going to delay the subscription so I'm going to wait for a second so if there is a problem here with concurrency and asynchronously then we will find out about it we subscribe and we're going to try and sys out the value that we get back and when we run that it runs to completion because there's no problem with running it but when we look at the values that come out we see that there aren't any values because the main thread completed before the subscription which was delayed actually got to do anything the way we handle that is using a countdown latch so what we're going to say is I will set up this precondition that needs to be satisfied before the main method can complete and I do that by creating a new countdown latch with just a single flag on it again the code is pretty much the same I emit an alpha I wait for a second I subscribe and you can see I've got some parameters inside that subscribe I'll explain what they are in a moment but the key thing here is that they count down the latch they release the latch in this case and when I run that I wait for the latch and what happens is it executes again because still nothing's gone wrong but this time it's actually waiting for the alpha to be emitted so as I said we've got some additional parameters in there they are let us define the behavior that we're going to have in particular scenarios one of which is error handling as I've said before errors will just go through naturally until somebody catches them so we need to be able to handle those things so if we take a look again a very similar piece of code we're setting up a countdown latch again this time we're going to have a flux I mean it's going to have two items in it the first one is just a simple string and that will work just fine but the second item is an illegal state exception so we know that this is going to throw an error we subscribe to it and then we have three parameters inside that subscribe the first one is on next which just says the next time I get something that comes in do this and that's the normal operation if you like and in this case we will set out the second one is what happens in case of on error and in that scenario we want to do something we want to handle the error in some way here we just print out the stack trace pretty straightforward but we also want to make sure that because we've had an error and this is a terminal condition if you like that we need to count down the latch we need to say this processing is complete the final parameter there is on complete so if everything has completed successfully we've had however many things emitted and now the flux says I'm closed then we still need we could do some other processing as well but we still need to release that latch to say this process is now completed we do the latch await and again that will execute correctly just going back to that actually this is one of the two biggest problems that we see people having when they're using reactive not just to do with our code but in any time that um you've written code that you think is great and it produces nothing because everything that's happening is off on a different thread and you don't see it so if you start using rector and you you don't get the results out that you're expecting it first thing to think of is countdown latch it's not necessarily the solution but it's a good place to start one final thing is point free style so you may have noticed from the code samples that they're using something that might look a little bit unintuitive if you look at it from an imperative point of view there's a link there to point free style guide and the reasoning behind it um what we found is that um it's kind of unintuitive at first and Ben certainly didn't like it when we got started um but after a while you get used to the the style and how it works and and it becomes more readable becomes more compact which helps with understanding the flow so if you look at this um slightly more complicated example i'm going to delete an application so i'm supplying a name and i've got two steps that it needs to take first of all it needs to look up the id based on that name and then it needs to actually do the delete based with that based on that id so you can see that the first builder that i've got there i could construct that in advance i could set up a variable and just insert the variable name inside that but you can see that in the second um builder i can't really do that in advance very easily because i don't know what the application idea is there are ways around it you can um create an unbuilt builder if you like and then just complete it inside there and there are various other cheats you can do but we found that ultimately when you get used to it that this style of um effectively inlining everything is much more useful uh than than trying to stick with the old style of imperative code okay with that i'm going to hand over to ben to wrap up yeah just to sort of build on this a little bit um you do end up with much denser code than you might otherwise um there are ways around that uh so if you ever took a look at the java client code itself you'd see that we'd never actually write a flow that was quite this dense that had this many lines will you you get a lot of reward from really extracting out uh methods and using the java method reference syntax so instead of um this whole second uh sort of flat map here with application id there'd be a method called uh was it get application id or delete application or something like that um that would take in just the application id and so this would sort of collapse to become a one liner and the same thing with the pagination utils and that whole thing that would you know have a list applications method that's absolutely compresses and so this realistically um even using point free style collapses down to like two or three different lines and the key is that it ends up being much more readable whether like if you're taking a look at it um even expanded like this i don't think anybody really thinks at having a bunch of assignment and equal signs and curly braces and stuff like that makes this any more understandable than if you sort of collapse the whole thing down into very small methods that have very clear names on it so uh with just a couple minutes left uh let's go ahead and take a look at um a summary of this so we talked a little bit in the very beginning about how to design so when is it appropriate to use reactive programming the key the easiest one um and probably the first place every single person is going to get involved in reactive programming if you choose to is if you're doing anything over the network the the sort of ability to do asynchronous non-blocking style programming inside of java is the key reason to start taking a look at reactive programming uh reactive methods must or methods and reactive apis must always return something void is not reasonable um you always want to return mono and flux and as i just said you want to have these very small reusable methods and if you take a look at our code you'll see um that a lot on the implementation side remember back at the very beginning i mentioned that one of the key value propositions of something like um project reactor rx java is this idea that you can declaratively say here are the things that need to happen sequentially here are the things that are allowed to happen in parallel with one another and you can look at it and read it and understand how these things are related to one another but someone else some other framework is responsible for doing that coordination in the most efficient way and if you take a look at reactor um things that you think might have been parallelized uh aren't necessarily because it turns out that doing things in batches uh but doing them sequentially can actually outperform doing everything in parallel um or everything in parallel at the exact same time and so you want someone else working at a different layer of abstraction working that out for you and you are simply saying here's what needs to be sequential and here's what's allowed to be parallel finally in the implementation um testing is a really key thing but has a lot of caveats or a lot of gotchas simply because so much of reactor programming happens asynchronously on different threads and test frameworks aren't necessarily designed to um uh think about things in that way on the use side um we said there are a couple things that go um problematic um you want to probably make sure you're using things like countdown latches to guarantee that you're holding processes open um longer than they might otherwise simply because a bunch of stuff is happening on other threads um there are ways we didn't discuss them in here but there are ways to effectively say uh I don't want to use a countdown latch I just want you to turn this back into asynchronous non asynchronous thing by blocking it open um we saw how to handle errors remember that errors are actually values that flow through a chain there are no exceptions uh you pass exception types around but nothing ever gets thrown in reactive uh you want to make sure you compose methods and obviously the point freestyle we discussed there at the end so that's it for us uh thank you all um I think we're right at time now so I will step off the stage and allow the next speaker to come up and we'll answer questions thank you very much