Why WebClient vs RestTemplate
We looked at RestTemplate as a way to make calls to other microservices. That's the inbuilt way of calling those APIs. Spring comes with RestTemplate and says hey this is this client which you can use for making any REST calls; it doesn't have to be microservices. But like I talked about in the previous workshop, this template is going to be deprecated soon. I don't know if it's soon; at some point in time it's going to be deprecated and there is an alternative which is called WebClient. You're not going to see a lot of usages of WebClient today, but that's, I believe, that's going to change. You'll see more and more people using WebClient. For the purposes of this workshop what I'm going to do is introduce you to WebClient so that you're ready and you have that information when you do encounter it. But once we have introduced WebClient we're going to take it out and put back RestTemplate because for today that's probably the most relevant knowledge you need to have. I get you guys prepared for the future that's coming up, right. WebClient is also a little bit more verbose than RestTemplate, but then it also has a completely different purpose.
From a single-line RestTemplate call to WebClient
So this is RestTemplate, right? This single line is making a call to the API and unmarshaling the object. Now what if I want to do this using WebClient? The way to use WebClient is to use a certain class WebClient.Builder. If you can notice here it says red because this particular class does not exist in the classpath. The reason it doesn't exist in the classpath is this is actually in the reactive programming space of the Spring Boot ecosystem. You know when you build a Spring Boot application you can build it the traditional way which is step one, step two, step three; it's sequential versus the reactive way which deals with the Flux objects and the Mono objects. We don't have to go too much into reactive now, but you need to understand that WebClient is in that space. In that path you're going to be dealing with a lot of asynchronous mechanisms of programming. So when it comes to asynchronous, the idea is let's compare it with synchronous. What's happening in this line: you're saying hey RestTemplate give me the object and you wait around till RestTemplate gives you the object. The next line, the immediate next line, you know that RestTemplate has done its job. But with asynchronous programming that's not true anymore. You have API calls which basically set things in motion and then you go on your way and do other stuff. So you basically tell WebClient go make this call and then you go do other stuff; you don't wait around for it.
Callbacks, Lambdas and asynchronous behavior
Then you might be wondering how do I get that data back? Well when you set things in motion not only do you tell it what to do you also give it a lambda and say once you're done executing whatever you're executing run this lambda for me. In that lambda you have code about what needs to happen when that is completed. So you're still not waiting around but you're still providing instructions about what needs to happen; you're just not doing it in the line below that previous call. You're basically creating a function and passing it to that asynchronous call in addition to what the work needs to be done. All right, let's replace this with a WebClient. Now first step is to get those libraries into the classpath. So if you open Spring Initializer and type web you see there's this other option here called Reactive Web. Reactive Web comes with Netty and Spring WebFlux, and then Spring WebFlux is that part of the Spring framework which has all these classes. If we had added this when we created our Spring Boot project we would have had this in the classpath by now and we could have been able to just do Alt+Enter and import the class, but we didn't add that. So the first thing we need to do is add that to the pom.xml. I'm going to open pom.xml and copy this web dependency and then change this to... I'm going to save and Maven is going to do its thing and import it. Now I'm able to have it import. You see this is coming from web reactive. WebClient.Builder is a builder; it follows the builder pattern and you use it to build a client. Anytime you need to make a call you did something similar with RestTemplate: you just created a new instance of RestTemplate. That was your 'builder'—you built a new instance and then used it in multiple calls in your application. But with this one you're going to use the Builder. Let's call it Builder WebClient.Builder. This is what gets you the builder. You create a builder and then from that builder you're going to be, every time you need to make a call, you create a new client, put in the parameters you need and then you say go. So this is kind of equivalent to creating a new RestTemplate. Not exactly, but you can think of it like that.
Making WebClient reusable: bean and autowired builder
What was that? Yes, that's the obvious next step, right. You don't want to build a new WebClient every time a request comes in. Where it is right now you're going to get a new instance every time you get a getCatalog call. So the obvious next step is to move it and make it a bean. Since you asked I'm going to do that right away, so let me move this here. public WebClient.Builder this is going to be the... all right now it's a bean and now I can use this in my resource so that I don't have to do this here. How do I use this in the resource? I create an autowired property and this is it. I have an instance of WebClient.Builder that I can reuse no matter how many controllers I have, no matter how many APIs I'm calling. I can just use that same builder. Now this is the tricky part here. So this particular line is going to be replaced by all the steps you need to do to make that call using WebClient.Builder. It's a little bit more elaborate than the single line that you're seeing here. So you basically do WebClient.Builder.build, basically creating a new instance of a client every time you need to make a call. Next you specify the method that you need to call: is it a GET method or a PUT or a POST? Here we're doing a GET, right: .get. When you're doing a POST you do .post here. And then on top of it URI: what's the URL you need to call? Basically going to copy this and then I do a .retrieve. I'm basically saying okay now that I've given you what the method is and what the URL is go do it, fetch me the data. And then I do a bodyToMono. If you don't know what Mono is you're probably going to be confused by this step; let me explain in a bit. And then I pass in the class and then I do a .block. This whole thing is going to give me an instance of Movie.
bodyToMono, Mono semantics and blocking in synchronous flows
They deprecated the old one and they're asking us to use this instead. Now I can introduce a local variable called movie and I have the movie information here. Let's break this down: what are we doing here? WebClient.Builder.build is using a builder pattern and giving you a client. Next you're using this chaining mechanism in order to build on top of what you already have. .get says I'm going to do a GET; this changes depending on the method. The URI is the URL that you need to access. In the case of a GET it's basically the same as the first argument in the RestTemplate like where do you need the request to be made. Then you say retrieve: it's like, oh go do the fetch. And then bodyToMono is basically saying whatever body you get back, convert it into an instance of this Movie class. So this is equivalent to the second argument in RestTemplate. But what is Mono? BodyToMono, anybody knows what Mono is? It's a reactive way of saying you are getting an object back but not right away; you're going to get it sometime in the future. So a Mono is kind of like a promise that this thing is eventually going to get you what you want. That's how you do asynchronous. Don't worry too much about it. If this is too confusing we can probably do another workshop on asynchronous if you guys are interested. But for now just think of it as you're getting back an asynchronous object. It's not quite what you want but it is in the future going to give you what you want. Think of it as an empty page where you know the message is going to show up over there but you're basically given a container, an empty container, and then told that at some point somebody's going to put something in there. So you have this empty container to hold on to and then you can do stuff when something fills in. That's how we do asynchronous. You can have that container; you say okay I'm not going to wait around till this thing happens, I'm going to do something else and then I'm going to keep checking this empty container. Well not even keep checking the empty container; you'll say hey container, once somebody puts something in there let me know and then you can take action on that. Now here's the thing though: this method, this API call getCatalog, is returning a list of movies. You know that by the time this last line is executed in this method you better have a list of movies. So no matter how you do this, asynchronous or synchronous, you have to wait around till you get that list of movies, and until you get that you cannot get out of this method. There are alternatives to this. If you do the whole asynchronous route you can have this method itself return a Mono. You're basically passing that empty container to Spring and saying hey I've done my job; this is what you need to return to whoever calls this API. Here's the empty container: I'm handing it to you. Once somebody puts something in there return it to the user who made this API call. You can technically do that, but we're not doing that now. We are telling Spring we're going to give you the thing; we're not giving you a container. We're giving you a list of catalog items. So guess what: we have to wait around for this Mono to return something back, which is this line: it's the .block. We're blocking execution till that Mono is fulfilled. Once we get that back the result of the block is basically that Mono container saying hey somebody put this thing in here. I know you're waiting around for me; this is what somebody put in my container, and it's going to give you what that is: it's a Movie object because we've said we want this to be of type Movie. All right, so with this we get the movie back. So we're using asynchronous programming constructs; we're using asynchronous programming classes to do synchronous programming. Once you get the movie instance I'm basically mapping it to a CatalogItem where I take the movie data out—the name and the description or whatever—and then put it into a CatalogItem. This should work exactly like it did before. Let's quickly test this out. Once we make sure this works I'm going to remove this code; we're going to go back to RestTemplate. Like I said we're going to continue the rest of this workshop using RestTemplate. There you go, same thing, nothing changes because we're still doing the exact same thing and blocking around for that asynchronous operation. Okay, now what I'm going to do is comment this out and then uncomment this so that we're back to the RestTemplate.
End of demo
back to the rest template V