Guide to "Reactive" for Spring MVC Developers

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to my talk guide to reactive for spring MVC first of all a couple of words about this session I decided to make this talk for spring MVC specifically because that's where the majority of applications are today and I want to give a heads up that this is a somewhat introductory talk the idea is to kind of break the ice you know with reactive and try to make it understandable in a way that you can apply it in existing applications and also to learn a little a little bit about it to get a little bit of exposure from a practical perspective which doesn't expect you to make big changes that you might not be ready for so if you have quite a bit of experience with reactive or if you've been doing stuff with it already you might find this session to be a little bit below your level so just keep that in mind as we begin a couple of words about me I'm a committer on the spring framework team I've been on the team for about six seven years now spring engineering before that I did training and consulting for spring applications and even before that I did lots of different enterprise application development in various domain domain so I've been around Java and Java development for quite a bit of time right so when we we've had lots of reactive talks in the past more than a couple of years here at Spring one and in other conferences and even at this conference you will find that the majority of the talks are going to focus on using a full reactive stack and this is completely understandable because that's where you get the most benefits of the non-blocking concurrency approach but at the same time this is not necessarily something that everybody is ready for so here's for example full reactive stack that we have with spring web flicks where you can run completely asynchronous foundation using non blocking i/o which is a fundamentally different way of processing and dealing with requests and responses versus the more traditional servlet container assigns a thread for a particular request and then do the processing for that and then you can block that thread as you want to here we're talking about a kind of a more non blocking approach which means that we're using a very small number of threads and then as we process the request and response if there is a slowdown then we might basically pick up later so there's a lot more switching of threads but ultimately the benefits of that concurrency model is that it's more efficient it's more scalable under load and and that makes it also more resilient but the question really here is how can we use this in order to add value to existing applications I keep thinking that's my microphone and that's not my microphone so how can we add value to existing applications that's the big questions here and the reason why this is a kind of a useful approach or useful perspective in my mind is because if it's less risk you don't have to switch to a whole new stack you can get practical hands-on experience with reactive programming can get exposed to what does it mean to actually work with reactive libraries and I'm gonna show you some stuff which hopefully will have some immediate benefits for what the kinds of things that you do in your applications so in spring MVC of course spring MVC was built for the server's api and for servlet containers it was built for the original version of the server's API in modern times the servlet API has a non-blocking i/o option but this is not something that you can introduce into an existing ecosystem of frameworks like spring MVC and others like time leaf and many others in the ecosystem without changing fundamentally the contracts underneath in the framework itself you know the assumption is for blocking i/o that when we do a read or a write to the request the response we're going to wait until that write is complete and then we're going to continue those kinds of assumptions are very difficult to break without changing the contracts and the foundations of a framework so that goes very very deep to make that sort of change but in spring MVC for quite a while now many of you will know this is that we've had support for asynchronous request processing this came with servlet 3 daro and Spring Framework 3.2 so it's been around for three generations already and it's used very widely to decouple the processing of the request from the servlet container thread that's the thread per request model which we had originally and for example in spring MVC you can return a deferred result you can also return callable and there's others like SSE and meter and that basically allows you to let the servlet container thread go we exit all the way from that thread and then we can continue doing something in the background while the response remains open and then when we're done with whatever it is maybe we're waiting for an event maybe we're computing something maybe we're making a remote call when when that something completes then we can actually write to the response and at that point it's still a blocking right but the actual handling of the request can be decoupled from the servlet container thread and we can use that same foundation for for us to be able to handle the requests reactively and we'll see what that means but essentially we're talking about using reactive libraries in order to do some sort of handling and then return back to the controller so the first thing I want to talk about is a reactive client for HTTP making HTTP requests how many of you here have used the rest template everybody yes so rest templates we've had it for a very long time it was created 10 years ago for Java 1/5 and it's very widely used for making HTTP calls it's a simple API based on template methods so you get a sort of a one-liner to make a call these kind of recipes for making HTTP GET HTTP POST originally the there were 24 methods in that api and this was designed for java 105 so that was the sort of state of the art at the time today those methods have gone to 40 plus so the experience that we had over time with the rest template was that at some point we started to have too many variations of these methods and the whole template method approach begins to become a little bit cumbersome you go into the IDE and you do a control space and then you see a ton of methods and over the years there's been a number of times when we chose not to add methods for things that are less common so for example if you want to do an HTTP delete with a body I don't think we have a method for that specifically to make that easy in the rest template you have to go to one of the exchange or execute methods which are a little bit more general so we try to hold back they could have been more than 40 today so that's kind of one limitation that we ran into over time with the API of course it was designed and built as a synchronous blocking API from the start which was ok ten years ago because you know the idea was that he used the rest template in a client and in a client you know if you make these kinds of calls it's not a problem to block because we're talking about a single thread anyway and it wasn't very common to do a very high concurrency type scenarios there's also no streaming I say no streaming it's a little it's possible to do streaming with the rest template in one direction but not both but it's not easy and it's pretty low level you're basically streaming the bytes it's not something that it was built for originally so fast-forward 10 years and let's see what's actually happened during those 10 years and why the rest template looks a little bit dated by now well first we have Java 8 and just like Java 5 brought new features like annotations Java 8 brought lambdas and new options to design API is in a more functional style in a more functional way so that's one big difference is today when we take a look at redesigning what should a rest client be it's it's a very different context Moore's Law is no more well we know that right the the speed at which the hardware continues to get faster and faster stop some time ago or or is not we're not getting a free lunch from the hardware anymore but at the same time the applications are becoming handling bigger loads and they have to do more asynchronous things on the server side or rather things that are that require IO and waiting and really with the rest template or anything of that nature which is gonna make a remote call we're pretending that it's synchronous because that's the simplest API that we can use but of course network operations are not synchronous and we're only pretending like they are and in many cases we can no longer pretend that those operations are six synchronous because that has a cost and a price associated with it and it takes more resources and it takes more time and it's difficult to orchestrate a number of different calls and to do that efficiently so we have the web client which came in spring frame or five and that has a functional fluent API we took a different approach versus the rest template where we did not want to be in that same position where somebody is asking for HTTP delete with the body and we have to say no because it's way too many methods that we already have we did not want to be in that situation so it's designed with a more functional flow and style API I'm going to show you something in a little bit in a moment it's asynchronous in non blocking from the foundation from the start which means out of the box it is asynchronous and non blocking and you have to do something extra in order to block and wait for the result so in that sense it's completely opposite from the rest and put it's reactive and declarative which goes along with being asynchronous and non blocking because when you are declaring asynchronous operations you want those to be declarative in the sense that you don't want them to kick off immediately you want to be able to come declare several of those together and then kick off and have them go off and do what they need to do and reactive it's exposing reactive types from a project reactor flux and mono and we're gonna see that in a moment part of my goal here is to actually get you exposed to that as well and to get a sense how many of you have experimented with reactor ok quite a few hands rx Java perhaps ok also quite a few hands ok how many of you think that you are sort of intermediate level at least or beyond intermediate level ok a couple of hands who thinks it's easy ok no hands who thinks it's hard ok I mean that camp as well I started from that and after working with it for a while I can tell you that there is light at the end of the tunnel it's very steep in the beginning and once you get to a sort of plateau and then then it doesn't bother you anymore at least that's my experience and I've talked to many people sharing the same the last thing I'm gonna say about the web client and out-of-the-box features is streaming so the whole async non-blocking design and reactive is a very good natural fit for streaming because we're processing data that comes from the network in bits and pieces and we already have to do things in that way which makes it very kind of a natural step from there to turn that into decode that into objects and to provide that in streaming fashion because the API is we expose they already behave in this way ok so let's take a look at this with some codes ok so the first thing I'm going to show you is a a kind of client application it's not running on a server I'm just gonna run it here by itself and it is using the rest template so that's the original client for HTTP access that we have in the spring framework and the only thing I will show you here is that I'm setting up a base URL and that's going to another application that I have locally which is going to simulate a delay you can see that parameter there I'm telling you to delay each request for 2 seconds because I want to simulate some Network delay and that I'm if you haven't seen this by the way on the rest template there's a-you right template handler method so I can configure how you're right you're right templates get expanded and I can for example provide a base URL and then the rest of it is pretty straightforward I have a for loop and I'm going to make three calls to obtain a person information from the rest template and each one is going to be delayed by two seconds so let's go ahead and run that okay so first one takes two seconds second one takes two seconds and then the third one as well and the total might be a little hard to see in the back the total is six seconds over six seconds because each one take two takes three seconds so obviously this is not a big issue depending on what you're trying to do but you can imagine that in modern day applications we have to do more and more of that and this is only the simplest possible example in a for loop you might have to do things in a more kind of coordinated fashion where you make one call and then you take the result then you make another call or maybe you want to make two in parallel so when we when we save the restaurant it is easy and I'll come back to this question it all kind of depends on what you're trying to do it's not that the rest template became less easy over time is that the things that we do are quite different okay so let's now take a look at using the web client and I know Josh and others are really good at typing on stage which I'm not so I'm going to copy and paste okay wow I to type fast so we have a new version here now copied the wrong one how about that that never happens right okay no that's better importing the web client so that's a good sign so this time I'm going to create the web client and it's going to the same URL and that you can see I'm providing a base URL as I create the web client and then I'm gonna go in a for loop and you can see here that the API is a little bit more it's it's kind of different all along the way I can get suggestions so when I first start out I get the HTTP methods then I can specify a URI most likely but I can go straight to other things if I want to go with the base URL and then after that I'm going to call retrieve or exchange we're going to talk about the difference but retrieve is sort of the simplest option and then I'm going to specify how I want to decode the the response and in this case I'm going to turn it into a mono mono versus flux is a single value versus multiple values and I'm going to turn that into a person and let's go ahead and run this Wow 300 milliseconds wait a minute something is wrong here this can be that fast anybody see the problem something in the base URL any other takes I'm not blocking at the end okay we're getting close yeah any others not doing anything with the person so do we even have a person let's take a look let's try and turn this into a local variable sorry I'm not subscribing there you go bingo so that's the answer right there so this whole thing is deferred it doesn't it's asynchronous but it also doesn't kick off until I do something until I subscribe and you can see that I get a mono and you can think of the mono is a promise of some I'm going to get but it's not going to go and try to get it until I actually explicitly subscribe or ask for that to be to be obtained so let's give that a try and subscribe okay so let's run that okay 423 milliseconds crates still very good but that's not the I don't think we are successful here because it seems like we got farther we actually fired the requests but subscribe itself does not sit and wait it does not block so we simply kicked off and then you know we took 200 more milliseconds and looks like something started to happen but we actually did not do anything so what we're going to do instead is we're going to remove this subscribe and of course we could somebody mention we could block and we could do that and that should do it but this kind of defeats the purpose of being asynchronous and non blocking in the first place right this is back to what the rest input does and and this is where it said it's asynchronous and non walking out of the box but you can turn it into a synchronous blocking if you want but this isn't really the way to do it because you want to defer and you want to make the most of the concurrency model here so what we're gonna do instead is we're going to think about turning this into Manos and then we're gonna collect these Manos and then we want to kind of wait for all of them to complete and do something with that so I'm actually going to use the stream API to make this get rid of this loop so we're gonna iterate over three and we're going to do a map of that index and then I'm gonna take this code down here since we have enough space let's do that mm-hmm and then we're going to collect all of this into a list and what we've got now is a list of Manos and now we've got all the Manos together and we can start using some of these reactor operators and this is where the power comes of all this what's available to us so we can say collects but of course that's a not a very good variable name let's say all our person Manos that's better and of course now we're declaring that we want to wait for when all of these are complete but we still need to subscribe in this case we're going to I'm just gonna do a block and let's go ahead and run it so you'll see they all kick off immediately right because we're starting them off and they're running in parallel in three concurrently that is and then we get back the result and we get a total of 2.9 milliseconds so roughly two seconds but a little bit more not quite two seconds but that's pretty much the the time it takes to execute one of these and because they were executed concurrently but if you if you pay attention and this is actually I'm also showing you some 5.1 goodness here with the logging one of the challenges here and first of all you will see that if you look at the threads we can only see three different threads here one is the main thread where we kicked off and then we see to react to native threads one is number six one is number eight so we're not necessarily using as many threads in order to process three different calls concurrently and that's the non-blocking concurrency model that I'm talking about in fact reactant ad out of the box runs with only four threads which depends on how many cores you have on your machine but the point is that as I need more concurrency it's not going to use more threads that's the blocking style if you block you need a threat to absorb that blocking but here what it actually does is it relies on callbacks under the covers where it fires off these HTTP calls in the beginning and then it waits for the result to come back and then it deals with the result but it doesn't need as many threats to do that right it can go in a sort of a event loop fashion and we can correlate and you can see that for example this here correlates with those two below the response came and they came in different whatever order they they came they came back and then the total was they were you know executed concurrently one question here okay so just for those in the back the question is if we created another web client at the top would that create a different event loop and would it use different resources that's a great question no in fact out of the box by default with reactant ad the behavior is that it participates in globally defined resources which you know you may or may not like this model but it's safe in terms of the idea is that there's only one event loop you don't really want more the whole idea of non-blocking model is you don't want more threads so by default it will do that but in 5.1 and i believe we back ported it to five oh there is a possibility to create the web client with explicitly given resources and then you can share those resources kind of the more traditional style of passing around the resources so that's also possible okay so we saw this one more thing that we're gonna do here let's do this so right now over here I'm using it's kind of split up the processing in to make this a little bigger first of all I'm using the Java eight stream API in order to collect those lists this list of Manos and then I'm using mono dot when so let's use all reactor facilities for the same because that's going to help us to make a single a single chain and now from here we can repeat now one thing which is tricky that I want to point out is that here we have a map operation and the map is going to execute this here but what was our experience in the beginning when we just try to run that it doesn't do anything right something needs to subscribe to it so if we simply use a map operation we're turning the index into a mono but that mono isn't going to be triggered automatically so when we work with reactor whenever we want to make a nested asynchronous call which itself returns a mono or flux we're going to use flat map and flatmap is actually going to subscribe to the mono and it's going to produce a if you look at the return value of this that's a flux of person so it took a bunch of Manos and turned them into a single flux of persons which is exactly what we want here right we so that's where this flat map nesting that's what it brings us versus a simple map which would give us a flux of mono of person so it's that's why we want to deal without nesting and now now that we have this we actually don't even need the mono when because we can go here and we can just say block for the last one of course there's no longer a flux of persons or we can say something like do on next and then we can take a look at each person and we can do something with that person basically we're getting a flux of those things or we can just say then which gives us a mono void so dope then basically says when all of this is done tell me when that's complete so I can just do that and then dot block but really it's the same thing as saying block lasts just block for the last one wait for all of them until the end so let's go ahead and try this so okay and that came back okay one more thing I wanted to mention here with the web client is the retrieve operation so the retrieve operation gives us kind of a straight path to the body of the response so we can just say body to Mono but if I wanted to I could also say dot exchange let me kind of mess this a little bit dot exchange and what this gives me is actually it gives me access to the response before the body has been read so now I can say response dot status code what's the status code I can say response dot headers what are the Heather's but if I want to deal with the body then I have to specify how I want to decode the body and that's an asynchronous operation right I'm going to have to wait for the data to come and then decode and that's why I'm using a flat map so I can return here and I can say let's turn that into a person and type it in just so I can remove it okay here we go so this gives us exactly the same thing but you can see here I have to do an extra flat map and that's a more advanced operation if you if you want to kind of peek into the status code if you want to look into the headers before you decide how to deal with the body but for the most part usually you can just use retrieve and then deal with it that way one of the other things you can do with the response here you can say to entity and you can say person class so that that will give you a response entity just like with the rest template if you wanted to get the body or if you wanted to get the call response entity okay one more thing to show you here and I'm gonna copy that mm-hmm in the interest of time so one of the other things that's interesting to do is imagine that for each one of these HTTP calls that we make we want to make a nested HTTP call which means that we want to make another one and then we want to combine the results so those are the kinds of things that you might end up you know kind of orchestrating and I just want to show you how beautifully easy it is to declare such things and and to point out the fact that you're not dealing with threads and yet the whole thing is fully concurrent and and does it in the most efficient manner possible so here the beginning is very similar to what we had before we're going to make a call or three calls for a person then we're going to decode the data and then we're using flatmap again because we're nesting to another asynchronous operation so when we get this person here when that one of these is ready then we're gonna make one more call this time to obtain a hobby for that person and then we're going to turn that into a hobby class and then block for the last thing so let's go ahead and run that and this time we're going to see the first three calls go out and then as soon as they come back the second three calls go out so it's it's all running kind of concurrently as soon as the data becomes available it fires the other calls and the whole thing completed in 4.7 seconds but this is if you think about it you know if you do this sequentially you would it would require six times two seconds 12 seconds so we're saving quite a bit of time by doing this s concurrently as possible cool right yeah definitely hmm okay then one more thing here is this which is the streaming case so I mentioned that this is a natural fit and certainly you can see here how when we're saying body to Mono we could just as well say body to flux we go into this is actually an SSC stream and we're going to obtain the first for and and then what's happening here 404 not found okay so it's actually time to look at the backend app okay so I have two apps one is the main app and then the second one is called remote services so we're kind of simulating some sort of back-end remote services originally I was using HTTP binbin org anybody heard of HTTP Binda org seen it and then when I was doing my own tests and I'm simulating delays it was delaying much more and I said okay what's wrong with my web client and then I look and I'm looking and finally I realize it's actually the website is taking longer so I decided to write my own kind of back-end here now this is a web flex application it's not relevant to the to the presentation but I'm going to show you what's here anyway this is using a the Java DSL for for the functional endpoints and you can see here I have URLs for person persons a stream so persons events I think that's the problem oh yeah it looks like I renamed it and let's run this okay and there's one coming every two seconds and I could leave it to run all day it can stream for for a long time but in this case I'm taking only the first four and I wanted to show you here the filter so for all of these requests I have a filter applied and that filter is gonna look for the delay parameter and then if there is a delay I'm going to use mono delay and then flat map and then delegate to the chain so you can see how easy it becomes to kind of simulate these these sorts of things okay okay so back to the slides a good question here is isn't the rest and put easier to use and that's kind of a common a common question and of course when we come from having used it for 10 years and you know we think of it as being simple well it's really the things that we do that I've changed if you find yourself in a situation like this where you have to make multiple calls if you want to think about how to make that concurrent how to make that efficient and then on top of that to actually think about efficient execution so you can scale well that becomes a very different game and it becomes very difficult to think about you know dealing with threads and executor x' then in that case by all means it's not easier and it's not simpler so it really depends on what you're doing personally my feeling is and once you get over the barrier of learning about flux and mono which I think in the context of web client is a lot easier the other thing you will come across is debugging experience obviously we're doing things concurrently but when we're trying to figure out what's going on obviously now we're dealing with a small number of threads dealing with a large number of things and when you want to debug the kinds of stack traces you see you cannot no longer use the stacktrace to understand you know where exactly the code and reactor has features for that if you go into the reactor documentation there's a section about how you can enable better stack traces which has a certain cost associated with it but if you're debugging that can help you a lot but the whole experience changes and sometimes the initial reaction tends to be the web client you know is more difficult but that's a case of killing the messenger because don't shoot the messenger because really now you're in an asynchronous environment and the problem is not the web client the problem is that you are trying to do things asynchronously and concurrently for good reason and even if you're using executor x' you wouldn't be in a better place your debugging experience would still not be very easy so it kind of comes with the territory will the rest template be deprecated so we contemplated doing that in 5.1 we had a conversation about that and at the end we decided not to deprecated it just yet because there aren't any concrete drivers at this time ultimately in the long run we don't want to maintain two parallel solutions in fact as we have to have new features to four HTTP client access we're not going to do that on the rest template side because we don't want to develop in parallel and the web client is a better place for for new features in any case so if we talk about the JDK 11 HTTP client being supported is one of the options that's only going to come to the web client if we talk about you know requests like streaming we're not gonna try and add that to the rest and put because as you can see there's just so many reasons why the web client is a better place to be so well it's not deprecated we have mentioned in the documentation that it's something that we are going to do at some point but at this time we don't have a strong enough driver and there's no harm you know if you're using it there's no harm in continuing to use it it isn't bad all of a sudden but please take the time to spend a little bit of learning around the web client and use it where it's appropriate speaking of that if we now go to the server side it all begins to make a lot more sense in spring MVC originally we decided that we're going to keep reactive support out of spring MVC and strictly in wet flux to make sure things are not confusing however as we got closer to 500 we realized that by all means we actually should have support in spring MVC and the reason is because the whole idea with spring MVC anyway is that if you do something in the controller the framework should adapt you know those flexible controller method signatures so what if you use the web client now you've got a mono or you've got a flux and the most natural thing to do is to return it from the controller method so we should be able to deal with that because you're likely going to do that in fact it is a good idea to do and for this reason we have support from five-o so it's been there for a year but it's just something that we haven't pointed out as much and I think a lot of people don't know about it but you can return flux mono you can return rx Java types from a controller method and we are going to deal with that spring MVC is going to handle that it's going to use the same mechanism as the deferred result for those who are familiar in spring MVC decouple from the server container thread and then deal with the flux in mono so it's built on the server 3 or async support under the covers this is what we do if you give a mono that directly translates into a different result we're gonna wait for the mono subscribe to it and then set the deferred result so if you're familiar if you're using deferred result it's basically something that you would understand or it will be familiar if you return a flux a flux can have any number of items we don't know how many items will it be a finite collection will it be an infinite stream so for that we actually rely on the media-type we in order to understand is this going to be a stream or is this going to be a finite collection most likely if it is application JSON for example we consider that to be a finite collection you're not going to be sending endless number of those so we aggregate them into a list and then we basically treat it as a deferred result of a list if the situation is streaming however say for example we're talking about event stream server sent events there's also another one we support called application stream JSON then in that case we have a clear indication that there's going to be a potentially infinite number of events well Infinite is a strong word but it could be we don't know when it's going to end it might be awhile and there may be some time between the items so instead we're going to basically write that to the response using response body emitter and we're actually going to apply back pressure against that which means that if you give us a flux we're going to keep requesting one at a time and applying back pressure to whatever the source of that is so this works pretty well with the web client and you can make these kinds of concise declarations orchestrate remote calls from the server side you're not dealing with threads anywhere and on top of that you get efficient scale and execution which is important on the server side because if you think about it it's no longer just using one web client you're sharing that if you have a hundred requests coming at your server each one is using the web client well that's a hundred automatically and a hundred concurrent remote calls that you're making so you're automatically much more concurrent scenario when you're on the server side and of course with the web client you automatically get the efficient scale under load and it's using only four threads again depending on the core and the reactive handling is not just the web client so we have spring data repositories as you know spring data kay it's got MongoDB support that's got couchbase Apache Cassandra and this out of the box and we have some more exciting news in that area coming tomorrow so be sure to look for that in the keynote tomorrow morning and there's also talks so if you look at the schedule it's actually there it's not a complete secret the Cloud Foundry Java client is built on a reactive foundation it returns reactor types so there's lots of various libraries by now that are using reactive streams and maybe args Java maybe reactor all of these things to react the streams you can mesh together and you can compose pipelines of things declare asynchronous things to do and then just return back to the controller so let's take a quick look at that also I mean it's more or less what we've seen so far but in this case it's on the server side so I have a controller and I have a web client and in this case I'm using I'm injecting a web client builder which spring boot gives me and I should show you the maven pump for that briefly mm-hmm so one of the things when you want to use the web client and the web client is in the wet flux jar you're going to have both the starter the web starter which gives you Tomcat and spring MVC by default and you're also going to add the wet flux starter and when spring boots sees both of these in the same palm it knows okay so you probably want to run spring MVC and then use the web client or some other client-side facilities from the web flex jar okay so now if I start this application I want to show you here so this is running this is running with Tomcats okay okay maybe we'll see that in a moment and what this application does is I've got the web client builder injected and I'm giving it a base URL so I'm gonna be contacting that back-end remote service from my controller and then I also have an account repository which in this case is a repository and you can see that on startup I'm actually inserting a number of different accounts with a score associated score and then this is the implementation for a person you can see simply making a remote call it gives me back a mono and then I'm gonna give that mono back to the controller as a return value from the controller method or I'm gonna return a flux of Persons so let's go ahead and run something here and this is the main app so 8080 and let's go to person dot one takes two seconds and then it comes back with the data and you can see the actual log so that's the dispatch of servlet so yes this is spring MVC and we are going to handle this request and you can see here from these tomcat thread it's going to initiate the HTTP GET and then it's saying starting an asynchronous request and I'm exiting but the response remains open because I'm I know that there's more stuff that needs to be done for that mano to complete and then at some point two seconds later on a reactant nettie thread we're getting back the response from the remote service we're decoding a person now we've got the result and we're going to do a dispatch back into the container so that's the deferred result if you know the way that the deferred result works is do one more dispatch into the servlet container and then we're gonna write that to the response so again this is what you would see with use of different results which we've had for a long time except now you can do that also with reactive types so let's give this a try also with a flux okay so now we got application JSON and that's a JSON array and you can see here similar output but in this case we are decoding individually all the results and we're turning that into a list and then we're dispatching back into the servlet container and then we're writing that JSON array or that list of person objects now we can also do a stream so that would be person events okay so that's SSE and we're getting the data back and you can see here how we're decoding okay so this is streaming from the server side it's getting a stream from the remote service and then that flux is being written back to the response of the client so those kinds of things you can see become possible and this here is a tomcat error which unfortunately not much I can do about because the connection went away essentially because I killed it from the client-side one more thing to show you here is making a kind of a more concatenated sort of a orchestration a slightly more advanced thing to do so I'm going to use the account repository that's the account repository and I can show you hear that this is extending the reactive crud repository for from spring beta and then I'm going to make a call to find all and I'm gonna sort them by their score I'm gonna take the first five and then I'm going to flatmap but I want to keep that sequential so I'm gonna make nested asynchronous calls and I'm gonna make one call to get the person another one to get the person hobby and then I'm going to zip the results together and return that back to the response right so we want to we want that execute it in the most efficient way possible but you can see instead of dealing with threads I'm actually declaring which depends on which and which can be concurrent like these two can be concurrent and I let it deal with the rest so let's do let's see that counts and I'm gonna leave you a link to the source code so there's a repository for this you don't need to I'll give it to you at the end of this presentation so you can see that this came back pretty quickly let's take a look at the outputs okay exiting response remains open and it's gonna make a total of I guess we have five different persons and then we're gonna make two HTTP calls for each that's ten calls and it pretty much fires all of them together and then waits for the results again you know the cost of making extra calls is a lot lower because we make those calls and then we're not holding any threads we're just waiting whenever they come back and then we deal with the results okay okay so let's talk a little bit about best practices so all of this looks nice and accessible of course there's some learning involved with using flux in mono but one way I like to think of it is kind of like the Java eight stream API if you've been through the process of taking a for loop and turning it into a stream it's sort of a similar type of thing except here we're also dealing with asynchronous non-blocking things and obviously the stack traces are not going to be as helpful but one of the common things I see is because we're so used to the you know synchronous blocking style of doing things that as we begin to experiment with this one of the things to expect is you're gonna find yourself in a place where let's say you're in the middle of you know this kind of processing chain and then you have to call something but you've got a mono so it's like you want to do a lock so you can get the data because that thing expects the data and not the mono so when you start to deal with this kind of mix of blocking and non blocking asynchronous in knots and synchronous api's it becomes very tempting to try and do these kinds of things but the thing to learn over time as you go on this journey of learning reactive and using these declarative functional style api's is that you want to defer you don't want to block but you rather you want to integrate into the processing chain so I showed you for example using flat map along the way so you got a mono and you need to do something okay you need to flat map and then then you can deal with a callback that gives you the value and then you can call the thing and that can integrate into the main processing pipeline so you're basically looking at deferring as much as possible in fact if you look to the you know kind of things we do here is we are always returning the flux or mana from the controller method if you're doing something asynchronous but you're returning not flux or Mona you're returning the actual value you probably had to block somewhere along the way and you really don't want to do it's sort of like taking a flight and when you take a flight you basically don't want to you want to stay in flight right you don't want to land because you're gonna lose time for connections and you want to get there and and I think the same analogy sort of works here you know when you start composing something see here you're getting accounts from a repository you got a flux you don't want to block for these and and then continue you want to continue to compose so I'm gonna use flat map and then that tells me okay when you have an account what do you want to do so I'm gonna use this lambda here to express what I want to do once there is an account but that account isn't gonna come until something subscribes to my flux and again the stream API is also has this kind of deferred nature so I don't think this is anything too radical here so just like with using web flex where you want to find applications to convert in full so you don't want to have too much mixing of blocking and non blocking I think the same is true in spring MVC as well you want to find kind of vertical slices controller methods or controllers word that you can convert so you're not doing partially blocking partially none blocking try to start with something where that you can convert the whole thing to to non blocking and then don't try to do things like write a bunch of blocking non blocking code and then put it behind a synchronous API because that's what you'd like to expose it's easy to go from asynchronous to synchronous right you just do a block and you're there if that's what you want to do you can do it but it's not possible to go the other way around you know once you give a synchronous API that's it you're limited with that synchronous API and whoever is using yours because you're concerned about the complexity you're exposing people consuming that API but at the same time you're giving them less choice so if they actually want to make use of this asynchronous nature you're not giving them that option so it's always better to make the API asynchronous and non blocking and then if you have to provide a synchronous layer on top but try and encourage kind of keeping that flight going instead of landing so in the end you want to compose a single request Hamlet chain deferred request handling chain once again I mean this is the example here it's all interconnected at the end of the day right first we have to get the accounts then for each account we want to make calls for a person and for a hobby then we want to zip that and the whole thing is being flattened into a single stream of maps of person and copy data so that's that's where you want to end up you want to compose that kind of single connected chain that can be subscribed to and triggered and then the whole processing continues you within a controller method especially you don't want to ever have to use block or subscribe anywhere I'm returning the flux to spring MVC and spring MVC will do it so again we're trying to defer as much as possible having to block or subscribe and then finally I'm just going to mention end-to-end testing for HTTP because this is relevant to spring MVC so we added the web test client in spring frame 5 and that's a very thin layer over the web client which means that the API is very similar the benefits are very similar all of what you saw here is a similar experience but once you get the data at the end from there you have a verification API which you will find similar to mock MVC but without the static imports it's again a functional fluent API now in spring MVC did this was built specifically for wet flux so he can test wet flux controllers wet flux endpoints but you can also be used because it is a client and that's the difference with mock MVC it actually sits as a client making HTTP calls you can use it for m2 and integration testing of any back-end it can be spring wet flux or it can be spring MVC or it can be Python it can be anything it want to test in you can do streaming scenarios quite easily as well and I did write some tests for this so I'm gonna show you that so this is what it looks like you will find that it looks a lot like using the web client but once you perform an exchange from there it's all about verifying what happened and we actually do block for the exchange to complete because in a testing scenario you don't want the test to end before the call is done typically you want to you know test the thing so we're going to wait for the result and then we can say okay what's the status what's the header however we're not blocking for the body so you still have the opportunity to express how the body should be decoded so among the options here is I can turn it into a person and that's a big advantage versus Mulkey MVC because this is an actual client that we can decode we can use things like JSON path so we can say let's verify like this or we can deal with streams so in this case you can see here that we have we're making a sse request and then we're going to get the first three of those for for the test and then we're going to use the reactor core step verifier which allows us to deal with streams of flux and mono and then to kind of verify the values individually one by one so that's that's kind of a nice thing if you if you have to test do integration testing or SSE and that's pretty much all I wanted to cover we have a few minutes left I wanted to provide a link to the source code repository so you can get that right away there is one that typo that I had to correct so I'll fix that after the presentation but if the SSE client example doesn't work it's because the URL is wrong so just bear to the back end there is an article on info queue that I wrote not long ago if you'd like to check that out on servlet and reactive stacks it kind of takes the perspective of servlets developer you know spring MVC kind of where we come from and what all of this means and also the spring framework reference has been majorly updated with regards to the web content so if you actually now me go there for a second so you'll see in the in the reference that we have that we have two different sections one for web server let and one for web reactive and if I go into say the web server late for all of the information here you will also find a link to the same in web flux and the reason why I show it here is because in order to be able to do that we had to majorly rewrite the spring MVC content to make sure it corresponds and it's comparable to the one in web blog so you can see how does it work in one how does it work in the other and of course when you do that you run into documentation that was written you know one year five years ten years ago in some cases and you want to rewrite it and so that's what ended up happening so anyway the web content has been majorly updated so please take a look keep that in mind and then if you have suggestions for improvement let us know we take that quite seriously and we make the changes right away and also the reactor documentation I would say is pretty good there isn't much on reactant ad but the reactor documentation is actually pretty good and you can learn quite a bit from that so if you want to explore reactive that's a good place to start and with that I'm just gonna point out three talks there's lots of reactive talks at good ones so by all means look at the entire schedule but I picked a few which I thought might be useful for learning if you're coming from the point of view of trying to figure out reactive and trying to understand how it relates I think these talks are something that you will probably benefit from and that's pretty much everything thank you [Applause] you
Info
Channel: SpringDeveloper
Views: 41,062
Rating: 4.9390583 out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud, reactive programming, reactive streams, webflux, webflux.fn, flux, mono
Id: IZ2SoXUiS7M
Channel Id: undefined
Length: 64min 27sec (3867 seconds)
Published: Wed Oct 03 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.