 Why are there four lights with no labels or stickers? None. It's going to be fine. Just push things until it works. Oh, so much better. I can see. Do you ever go to the theater and see movies? Are the lights on? Makes no sense. All right, my friends, very good. Well, thank you so much for coming. We have a lot to go through, not actually too much, not as much as I usually do, so that's good. But we do have a lot to go through, and with that in mind, I encourage you to sort of note this repository on the get up side there, the side there. Note that get up repository for your own reference, for your own notification for later. I'm not expecting you to remember everything that we do tonight. I just want you to remember what's possible, and you can reinforce what you've understood with the code later on for your own perusal and your own edification. So grab that there, okay? I'm also very happy to answer questions. I'm happy to engage if you are online, if you have comments, feedback, ideas, questions, whatever. Don't hesitate to reach me. How many of you, by show of hands, are on Twitter? Right on, good stuff, that's marginally better than it was last time though. So I need this to improve, so when I come back to the third time, all of you are on Twitter. Find me on Twitter, the rest of you, get on Twitter. Right? It's a great place to be, it's the new IRC, it's where all the developers that power the open source that drives your businesses are. And if you have questions, comments, whatever, they're all there willing and happy to engage. It's a vibrant open source community, right? So email. What about email? Anybody? Email. Anybody. Okay, well that's also an option. It's not nearly as communal and friendly and reusable and shareable, but it's an option. So find me there if you'd like. Actually, does anybody here need a bio break or anything before I get too far in the way? It just occurred to me, we've got like an hour and a half, right? How long do we have until we're, I have to stop? Yeah, we have about nine. Nine? One and 20 minutes. So I remember last time that they were like, we had to get out. Yes. Last time we left at about nine and a half, almost ten and a half. Yeah. Does anybody need to like open source some stuff in the bathroom? Anything like that? Josh, just tell me and I lock the doors behind. Okay, good. Okay, good, good, good. Okay, well in that case, are we okay? We're okay. Anybody? That's good going. I just want to make sure on the same page that was a great talk, but we have an interesting place to stop right now. So okay, there's that. If you have questions, find me online. I'm happy to answer questions. A little bit about me. My name is Josh Long. It's very nice to be here. I'm so happy to be here before you for the second time. It wasn't more than a year ago, right? It's been about a year. Wow, time flies when you're flying. So there's that. I'm happy to report that I'm finally done. I'm finally done with that book. We'll get to that book in a second. I work at Pivotal as a spring developer advocate. My goal, what I try to do is to help the community, to help customers, to help organizations build better software. That dovetails very nicely with what I do as a Java champion. And I spend my time in front of organizations like yourselves, in front of community members and customers and so on. Talking about how to build better software in terms of Java, in terms of spring. As part of that, I work on code. I work on a lot of different spring projects. I'm very, very proud of my distinguished, highly lauded, highly acclaimed, very, very, very infamous record of contributions to the spring projects. I am now the number one, the number one, top ranked, most visible, most highly acclaimed, most recognized contributor of bugs. But still number one, number one, number one, number one in all the projects, number one, more bugs per commit. I'm not saying I'm proud. I'm just saying that's better than nothing, right? So there's that. And I also, you know, I've done training videos. I wrapped up filming of this spring boot micro, building microservices with spring boot live lessons, training video with my friend, the one, the only, the amazing, the inimitable Phil Webb. That was fun. And then I just recently, like a week ago, finished up this infernal book I've been working on for the last two years. I was talking about it here as being so close to done, last time I was here, and now it's actually done. That book is called Cloud Native Java. It's all about how to build applications that survive and thrive in the cloud. And it's in terms of spring boot and spring cloud and cloud friendly, of course. And this is particularly salient, given our proximity. I want to address something very important. And I can see it in your eyes. Even now, I can see the curiosity welling up in your eyes. You're all wondering, what is that bird? Anybody who knows anything about O'Reilly books knows that it doesn't matter what's in the book. Nobody cares. It's just the animal on the cover. That's what makes or breaks the book. And this is even more a proposal given our proximity. That bird is a blue-eared kingfisher. It's a bird that is indigenous to the Indonesian Java islands. In English, we would also say native to the Java islands. And birds, birds fly often through the clouds. So that's a bird that is native to Java that flies through the clouds. It's a bird native Java bird. It's a bird that never mind. Never mind. It'll come. So there's that. And I work at Pivotal. And we've got a lot of great open source software that we care about very much at Pivotal. Some of which you see represented this amazing slide with this great art by my team member, Ashley McNamara. These are like sort of, if the Simpsons designed the logos for some of the projects, I think they're really great. Well done, Ashley. She's awesome. These are some of the projects. How many of you know Spring? Just making sure you're all in the right room. Okay, good. Cloud Foundry. You know Cloud Foundry, right? Good, good, good. So there's that. And we have other projects. We have Apache Tomcat. How many of you know Apache Tomcat? Apache Tomcat. Apache Tomcat. Okay, well there's that. And RabbitomQ and all sorts of good stuff. And we care about the open source, but let's be very clear. It's not the reason I'm here. It's not what motivates us. It's not what drives us to spring out of bed, right? What we care about more than anything else at the end of the day is helping customers and community members deliver software faster. And we've seen that as part of that sort of drive, a lot of organizations have moved to this microservices architecture because it allows organizations to decompose large applications into smaller batches, which then allows smaller teams. And this is a great architecture, but there are some things that arise that become obvious when you move to this architecture. There's complexity, first of all, implied in distribution, right? Implied by building a distributed system. And we've talked, at length last time, we talked about how to address some of those complexities with Spring Cloud. One other complexity that sort of becomes obvious only at scale when you start to have enough data being moved around the network across network boundaries is... How do I handle all that input and output? How do I manage the transit of that data, the communication of that data from one service to another efficiently? The traditional approach to building services doesn't really scale, right? It doesn't really scale. Before I get too far down the road, let me pause here. I forgot to do one thing more important than anything else except for the book cover animal. Okay. Okay, when I say open source, you smile and say open source. Ready? One, two, three, open source! Very good. Good, good stuff. Thank you so much. I almost forgot about that. Can't forget about that. So the question that comes is how do we move data across the network efficiently? How do we manage a large amount of input and output? And that's where a lot of our systems start to bottleneck these days. And the reason they bottleneck is because the programming stacks that we use today are not optimized for input and output, right? They're optimized for ease of consumption. But when it comes to input and output, we do things in a traditionally sort of synchronous way. And this doesn't translate very well at scale because there's a lot of wait time, a lot of idle time in traditional input and output tasks. Time where services could be doing other things but instead are blocked waiting for more input and output. Now, this isn't a particularly new insight, right? Operating systems by default at most tiers do asynchronous input and output. It's only at the higher levels in our stack that we then try and force lower level operating system input and output to be synchronous. If you use the JDK, if you look at JDK's input and output streams, their synchronous lies on top of asynchronous things at the lowest levels. Network IO in your average operating system is by default asynchronous. So the question then becomes how do we get around that? How do we write our code to be able to support this? First of all, we need support in the JDK. Well, good news we have that, right? JDK 1.4, which is now 15 years old, right? JDK 1.4 has Java NIO. It has support for channels. And it gives us the ability to talk about input and output asynchronously. It's not easy, let's be clear, but it's there. It's an option, right? And so if it's been there for so long, then why aren't we all using that? And the reason we're not all using that is because input and output is not by itself enough, is it? When was the last time you wrote a web service just using channels, right? Or did database access using just input and output streams? No drivers, no clients, nothing. No ORMs, nothing, right? So we need higher level support. Now, one part of this solution is we need to be able to build APIs that work with input and output that is asynchronous. And we need to be able to preserve that asynchronousness at higher levels. And we're almost there, I think. If you look at what the JDK offers, I'd say it's three quarters of the way there. To being able to support what we need. To be able to support a type that describes this sort of kind of data. If you want to describe a method that returns a single value in the JDK, in Java, for example, you can say I have a method called foo and it returns a string. So you say string foo, right? What if I want to return multiple values? So I say collection of string foo. What if I want to return multiple values? Sorry, what if I want to return a single value but asynchronously? It's not here now, but it may be in a minute or an hour. That's pretty easy, right? Completable future of string. Completable future angle bracket string. So that's three out of four. The fourth one is what if I have multiple values that may be there but they're not here right now, they'll come eventually. And a potentially unlimited amount of values. And we don't have a nice way to describe this in the JDK. Stream isn't quite right. Stream actually has semantics that are not quite what we're looking for here, for asynchronous, right? Stream is saying that it's potentially unlimited, but it's not really asynchronous. So we've looked for, you know, the Java community at large has looked for the last seven years for an answer for this, right? And there have been a lot of great things, a lot of great sort of technologies that have come in the pursuit of this thing. That work isn't unique to the JVM at all. In fact, I'd argue that some of the really interesting work started in the .NET community. The reactive extensions for .NET from Microsoft Research was what gave way to what we now talk about as RxJava at Netflix, right? So RxJava is, I think, the sort of 800-pound gorilla in the space. It's the thing that everybody knows about. RxJava one is an API. It's a library that you can use to talk about this missing thing, this missing type of value, a potentially unlimited asynchronous set of values. That's one option. ACCA from Typesafe, now they're called LightBend. They have another way to solve this problem. Vertex, which is from Red Hat these days. They have another way to solve this problem. And of course at Pivotal, we have a technology called Reactor. And Reactor also had another way to solve this problem. So we have at least four different players. I may be missing a few. And there's no standard. There's no convergence. So about three years ago, these different players, among others, converged and they extracted and identified the missing piece. They extracted the very essence of what we're trying to do here into a separate sort of de-facto standard called the Reactive Streams Initiative. The Reactive Streams Initiative describes four types, four interfaces, four deceptively simple interfaces. And that, I think, by the way, is almost a bit dangerous. Because it makes it seem like all you need to do to provide a reactive implementation is to implement these interfaces. And the truth is that it couldn't be further from the truth, right? If you want to build your own reactive implementation, your own reactive implementation that implements these types, you'll spend the better part of a week getting there and you'll still fail. So it's a good way to kill a week and not get any results. Don't do that, right? Instead, use one of these tried and true implementations. The test kits for this specification is exhaustive and it's crazy. It's really crazy. There's just so much that has to go into making this work. But once you have an implementation that actually works, it's amazing, right? So we have these different implementations. Now they all support or at least can inter-operate with these types. But these types, by the way, are not by themselves enough. If I have a collection of strings, don't I want to do more things with it than just hold the values? I want to be able to filter the values. I want to be able to transform the values. I want to be able to operate on the values. The base types in the reactive streams initiative are very simple. There's four types. There's publisher. Publisher says I'm going to produce a value. It actually says I will take a subscriber and create a subscription and I will notify that subscriber of the values. There is the subscriber itself. That's the thing that the publisher provides values to, which results in a subscription. And then there's something called a processor, which is both a publisher and a subscriber. Four interfaces, very simple. Publisher, subscriber, processor, and subscription. These are not in themselves enough for us to do any kind of higher order sort of management of the data in these types, right? There's not even really an explicit description of a collection or anything like that, right? We have this idea of a publisher, but all that publisher knows is that something is going to subscribe to it. That's it. It's not enough for us to be able to talk about data. It only describes life cycle. The fact that something will subscribe to something later, right? So we're still missing something. We need something that we can use to be able to manipulate sets of data and this is where these different implementations can come into play, where they can provide a lot of value. The Reactive Project builds on the sort of Reactive Streams Initiative and it builds on those interfaces. Other implementations like ACCA don't build on the interfaces, but they provide the ability to get a reference to those interfaces, right? So they have their own types and then you can call a method and it'll give you a Reactive Streams Initiative compliant pointer to what they're doing in their native types. Either way you can interoperate, right? So that benefit is that if you write code using Reactive Streams Initiative you can now talk to these different ecosystems and share data without ever blocking. So we need this higher level thing. We need this higher level thing like Reactor. Reactor provides higher level operators on top of the basic Reactive Streams Initiative types. Reactive Stream provides operators, let me do filtering and transformations and do flat map and filtering and all that kind of stuff, right? The kind of things you would expect to do if you had a collection of data, a JDK collection of data. The Reactive Project provides two specializations of the Reactive Streams publisher. These are documentational. They imply certain characteristics about the data. Their implementation is different, of course. There's nuance to their implementation as well, but their biggest value is that they tell the client of those APIs what to expect. There's a mono. A mono is a publisher that produces one or zero values, right? It's a publisher that just returns one or zero values. Then we have a flux. Flux is a publisher that produces zero to N values, a potentially unlimited amount of values. These are, as I say, they're useful as a sort of documentation. If you're displaying a user interface and the method that you're going to call returns a mono, then you know you should probably display one text field. If you have a flux, then you know you should probably display a table or a grid or something. That's the point. They're still publishers, both of them implement publisher, and you can pass them around as publisher, but it's useful to understand what they imply. Now, with that in mind, with that backdrop, we're going to use Project Reactor, but this is, I think, not still, this is still not enough, is it? Can we build a web API with that? Can we do database access with that? Can we do security? Can we do all the sort of things that we do in traditional sort of typical everyday apps with just that? Of course not, right? If that were enough, then we would have all been building this stuff six years ago when the first of these options sort of emerged. For this to be truly effective, it needs to be integrated at every stack, every level of the stack. And if it's not, then there's no point. The last thing you want is to try and go reactive and then have to block at some higher level. So that's what the sort of future of what we're going to talk about here today holds for us, is the opportunity to have an end-to-end experience that supports this reactivity. And it begins in Spring 5. Spring 5 builds on Reactor. We're going to ship Spring in the summer. So yes, Spring will come in the summer. That's cool. It's that good a framework. So Spring 5 will ship in the summer. It provides a web runtime that builds on top of Project Reactor. It's called Spring Web Flux. This stands separate from Spring MVC. Your existing traditional sort of Spring MVC code still works, but there's a separate web runtime. It'll feel very familiar to what you're used to if you've used Spring MVC, but there are some concessions to the fact that what we're trying to do is inherently asynchronous and reactive. And this is, as I say, just a foundation. Spring at its best serves as a foundational layer for the other projects in the Spring ecosystem. So what you'll see today is we're going to also demonstrate Spring data and its reactive support. You'll see that we're going to talk about Spring security and its reactive support. And this is just the beginning. All of this will sort of bubble up into Spring Boot, the first release of which is Spring Boot 2 due in December. And then that'll percolate and become the baseline for the next release of Spring Cloud due in early 2018. So the real power here is that it's end-to-end. We can do reactivity from the request all the way down and then back again. If you end up blocking somewhere, then you lose that benefit. You may as well just not bother, right? Okay, so with that in mind, here we go. Let's build an application or two, huh? So, oh, cold chair. Okay, I don't even know what I should be drinking. So those are my slides. I hope you like those. Alrighty. So what we're going to do today is we're going to build a new application here at my absolute second favorite place on the internet. My first favorite place on the internet, of course, is production. I love production. You should love production. You should go as early and often as possible. Bring the kids. Bring the family. The weather is amazing this time of year. It's the happiest place on earth. I love production and so should you. But if you're not already in production, then you begin your journey here. It's start.spring.tolayo. If you want for inspiration in the early morning before a cup of tea or coffee, start.spring.tolayo. If your children are restless and can't sleep, start.spring.tolayo. And if you suffer from indigestion after a long night of alcohol abuse and PHP, start.spring.tolayo. So we're going to build a new application today, and we're going to take advantage of spring boot 2.0. This is, as I say, a milestone. It's early days yet, but it's there, and we can try it out. And we're going to build an application. And what I want to do is I'm going to build an application to manage a hypothetical service that manages, oh, I don't know, movies. Imagine in the far-flung future that we had some sort of service on the internet by which we could access movies. Another word for which is, of course, Flix. We could call this hypothetical service Netflix. And we're going to need a few things, right? We're going to need a service to manage that, and then we're going to build a client later on. So we can build our service. We're going to call this the Flix Flux service, or you can shorten that as FFS or for Flux sake. Okay, so Flix, for Flix Flux service. And we're going to take advantage of the reactive web support, right? This is different from the web support. We're going to use a reactive web support. We're going to use Lombok, the Java annotation, the compile-time annotation processor. And then we're going to choose a data access technology. And there's a lot of good options here. And I encourage you to sort of peruse this list at your own leisure. I'm going to use the reactive, I'm going to use one of these reactive implementations. You'll see that we've got reactive MongoDB, reactive Cassandra, and reactive Redis. One thing you don't see here is reactive JPA. You don't see reactive JDBC. And there's a reason for that, right? There's no reactive JPA and no reactive JDBC because fundamentally those are blocking APIs. There is no JDBC that is reactive. If you want to use reactive programming and then you use JDBC, at some point you're going to block. I've heard encouraging discussions last year at Java One, Oracle Open World slash Java One. Oracle talked in hypothetical terms about having a reactive JDBC implementation. That was in 2016. And I have every confidence, I have every confidence knowing Oracle as I do, knowing how hard they work at making it bad for users, that they'll get this done in the next 10 years. Maybe 10. I know they can do this. Maybe. So I'm hopeful, you know? 10 years, 10 more years. That's hypothetical, but it's promising that they've at least even acknowledged it, right? By the time Oracle gets around to talking about a problem that users are having, it's been solved. So that means we're in a good place, right? In the meantime, spring data doesn't provide a reactive facade on top of JDBC or JPA. That would make no sense, right? We don't want to provide you a more complicated API that's just as slow as the old one. That would be the worst of both worlds. So instead, we're going to use a truly reactive implementation. Spring data itself already has initial support for reactive APIs. There's reactive couch base. You don't see that listed here, because for the moment there is no auto-configuration for that. But it's coming, right? The spring data team has a super set of reactive implementations, then the spring boot auto-configuration in spring boot 2.0. But of course, by the time we get to spring boot 2.0 in December, all of the spring data projects that support reactivity will be well-represented in spring boot itself. So we have a lot of options here. We can use reactive Redis. We can use reactive Cassandra. Or we can use reactive MongoDB. Now, they're all good choices. I'm going to use reactive MongoDB because when you want to lose your data and you want to lose it reactively, there's no better choice than reactive MongoDB. So there's that. Now, anybody who knows about start.spring.io knows there's a lot of great choices here. And I encourage you to cruise this list at your own leisure later on. There's a lot of great check boxes that I haven't selected. And you'll see that these are going to be better integrated in the reactive ecosystem. But for now, there's a lot of great choices. I encourage you to cruise this list and take advantage of all the options. We do have two drop-down menus here. And thankfully, this drop-down menu doesn't even really make sense anymore. If you're using the reactive spring 5 support, there is no ability to use 1.6 and 1.7. Spring 5 has a foundation of Java 8. Hooray! So that's awesome. So this drop-down menu, I think they're all going to fix that because it has to be limited to just that one version. And then there's this other drop-down. Both of these drop-downs are what I like to call non-choices. They're choices that you could make, but that you shouldn't. They're non-choices. They're choices in the same way that stripping naked and running in traffic is a choice. You could, but don't. Non-choices. And that's not just Indian bread, my friends. We have here the choice of packaging. A lot of people get confused about this. They don't know when and where to choose which. So I'm going to do my double-headed best here and now to explain. If by some freak fluke of physics, some terrible tragedy of time-space, you find yourself stuck in the distant, distant, distant past, far, far, far beyond modern help, then choose dot war. But if you're here with me in 2017, then choose dot jar. This is a big part of my overarching and guiding personal philosophy of make jar, not war. Now, it is interesting to note, though, that all this reactive stuff that we're going to talk about today, it works on any servlet 3.1 container if you want it to in degraded performance, but it will work. We can adapt to that runtime. And so you could actually deploy dot war into a web sphere. I wouldn't, I mean, unless you're like very drunk. You could, though. It's just an option. I'm just saying you could. It's like having a Ferrari on top of an elephant. So there we go. We're going to hit generate. We've got a new project here and I'm going to open this up in my ID and it doesn't really matter what ID, anybody knows, knows that I don't care at all. I'm using IntelliJ. How many of you using IntelliJ? I'm just curious. Write on good stuff. Hot sauce. Well done. What about eclipse? Eclipse. Good stuff. Write on. Well done. What about net beans? Write on. Good stuff as well. What about E-Max? Are you here, sir? Did you come back? I don't know if he came back. Every time I talk to an audience, it doesn't matter which city, country, or continent, every single time there's the same guy, same object identity, same human. I say, who uses E-Max? I do. And then he leaves. Ah, troll. So, okay. Let's build an application. I'm going to build an application to a series of type movie. I'm going to make this a spring data document, a spring data MongoDB document. I'm going to have a primary key here, private string ID, private... What else do we need? We need private string title. Title. There we are. Good. This is going to be an ID column. Very good. Now, this is the essence of what I want to do, but of course I need getters and setters and constructor and all that stuff, so I'll just use the appropriate annotations here at all.org's constructor. There we are. Then I'll create a repository to be able to persist and manipulate and manage instances of this entity. So I'll create a movie repository, right? Now, again, this should feel altogether very familiar if you've ever used spring data, but it's just a little different. We're going to use a reactive Mongo repository, a reactive Mongo repository to manage instances of movies whose primary key is of type string. And this works very similar to what you've seen before, but again, some slight concessions to the fact that what we're doing is reactive. We return values for the insert method, the find all methods, et cetera. They return publishers, don't they? This returns a publisher of type flux. By the way, there's the definition of the publisher. And this returns a publisher of type mono, right? So you get both of those. Same thing here for the sorting and paging, right? You get all that kind of stuff, everything you expect except that now it takes, as its inputs in some case, a publisher, and it returns a more specific flux or a mono. And by the way, this is our general advice to you as well, to do this in your own APIs. Take publishers in, return specific fluxes or monos back. So for return values, be specific for inputs, be forgiving, right? Take anything you can. So there we go. We've got our reactive MongoDB repository, and now what I want to do is I want to save some records into the database so that we have something to work with. So I'm going to create a new command line runner, and this is just an object that Spring Boot will call back when the application starts up. It's a great place to do any kind of initialization, any kind of back office ETL or messaging or batch or anything that sets up or initializes the state of the application. In this case, it's an enviable place for us to write some sample records, some sample movies to the database. So I'm going to create a command line runner that injects the constructor there and mute that, thank you. And I'm going to inject the movie repository. I'm going to save some records. So what do we need to do here? We need to create some records. So let's create some titles here together. This is a good chance for audience participation. Let's imagine some names on the theme of reactive programming. Anything that has to do with reactive programming, think about fluxes and monos, anything you can imagine being relevant here. So I'll get us started with my favorite sort of reactive programming movie title, Silence of the Lambdas. Yeah? Okay. What about, what's the movie that? The reactive runner. The, yeah. Do you have a runner? Yes. What about the movie with the flux capacitor in it? Which movie was that? Back to the future. Anybody here like anime? There's an anime that has the word flux in it. In the title. Aeon Flux, yeah. Very good. What about that sci-fi horror movie? The Enter the Monovoid. Right? Fluxman versus Monoman. Meet the fluxers. The Fluxinator. The Fluxinator 2. Now he's pissed. Anybody here speak Spanish? Alguien que habla español? Yes. In Spanish, mono means monkey. So there's that great movie, of course, 12 monos. Or Enter. No, sorry. E2, mama. E2, mono, tambien. There we are. So there's a few reactive movie titles. And what I want to do now is I want to turn them into movies. Right? I've got titles. So I've got a title. Let's turn it into a movie. New movie. Okay? And the movie is going to take a UUID. Two string passing in the title. And then what? I want to save it, right? So I want to turn that movie. I suppose it's the other way around, isn't it? Map. Okay. And then what do I have here? I have a movie that I want to save. And I'm going to say movie repository.save. Passing in the movie. And that can be a method reference. That would be the first thing. Now, I would like this to run. Remember, this is reactive. It's asynchronous. So nothing is run until a terminal condition is met. And this way it's very similar to the Java 8 streams API. Nothing is going to happen right now if I just run this code. I have to actually subscribe to it. I have to say I want this to begin, to begin processing. So this is certainly one thing. I can subscribe a few different ways. I can say flux.subscribe. And it's going to ask for a consumer. It's going to, oh no, sorry, I should have done this. Flat map. Flat map. Map. What have we done? Hold on. So now what I want to do is I want to subscribe to those movies. And I could just, I could just print line. And what's going to happen here is that each time there's a value that is emitted from this publisher, the publisher that gets returned from this, it's going to print out the values, right? But this is going to give us a, I think, deceptive picture of what's actually happening right now, right? You can see that it's printing out what has just been written. But is that actually the state of the database? And I'm using, with Mongo, I use the term database with big ironic air quotes. Is that actually the state of the database right now? You know, the expression a broken clock strikes true twice a day? So a broken clock is valid at least twice a day. Even if it doesn't move, it's the right time twice. So even Mongo will save the data eventually, enough times, maybe twice a day. So we can't take for granted that that database doesn't already have data in it. So what I want to do is I want to, first of all, I want to delete everything in the database before we run this code. And I want this to happen before we write all that other data. So I could say block, because remember, the delete all is going to return a mono, a publisher, and I could say block, but that's a pretty awful thing to do, isn't it? I've got this nice reactive API, and then I go in and do that. I showed that to my girlfriend, and she looked at me so disappointed. So, so disappointed. You're not very smart, are you? She said. She might have been right. So that's not an option. We don't want to do that. What I want to do is I want to say after this delete all has finished, I want to do something. Well, remember, this isn't going to produce a value. It's going to return a publisher, but it's never going to emit a value. It's never going to say, I've got a value for you, right? So it'll be done. It'll terminate, but it'll never actually emit any values. So we're not interested in executing in the do next callback. There's a callback that the subscriber has called on next. We're not interested in getting notified of a new value. Instead, we're interested in being notified of termination. And so we could say, subscribe. And there's an overrided version of the subscribe method that takes a consumer for the values that might be emitted, a consumer for the exception, and then a runnable for the completion. That's one option. Another is to then just give it a publisher to say, then, once you're done, do the following or evaluate the following. I'm going to say, then, many, passing in that. And that cleans up the code, I think, a fair bit. And so we still need to subscribe to that system that out print line. There we are. So now, let's run this again. There we are. So now it's going to delete everything and then give us the results. So we've demonstrated here a dependency. We've got one call that has to happen before the other. This is a dependent value. The code, by the way, it's easy enough to understand. It's easy enough to reason about. Behind the scenes, it doesn't really matter whether this is happening asynchronously, if this is actually happening in different threads, or if it's happening synchronously. We can change the scheduler. That's a matter of configuration. We don't have to worry about that in our code. As long as we know which method is to call when, we'll get the right result. It will execute as we expect it to. That's nice, because we're not dealing with multi-threading here. We're just dealing with APIs. Imperative looking APIs that can, as a matter of configuration, be asynchronous. So now we've got some data. And I suppose what I want to do is I want to build a REST API. I want to build a service. If I write data to the database, but I can't read it from an API, it's not really much of a service, is it? So let's build a service. I'm going to call this the Movie Service. And the service, it'll just support a few endpoints here, a few methods. Let's see. We want to have an endpoint that returns a collection of all the movies. We'll just call that. We'll satisfy that definition in a minute. We want to have another endpoint that returns just a specific movie, so a mono of movie. I'm going to say that it takes an ID, so string movie ID. And I would like to have a third endpoint that returns all of the people who are watching, it returns events about all of the movies that are being watched. So imagine if I could log into that other service that sounds kind of like Netflix. Imagine if I could look at the logs and stream all of the events, all of the people that are watching different movies, like the firehose of their videos. I would basically be streaming all of the streaming, right? Or in a way, I'd be crossing the stream. I could do that, right? But we don't actually have a bazillion users logged into our service right now. Not yet. This is going to be big, but not today, right? So we're going to use a little bit of imagination and just synthesize that kind of data. So we're going to create a new endpoint that returns events related to movie watches, right? So I'm going to create an object to store that data called the movie event. And this is going to just be a simple pojo that will wrap the movie and the date, right? There's our date. So there's that. And it needs a new argument constructor and an all-argument constructor. No, all-arg constructor. And it's going to return the movie events for a given movie. So a flux of movie event events for a string of movie ID. Now, these first two, I think, are pretty straightforward. We can implement this one pretty quickly, right? So we say movie repository. And we just inject that into the constructor and we're off to the races. So the first two, movie repository dot find by ID. Voila, not bad, huh? The second one, same thing, movie repository dot find all. There we go. This last one is going to require a little bit of imagination, right? What we're going to do is we're going to say I want to create a flux that produces a new value every second, right? And this is where the fact, this is where it's nice that there is actually a scheduler behind the scenes here, right? So we're going to create, we're going to use some of the operators that come with the Reactor API. It's going to give me a flux dot interval, duration of seconds, and it's going to give me a new value. It's going to give me a flux that produces a value every second. So even if I wanted to, you know, go through the values as fast as I wanted to, I could only take them at a second at a time. There's a scheduler there, right? So I want to do that, and then I want to take, I want to create another flux that returns movie events, and I'll say flux dot from stream, and I'll use a stream dot generate method, and this is just going to return the movie event for a given movie. So let's say for now that we have a pointer to the movie that we're trying to look at. We don't yet, but we'll come back to this, right? So I want to say generate a new movie event, passing in the movie, and generate a new date, okay? So there's two fluxes. Now what I want to do is I want to zip them together. You know, like a zipper? The zipper locks on one side, and then the other side locks, and then the other side locks, and then they lock. And they move in lock step. One links up next to the other one. So I'm going to use that kind of metaphor here. I'm going to zip these two different fluxes. I'm going to take a value from the flux on the left, and I'm going to take a value from the flux on the right. But I can't go any faster than the slowest flux, right? They move one at a time. So I can only take one value, then I must wait for the other value. The result is that I'm going to get, if I zip these different fluxes together, like that, I get a composite flux. I get a flux that produces an object of type tuple, whose values have typed long or movie event. Well, I don't really care about the timing. I don't care about the long, the interval. But I do want the effect of scheduling it to last every one second, right? Forever. It's going to move in lock step, generating a new value every second until the computer runs out of electricity, basically, right? Until the heat death in the universe, or at least in this program. So we're going to say that we want that, but we don't care about the, you know, our contract is that we're going to return a flux of movie events. So we're going to say flat map tuple 2, get T2, right? And that, do I want that? Map. There we are. So there we are. That's our code that does what we want. But we still don't have this movie. So again, this is where that dependent call becomes very useful. So we're going to say, find the movie ID, return that. We're going to get a movie, and that's going to give us a mono. And what I want to do is then call the then method. Then gets executed after it's done executing, after all the values have been emitted from the previous publisher, right? Well, in this case, I'm going to execute and turn whatever I get as a publisher into a collection of fluxes. So I'm going to say then many, and then put this in there together, right? So, sorry, flat map many. There you go. I'm going to take the mono, which produces one value, and I'm going to use that to return multiple values, like so. Okay? So there we go. We've got a flux that produces a new value every second. Another flux that moves and locks up with that. Oh, well, whatever. And we can see that in action. So now we've got a basic service. We need to build an API, right? This is what we're all building up to. So we're going to build an API. And here we can use the traditional sort of spring MVC style rest controller if we want. So act rest controller, movie rest controller. And we create a bunch of endpoints that look, I think, all together very familiar. So public flux of movie, all, right? There's this. We can create another endpoint that returns a mono of movie by ID, string ID, and create another endpoint that just returns a flux of movie events. And I think this should look very familiar, right? So we're going to do just a little bit of delegation here. We're not going to actually write all this code again, because we've just done it. So we're going to use the service here, private final movie, sorry, movie service, inject it there. And we just return the data as we expect. So for this one, we say movie service dot by ID, movie ID. We're going to map this to movies, movie ID, specifying a path variable for the movie ID. Very, very traditional sort of thing. Here we say movie service dot events passing in the movie ID, path variable string movie ID, movies, movie ID events. Now this, we're going to come back to this, but something is kind of wrong about this one. Something isn't right for this one. We're going to come back to that in a second. And then finally for this one, we're just going to return the movies. All right. So there we go. There's our different endpoints. These last two are fairly straightforward. They both, you know, this one may return a large amount of data, but it will eventually terminate, right? We only have so many movies that we can return. We know, however, that this event stream is going to produce values forever. It's going to produce a new value every second for the rest of time as long as there are seconds to produce values in. And so if we are using a traditional sort of request response centric web framework and a client that's going to talk to this, and we send back the data as JSON or XML, most clients, when they see that content type application-json or application-xml, they assume that they can wait for the end of the document and then they can start parsing it and trying to load it into memory into a buffer that they can then create a document out of, an object representation, not just Java, any language, right? That's because that MIME type tells them that they can expect to do that. Application JSON refers to a document. What we're trying to do is to return something that will never end. So application JSON isn't really the appropriate MIME type here, is it? What we want is to send values down to the client, to push values to the client endlessly. And we can use a couple of different protocols here. There's a couple of different protocols. There's web sockets. Web sockets is one way to send values to the client, to push values to the client. That's an option. Another is to use service end event heartbeat streams or service end event streams rather, right? Service end event streams are, it's a protocol. It describes how to do data framing, right? If you've ever written a low-level networking client, then you know that one of the things that's important is to learn how to do message framing, how to limit when a record is done being sent to the client, right? All protocols have this concept of framing. So service end event is a service side push mechanism, but it has an explicit concept of framing. And it's a very simple mechanism. It's just a new line, and then the word data, colon, and then the JSON string, and then a new line, right? So we want to use that. And if you've ever used the Histrix dashboard, how many of you have used Histrix? Well, the Histrix dashboard that you can use to monitor your circuit breaker, it emits a heartbeat event stream that you can use to follow the state of that circuit breaker. And it goes on forever, never, never, right? So I'm going to use that protocol. I'm going to use the media stream. So I'm going to say value equals this, produces equals media type dot, oops, wrong one, text event stream value. It's text for such event stream. And there we are. There's our first implementation, our first crack at building a web API. Okay. Let's see. So curl, HTTP, local host, 8080 forward slash movies. Oops, a little dense, isn't it? There it is. All right. And we can use one of these IDs here. Grab that, copy, curl, HTTP. I guess we could have just done that. Okay. Movies, paste, JSONPP. There's our single record grade. That seems to be working. Now let's get the endpoint with the service and event heartbeat stream. There we are. So again, different protocols, but we're not doing any gymnastics, right? Web sockets, service and event streams, rest. From the implementation perspective, it's all the same thing in spring web flux. This is different from what you would have done if you're using traditional spring MVC. You would have had to use a sync response or a sync result object in spring MVC to handle this kind of asynchronous response. You would have had to use an SCC emitter, right, to handle asynchronous response for service and event streams. Now it's just flux. Even if you're going to finish, even if the result is finite and you're going to finish soon, or if it's endless and it's not going to finish ever, it's just fluxes. All code, all publishers. Everything is just publishers. So it makes it very simple to understand what's happening in your code because it's just publishers. Where does it differ? It differs in the content type, but that's it. You just think about the world as publishers. Okay. So that's one way to build the web API. And I like that. That's certainly going to be, I think, a very popular option for people who are moving from sort of spring MVC to spring web flux. It's certainly going to be the most familiar, right, port in the storm. But there's a lot of things here that are a little different. First of all, first of all, hello, computer. There. Can you see that? It says Netty started in port 8080. So this isn't Tomcat. This isn't Jetty or Undertow or, you know, any of those other, any of the embedded web servers that Spring Boot has historically packaged. And it's certainly not a deployed application server. Spring web flux ships with a brand new Netty-based runtime, a web runtime written from the ground up specifically to support this reactivity. You can swap that out. You can use, as I say, you can use embedded Tomcat or embedded Undertow, in which case the web flux API will run in degraded performance way, in a degraded performance on top of the servlet 3.1 API, right? And that's an option. That's one of the features that's very distinct for Spring web flux is that you can run this API on top of traditional servlet 3.1 APIs in a degraded way. Remember, you're not going to get some of the benefit because the API, the servlet 3.1 API, isn't all, it's not non-blocking, right? It's not going to give you that full benefit. If you're trying to get a session or a cookie or something like that, you're going to block. Yeah. How much memory does it occupy by having the embedded Netty? I remember, like, with Apache Tomcat, it was 200, 300, because it started 200 threads by default. Yeah. How much for Netty? I don't know. What's the right way to, how do you, how do you want me to give you that answer? If you use actuator, then you can use the shell to see the memory. The remote shell? Yeah. That's deprecated. Deprecated. Which makes me sad because I loved it. How about actuator? Can we look at actuator? Sure. Let's add that here. I'm not sure how well that's going to work with our web flux, but we're going to try. Hey, cool. Yeah. It's a lot of the stuff, again, one of the big things that they're doing in Spring Boot 2.0 is making all the stuff work in the reactive world. So right now, I wouldn't trust that. And even, by the way, even if that did work, management security enabled equals false. Let's try that. Yeah. Although, J console. Okay. M beans, Spring Boot, metrics, operations, get data. Okay. Let's see what that gives us. Heap is 2496 in it. Heap used is 44136. Yeah. You get a lot of benefits from that, right? Okay. No. Cancel. Okay. Okay. What is Top Show? Java, whoop, come back. Is that IntelliJ? I think that's IntelliJ, though. That whole thing there. Yeah. That's got to be IntelliJ. 1.36 gigs. Yeah. Okay. At any rate, that's one way to build the APA. And I certainly like it. It's certainly a, you know, it's familiar. We all know how to work with that. But that's not the only way to build it now. We have a new mechanism in Spring WebFlex called the Functional Reactive Endpoints. And this is, I think, a long time in coming. I've certainly wanted to have this in Spring for a long time. Anybody who's ever used Sinatra and the Ruby world or Scolatra and the Scala world or Spark Java, well, we'll be very familiar. Sorry? Vertics. Yeah, callback. Yeah, exactly. So these are very familiar. This is a very nice approach. And the way this works in Spring is you define a bean of type router function. Can route routes. And our job is to say routerfunctions.route-request-predicates.get-movies-new-handler-function. Okay? And we're providing a callback. Fairly straightforward, right? This gets a little, we're going to do it, we're going to write this code here. But if you have enough of these, it becomes useful to sort of factor this out. And again, that's not hard to do. Because all you have to do is to provide a method reference that implements the same signature. Right? So here's how we do this. Here's how we implement this one endpoint here. ServerResponse.ok.body. And remember what we're trying to do here. With the Spring MVC style rest controllers, the return value, mono of generic type movie, gave our framework enough information to know that we're returning a stream of movies. So even though behind the scenes, we're using JSON or, you know, DOM, not DOM, we're using something stacks to write that XML. We're not loading the whole document when we send the response back. We had to do some very, very twisted work to make this do the right thing. It's going to do data framing for you. You're giving it a hint about what it should try and render and then send back. Right? And the same is true here. We have to give the framework a hint about what it should render and then commit to the client buffer. So here we're going to say that the body, I can use that service here, movie service. Okay? Here we're going to say that the body is movieservice.all and it's going to be a publisher of type movie.class. Right? So that would certainly work. And again, this becomes a little cleaner if you replace it with a lambda. Replace this with a lambda. Oops. There we are. Replace that with a lambda. So that's our sort of... I wish I could make this a little cleaner. Whatever. Okay? So there's one endpoint. And we can continue. We can say and route. And here... There we go. Here we can say get movies of movie ID and same thing, request serverresponse.ok.body.movyservicebyid. And we need to get the movie ID, don't we? Just like we did before or just like we did in the Spring MVC code. Here we're going to say request.pathvariable equals movie ID. Right? Movie.class. So now we've got two responses, two endpoints. One that returns just the movie by its ID. One that returns all the movies. And we're going to do this one more time to return the events. Okay? So and route, get movies, movie ID, events. Request serverresponse.ok.body.movyserviceeventspathvariable. So request.pathvariable equals movie ID. And we're going to return a collection of movie events, not movies. And this is almost what we need. Remember, but we still have to signal to the client that this is not your typical JSON body. So here we specify the content type when we send the response. So content type equals text event stream. Okay? So there's our rewritten API. And this is again, if you factor out this logic into a handler, into a handler method and use a method reference, it becomes a little cleaner. But at that point, you know, you're kind of back to building a controller. When you have a normal screen though, this isn't so ugly. It's just one-liners, right? Okay, so let's see. How do we do movies? There we are. There's our movies. Do a search for silence of the lambdas. Okay? There's that one. Events. There's my service end event heartbeat stream. We get all that for free, right? So we have built the same API two different ways. They're two different styles. You can use either one. I encourage you to check that out to sort of exercise discretion. Now, let's build a client, right? Wouldn't be much of a service if there wasn't a client. Yes. So, did it get warmer in here? Is there a reason? Or did it something I said? My deodorant? It's all those cost-cutting initiatives. You know, like 9 a.m., all new developers should be going home. So they've gone off the condition. In the states, in order to cut costs and make them stay late, that's very confusing. Okay. Is that what happened? Air conditioning turns off at 9? Or 846? It turns off at 9. So why is it off now? It's not off. Is it just because there's more of us here? I'm not like having a stroke or anything. Okay. I'm just curious. Okay. So we're going to build a client to talk to our service. We're going to call this the Flix Flux Client, or Flux Flix Client, who cares? We're going to use the reactive support in Spring Boot 2.0. So we're going to use Lumbuck. We're going to use the reactive web support. And we're going to generate. So unzip, Flux Flix Client. Idea.pom.xml. Okay. Now, I'm going to do something that you should never do. Ever. Not even when you're all by yourself, all alone, all alone at home, and nobody's watching. I'm going to copy and paste some code. So I'm going to grab this type here, my little DTOs, and paste it into the client here. Okay. So there we go. We're going to build a client now. And we're going to use, we're going to build a client. We could use the Spring Frame with a rest template, but the rest template is itself a blocking client. The rest template was built more than 10 years ago. It has served us well. But for what we're trying to do here, it's not particularly efficient. It's going to try and block data. So we're going to say Web Client. We're going to define a bean of type Web Client. And we could just leave it like that, or we could give it a base URL. So 8080, right? So there's our Web Client, our base one. And we're going to use that Web Client. Talk to the service. So client.git. And then the URL, of course, is just empty, empty, because we don't need anything else. Oh, actually, we do. We want to forward slash movies. And then we can say exchange. And then that'll give us a callback with something called a client response. So we can then say map. Sorry, map. And we get a CR. And we can do all sorts of interesting things with the CR. We can get the cookies, the headers, the status code, all that stuff. But what I really want to do is I want to just get the value, get the response, and then immediately transform the response to a client. Thank you, kind sir. And then I want to immediately get the response and transform it into a publisher. I want to iterate over the values that I've gotten from the service call as a publisher. So instead of calling exchange and then manually calling the flat map method on the client response and turning it into a collection of whatever, a flux of whatever, I can use the retrieve method. And the retrieve method goes straight to this. It saves a few steps. I can now say give me a publisher of type flux. And then what I want to do is I want to say, if I want to filter a movie by its title, right? A on flux, there we are. And I'm going to then use that returned movie. I'm going to use that to then call the event stream, right? So I'll say client.get.uri. Movies. Movie ID. Events. Passing in the movie ID.retrieve.body-to-flux. Movie event. OK. And then we'll return that here. So gizunt. Then we can subscribe to the values and print line. OK. So there's our command line runner. We don't really need that, do we? Don't need this. There we are. So all I'm doing is I'm creating a command line runner. It's going to call the movie's endpoint. Then it's going to get the data. Turn it into a collection of movies. Find one movie that matches our certain string. Then use that movie to call another endpoint. The events, come on. The events endpoint. Passing in the movie ID as the URI variable. And then printing all that value that comes back out. All right. Let's see if that works. Or not. Oh. I'll bet you I know. Server.port equals 8081. I'm not even going to look. Ha. There we are. So you can see reflected in the console there, an ever-expanding list of values being generated from the service. It's not going to try and load everything. It's not going to buffer everything. It's just going to return the values and write it out as it sees them efficiently and infinitely. It's going to go on and on and on forever and ever and ever and ever. It has no end like the skies and the oceans and the stars. Infinite. Endless. Like the bugs in your code, just infinite. Just infinite. So there we go. That's our client. Now, it's 9 o'clock. What time do we have to get out of here? Seriously? Can we do it? Can we do half an hour? Who wants to do security? Nobody. If you're excited about security, raise your hand. That was the first time that's ever happened. So we'll do security. So I've got a rest endpoint. We've built a super efficient, oh, Santa Maria. We've built a super efficient, super scalable, resilient, robust Hello World demo. So not much of a demo. And this isn't going to be very useful if it's stuck at demo land. So one of the real world concerns that people care about when they move to, you know, when they build applications is security. And think about how security works. In particular, think about spring security, right? It has a thread local attached to the context for the request. That locals don't make a lot of sense in the reactive world. The last thing that we want is to do all this work to get ourselves up to speed with the reactive programming approach that spring supports, only to then bottleneck on top of a thread local before anything gets done. So spring security five, which is also in milestones, features end to end reactive support. And it has some other nice features as well. It also supports o-off, you know, built in as opposed to being a separate project that code gets merged into spring security itself. So all of the support is now in spring security five. What we're going to do is we're going to use spring security here. But there is no spring boot auto configuration for spring security, not yet anyway. So it's up to us to sort of pull things together ourselves. It shouldn't be that hard. I don't know, how many of you have used spring security for ten years or more? Okay, good. It was painful in the beginning, right? Security is a very hard, complicated domain. So the original focus of spring security was to make anything possible. Now, in the last sort of eight years, it's gotten simple as well, right? But in the beginning, it was very possible to write, you know, five, ten, stanzas of XML before you had anything working. Now, what we need to do to support spring security in our application is we need to think about authentication and authorization. These are two distinct things in the spring security world. So let's go back to our application here. I'm going to bring in the dependencies. Again, there is no starter, not yet anyway. There will be, but give it time. Spring security config, right? We need the spring security implementation. We need the web flux integration for spring security. And we need the core support, right? So these are the three dependencies that we need for now. Again, I expected that there was going to be a spring boot starter reactive security or something like that eventually, just like there's a spring boot starter MongoDB reactive, right? Okay, so there's this. And what we need to do to make this work is, again, we need to talk about the two things that are implied in security. Any discussion with security involves both authentication and authorization. Authentication is who's making the request? Is it Josh or Jane or Weren or Sergio or, you know, who's making the request? There's no implied assignment of rights in that discussion, though. Let's say that we know it's Weren. What is Weren that allowed to do? That's authorization. Authentication is who's making the request? Figuring out what that authenticated principle is allowed to do, that's authorization, right? Maybe Weren is an administrator so he can, you know, manage everything in the system, but some people are just regular users. So they can only do read-only kind of things, right? That's authorization. So with spring security, at the heart of spring security, you have something called an authentication manager. An authentication manager is a very, very simple type. It looks like this, authentication manager. And the contract is super simple and purposefully vague, purposefully abstract and decoupled from any particular discussion of technology or identity provider or, you know, authentication flow, right? So here we have an authentication manager that takes an authentication request and returns an authentication. Fairly simple, right? Authentication in, authentication out. If authentication is successful, then this boolean is authenticated will be true. It's about as simple as it gets. There is no implied discussion about, you know, who this is. Well, not until the return value is here, right? The return value has credentials and a collection of granted authorities and details and principles, but even there, it's just objects. There's no implied discussion about what this should actually contain. It might contain a certificate. It might be, you know, it might be just a collection of strings. It might correspond to scopes or rolls or whatever. It doesn't really have specific details here. So the authentication manager in spring security is the heart of spring security. Authentication manager then delegates to a chain of something called an authentication provider. Authentication providers are just like, they look exactly like authentication managers, except they also answer the question, can I handle this kind of request? It's a chain of responsibility. So authentication manager manages a collection of providers. There is a, there's a specific type of authentication provider that you may be familiar with, if you've used spring security, called a DAO authentication provider. The DAO authentication provider is how you, it's how you use spring security to answer, to do, to support authentication using usernames and passwords. So if you've ever done a username and password based login in a web application, that's ultimately going to delegate to a DAO authentication provider. In this case, DAO refers to, it refers not to the way, that's a Chinese joke, friends. I thought that would have killed here, never mind. It refers instead to data access object, right? So we can use a data access object, like a repository basically, to solve that problem. So we're going to use, it's basically the same structure in the reactive world, but things are a bit simpler. So we're going to create our reactive authentication manager. Okay, here we are. New, and then this is a user details repository authentication manager. Okay, and we're going to pass in a user details repository. Okay, there's this. And we're going to provide our own user details repository in a minute, but let's just set things up so that we know the players and how they wired together. Okay, so user details repository UDR, there's that. Okay, and finally we need to, this is what we've shown you here. This is all to do with authentication. Now we need a discussion of authorization, right? So authorization, and basically we also want to configure spring security. We want to configure spring security to protect our web based endpoints. So we're going to create a bean here of type web filter. This is the spring web flux filter mechanism, right? So web filter, security, filter, chain, although it doesn't need to be called that. You just may be familiar with it, so I'm going to use that. So htbsacurity.htp. Okay, there's our htbsacurity root configuration object. And we're going to say return htbsacurity.build. And we need to specify a few things here. We need to say that we want to use htbsacurity for security, great. We want to tell it to use our authentication manager, our reactive authentication manager. That's this thing here. So we're going to give it a pointer to that, right? AM. And we want to tell it to protect our endpoints, all endpoints. Starting with four slash asterisk, asterisk. And here we could, you know, we can use the traditional sort of, I'm sure you've done this before. We can use the traditional sort of methods here. Has authority, has role, permit all authentication. Basically, we can provide a string here. We can say role admin, for example. And that would certainly work. But I want to demonstrate a nice feature in Spring Security 5 that's new. The access callback. And the reason this is so nice is because Spring Security 5 builds on top of Spring 5, which in turn builds on top of Reactor, which means everything is Java 8 or better. So we can use lambdas into great effect. And so Spring Framework itself has been Java 8 modernized, right? And so Spring Security is now taking advantage of that as well. Here's an ideal place for a lambda. This is a reactive authorization manager. So we'll come back to this bit of code here in a minute. But let's go ahead and implement this first. So when a request comes in, it's going to be represented as an authentication. Spring Security is going to then turn that authentication. It's going to try and authenticate the user. And it's going to do that by unpacking the authentication request and determining that there is a username in the request body. It's going to then delegate to its authentication providers. In this case, the user details repository is going to be plugged in somewhere. And it's going to ask this user details repository, I've got a request coming from somebody called username. Who is that user? I need you to tell me who that user is and then provide it for me as a user details object. The user details object, there's a concrete implementation called user. So, since this is security and we care about the durability and the longevity of the data and we care about the accuracy of the data, I'm not going to use MongoDB. We're going to instead... Yeah, we're going to hard-code it and keep it in memory. And it'll still be more reliable than MongoDB. So, we're going to create a hard-coded map of strings with a list of roles. Okay? Web scale. New concurrent hash map. Okay? Actually, make it even simpler. Don't even need this. Go back. There we are. So, we're going to save the users here. We're going to say, we're in arrays.aslist. Roll add... Actually, here. Public static. Final string user. Roll user. Admin. So, user. Okay? And I'm Jalong. I'll just be user. So, there we are. There's two users in our system. And when a request comes in, we're going to check our database. Big Iyuanic air quotes. We're going to say users. Sorry. Users.git username. And that's going to return either a list of strings or null. So, I'm going to say optional of nullable. I'm going to map that list of roles, right there, right? I'm going to map that to a user object if it's there. I don't actually need the user. I need the fact that this is here tells me that that record is in the database, is in the map, right? So, that's actually what we're doing here. So, we're going to create a user object, user. New user. Okay? And the user object, this is a concrete implementation of user details. It expects the username, which we know is there. It expects a password, so we're going to just hard-code it because, you know, security. And then it expects the collection of roles. And of course, the roles here are, it's just a list of strings. So, we need to stream it, to map it from s to new simple granted authority, passing in s. There we are. .collect.collectors.toolist. There we are. So, we save that. Granted authorities. Good. Pass that in there. Okay. So, we've got our user. And, I wish I could, I think I'm doing the thing that makes me saddest in the whole world. I think I've got tabs. Oh, yeah. Anyway. Okay. So, we've got that. We turn the user. Goodie. Okay. So, there's that. We assign this result to an optional of user. And we're going to say, return mono.just or empty. Is that right? Yeah. User.or else throw new username. Not found exception. Couldn't find username. Okay. Simple. When people look at this code, they're going to say, boy, that's simple. Or not. Anyway, you won't do this more often. You're not going to do this usually, right? I'm using a, I'm running my own user details repository. This one time so that I don't have to set up, you know, LDAP for our demo. Okay. So, there's that. So, we've got a custom user details repository. We've got the reactive authentication manager. All that we need to do now is we need to say, what happens here? How do we do the authorization? In this case, I could call a database. I could talk to, you know, I could check the horoscope. I could do whatever I wanted to determine whether that user has the privileges to access this resource, right? In this case, it's every resource. So, every request at four slash root will get passed through this line of code. In this case, I'm actually going to manually implement, so you can see how it's done, the same thing that spring security is basically doing behind the scenes. I'm going to check the collection of granted authorities and then use that as the basis on which to decide whether a request should be allowed. So, I'm going to say mono dot map authentication. And my job here is to say, does the user allowed is the, you know, user is admin, right? So, I'm going to say, I'm going to say that we need the authentication dot get authorities, that's the collection of granted authorities, dot stream dot any match, ga dot authority dot equals roll admin, or just admin, okay? And we're going to say, if that is true, then we turn a new authentication authorization decision saying user is granted, or user is admin, okay? So, we say return mono dot just, did I already do that? Hey, I did that, didn't I? Yeah, that works. So, goodbye to this. Okay. So, this becomes a little cleaner when you use lambdas, of course, so goodbye to that. And there we are. So, now let's start this service up again, and let's see if we can make the request. So, whoa, what did I just do? Here we are. Curl, HTTP, local host, 8080, forward slash movies, minus V. It says 401 unauthorized. We're not allowed to make that request because we're locked out. Now we can say minus U, J long password. So, I don't have the permissions to access the service, do I, right? So, I am just a user, and we're specifically testing to make sure that whoever makes the request is an admin. So, I'm going to make the request now using curl, and it says 403 forbidden, not allowed. Now, change it to my buddy here. There we are. And there we are. There's our data, authenticated. So, there's the service side. And of course, on the client, we also want to be able to use this. Otherwise, it wouldn't be a lot of fun. So, we change one more thing. Here. And we can create a filter. Let me say exchange filter functions dot basic authentication. And password. Et voilà. Okay. So, there's the code. I'm configuring a filter on our web client to do basic authentication. And it's sending the username and password. Now, we can prove the negative by breaking the system or by tampering with information. See, H3 request failed, 500. Or we can try my name. And we'll get an exception, right? So, it only works if somebody is valid and they have the permission to go through. 403 forbidden, right? Okay. So, my friends, we've looked ever so briefly at just a few things that you can do to build reactive applications using the Spring ecosystem. We started with Project Reactor, which underpins everything, right? And the nice thing about Reactor is that it lets you describe synchronous and asynchronous values using the same thing. Once you write your code, whether it's actually asynchronous or not is in implementation detail. As we've looked, as we've seen in our talk today, there's a lot of places where it is actually going to be asynchronous and you benefit from that asynchronousity. Everywhere your stack where you have input and output, and we take for granted how often that happens, but everywhere in your stack where you have input and output is an opportunity for asynchronousity and for reactivity. So, we have introduced that. We can support that by using the publisher types, the types from the Reactive Streams Initiative as supported by Reactor. Then we saw how we can then use that to talk to the database, a reactive supporting database driver, something like Reactive MongoDB or Reactive Cassandra or Reactive Couchbase or Reactive Redis. Then we saw how we could build a web application or web API. We used the traditional spring MVC style first using REST controller, but then we looked at this new thing called Functional Reactive Endpoints. I'm a big fan of that as well. Then we introduced security. The security bit is all kidding aside. You're not going to usually create your own user details repository. You're going to have one that's preconfigured out of the box in spring security. You don't have to register your own Reactive Authentication Manager once spring boot. Auto-configures all this for you. That's two out of those three beans that are gone. Then the only thing that remains is how you configure the web filter, the security filter, which says that you want to do HC Basic and you want to do these checks at these endpoints and so on. That's what you would have to do anyway. The security stuff will only get better. I think it's very nice already compared to, you know, cognitively we need to solve authentication, authorization. There's a bean for authentication, another bean for authorization, and then there's that one extra bean which we need for infrastructure which is the Reactive Authentication Manager. So that'll go away. That's two lines of code. It'll go away. This is just the beginning, as I said. What we're looking for, one of the real values that spring can bring to the table here is that we can integrate this stuff end to end. So you can build an application that in every layer of the stack is reactive. And we've got a very rich ecosystem here so we can bring support for that across every project where it's appropriate. We're also going to have new projects that are, you know, reactive first. They don't have any synchronous alternative. One new project that we have is coming up. It's called Spring Cloud Gateway. Spring Cloud Gateway serves the same sort of use cases as the Zool Micro Proxy. Last time I was here, I talked about the Zool Micro Proxy. The Zool Micro Proxy is ideal for, well, just that proxying data back and forth from services downstream to the client. It's naturally very IO-intensive work. So it makes sense that this would be reactive first. There is no alternative. It uses Reactor. It's built on Spring 5. You can't use it with anything older than Spring 5. It has, out of the box, because it's a spring project, it's, you know, I think the API is much cleaner than the Zool filter model, right? I don't know if you've ever had the displeasure of writing a Zool filter, but in order for you to write a filter, you have to implement a method and then return null. You have to implement a method in the interface and then return null. And the reason is because they just forgot to change it to void. Seriously, it's never used. It's completely pointless. So it's like, every time I see that API, I want to take a shower, you know? So it's just, it's not a good API. But it works. I'm not trying to take away how valuable it is and the fact that it works, but nonetheless, there's room for a cleaner alternative. And also, some of the things that Netflix does that are really interesting with Zool, that stuff isn't yet open-sourced. So for example, rate limiting. I want to have a proxy that is the first port of call that is then used to sort of handle requests downstream. Right? But I only want to allow, I want to throttle, you know, 10 records per second. I want 10 requests per second. That's called rate limiting, right? I can't do that without writing my own Zool filter right now with Zool because that code is proprietary to Netflix completely reasonably. I get it. That's fine. But nonetheless, we have, for example, one that we provide in Spring Cloud Gateway. There's a lot of things that we can do that. We wish we were there, but there weren't, you know? So there's a lot of really interesting opportunities here. And as you've seen, it shouldn't be too hard, too big of a cognitive jump to sort of take that first step. It is just Spring Data. It is just Spring Web Flux and Spring NBC style, you know? And you should be able to get up and running very, very quickly with Spring Boot, doing most of the configuration legwork for you. Now, I'm grateful for your time, my friends. I really am. I know you have a lot of places you could have been tonight, but instead you chose to come here and hang out with us. And that's really, really great. Really cool. Thank you so much for that. I want to thank you for being here. I'm happy to answer any questions. I can imagine you might have one or two. And with that, thank you so much. Okay? Thank you very much. Cheers. What's your... Yeah. The authentication? Yeah. I'm not sure if the... So, good question. Yes, there is a way to do that. I just don't know if it works the same in the new world as it did in the old one. So if I go back here, this is the client, here's the service. Let's see. I don't know if this will work. We're going to try. So let's get rid of this for now. I don't... I mean, let's get rid of that. And then in this one, in the REST controller here, in the old API, in the old sort of spring MBC blocking, I can say principle P. Let's see if that works. Okay. Yeah. It didn't blow up. That's a start. And we don't... Do we have a client? Let's restart that. Hey, look at that. Does that works? So yeah, that works. Ha! I learned something. Other questions? Yes, sir? It's a popular example on your... Yes? I thought you'd never ask. Is this your new love? It's your new love too. You just don't know it yet. You just don't know it yet. Kotlin... So in Spring 5, we have a separate Kotlin module. You know that Spring Boot itself has supported Kotlin as one of the languages on the Spring Initializer for a better part of a year now, maybe even more. So there's Java, Groovy, Kotlin. And Kotlin has always been there as an option for generating Spring Boot applications. But really, it was just, you know, setting up the compiler plugin and setting up the main build. Otherwise, it was just Spring Boot. You're using the Spring Boot API. What we've done here now is we have in Spring 5 a separate module that provides Kotlin extension methods for types, right? And Kotlin can do some very cool tricks that Java can't do, one of which is reify generic information at runtime. So we actually... The extension classes in Kotlin allow me to add methods to types at runtime, right? To existing types. So I can add methods that are aware of generic parameters and thus don't need to have them specified as a class literal. So imagine using the REST template. You know, the REST template has a a git for entity, and it takes a class literal. I can say, REST template.gitforentity.movie.class. Well, if I have a list of movie x as a return value for that git for entity, why do I need to say movie.class again? It knows that the return value is, you know, so it can do that now. I can override that. So we've got some extension methods for common case uses in Spring 5 itself. You don't have to use Kotlin. We're not like, you know, it's fine. But then, one of my favorite things is what we're doing in the Spring 5 Kotlin module is we have some DSLs where they make sense. So here, github.com, Flix Flux Service. Here's the... This is the code for this example, by the way. Flux Flux Service Kotlin. Source, main, Kotlin.com example. And there's a DSL, for example, for the functional reactive endpoints. So here's that same code as I wrote before. Just a little bit simpler. It's a little easier to read, I think. Just a bit. Here's the movie event without Lombok. Actually, this code doesn't have the security. There's no security here. And what else is it missing? It's missing security... Oh, and I don't have the commented out REST controller. I've just kept the functional reactive endpoints. So that's 110 lines of code. Here's the... Yeah. Let's assume that... Let's look at the security here. That's the service. There's the security bit right here. So goodbye to this. Okay. And keep that and get rid of the REST controller as well. Okay, so Control Alt L to format it. Get rid of the extra lines. 146 lines for this. You know. 110. Right? Like for like. And I'm not saying that you should switch to a different language because it's less lines of code. Perl is infinitely fewer lines of code, but I wouldn't do it in a heartbeat, right? Like, I'm not saying you should do that, but it is a more typesafe language than Java. It compiles as fast as Java. Unlike Scala where you want to warm your hands. So it's a nice language. We have some nice DSLs where appropriate. You don't have to use them. The Java Builder APIs and Java DSLs are perfectly usable. You just saw that. It's fine. I'm not complaining. I wrote it live. I felt no trepidation about doing it live. But that said, Kotlin has really caught my attention. It's just really nice. Google seems to like it. I don't know if you saw the recent announcement that it's now a supported language on Android. And that's because Kotlin compiles to Java 7. Making it perfect. Google doesn't have to do any work to make Android native Java 8, you know, really good. So there's a lot to like. Yes, sir? Is your feeling that it will stick around Kotlin in the spring ecosystem? It's in spring framework. Because there were some scour extensions over some time ago that they sort of disappeared. They weren't, but that was an in spring framework. Sorry. That was never in spring framework. Yeah. And with Kotlin, we've gotten... So the Kotlin team has been very, very responsive to making changes to the language to make it work better for Kotlin. They're serious about it, right? And the community has been amazing. They are using it. They're doing amazing things with it. And they're asking us for this. And now it's in spring framework itself. Remember, spring framework, we don't break spring framework. Not come head or high water. It stays backwards compatible wherever possible, right? For five years, often. So, and then for the core stuff. I mean, my goodness, spring, you know, if you wrote a spring 1.0 application from 15 years ago, dropped in spring 4.3 today. That would still work, right? So, yeah. We don't introduce things into spring framework into the distribution lightly. So I expect that'll stay there for a while. And Kotlin itself is, as you know, it's five plus years old now. You know, it's certainly got common ground. It's one of the languages that developers report wanting to learn repeated, you know, all these different developer reports that I see from zero turnaround and others like that. So, you know, but don't take my word for it. Just try it. I didn't even mention it because it's not like you have to use it. It's fine if you're using Java, you know. I love Java, but Kotlin's cool. Like, I almost want to do my talks in Kotlin. I'm not sure if people, like, would anybody be distracted if I did that? Would you? Sorry? I think we're trying the Kotlin model. Yeah. And you wouldn't be doing all that cleanup after you've written the code. Yeah. Do you want to see something kind of cool? Like, so here, let's try this again. Flux Flix service Kotlin. Spring Boot 2 Kotlin. We don't need Lombok. We just need reactive web, reactive Mongo. Generate. Unzip Flux Flix. Unzip Flux Flux service Kotlin. Idea palm.xml. Whoops. So that's downloading the Internet. Give it a second. I'll take some tea. I think I've earned it. And so this preconfigured Kotlin for me, mainly adding the standard library there and the Maven plugin. What I love about this, you know, IntelliJ, the team at IntelliJ have shown their commitment to making this work. And the way I know that they've shown their commitment to doing that is that they wrote the Eclipse plugin for Kotlin. Yeah. I give them a lot of credit for that. That's what I knew they were serious. What about Netflix? Yeah, I just don't know if that's a thing. Okay, so my favorite part of that experience, though, is this. You can go to Paste. Yeah? And you see that? It says, clipboard content copied from Java file. Do you want to convert it to Kotlin code? Yes, I would. Yes, I would. And there we are. So now this is all Lumbuck. We don't need that. It's not perfect. Obviously, this should be just a, you know, I don't need the actual, I can just do this, right? Here's the movie, paste that in there, good. And then we need the movie event in the website. Where's my movie event? Yep, data class. Okay, there's that. Some things require a little bit of work. Yeah, a little bit of clean up there required. Let me see. I'm going to cheat here. Well, anyway, I could sit there and fidget, but 90% of the work is done in that extension. It's a nice language. I don't know. Give it a shot. Take my terrible Java code and copy and paste it. And we talked about how that's the only other time when it's okay to copy and paste, even when nobody's looking. Other questions? Yes, sir. So now we have all this nice little reactive backend. What do I tell my front end friends? What should they use to interface nicely with it? Oh, they're going to be so happy with you. Because on the client, the perspective, if you're building a REST API, the perspective from the client is exactly the same as before. It's still a REST API. If you are serving service and event streams, you can consume service and events from Angular and React and whatever. Same as before. Nothing is different there. Same thing for WebSockets. The client won't care. That said, there is an opportunity here for whole team learning and improvement. Your friend and developers are probably already doing this. They're probably using something like Rx.js, which is a reactive JavaScript client that provides the ability to talk about types in the same way as we've just done here in the service side. So they might say, what took you so long? You know? And that's okay. They're right. Give them some credit. What about some of the native applications? Have you had any experience with those? Like on Android? Oh, yeah. So again, there's an Rx for Android. There's an Rx implementation for Android. I don't know about the iOS stuff. I have no idea. But I know that there's got to be an Rx implementation for iOS as well. You go to reactive.x.io, you'll see all the languages. Yeah. There you go. Yeah. And how about plans for some of these reactive things reporting on to Android, the Spring for Android? There's no plans right now for making any of this stuff work on the client side. We have Spring for Android, but that's just a REST template. It's never been full configuration and all that stuff. And I don't expect us to be further investing beyond that basic capacity. Especially now that we have a really good like OK HTTP, for example, and Android is a great client, right? And Retro, what's that? What is it called? RetroWeaver? What's the Android client? Yeah. It'll come to me as soon as I leave the room. They're already doing it. It's already done. It's nice. We don't have to like the code. My favorite kind of code is the code. We don't have to write. There's no need. Other questions? All right. Well, thank you so much. I appreciate it.