 So yeah, it's a thing. I am very excited to announce, when Greg asked me about an octa thing, there is something that really exciting happened today, and that is octa is now on start.spring.io, one of the coolest places on the internet, so you can actually select octa now. And if you don't configure it, then your app won't start, because you haven't configured it. So it's just like spring security, except out of the box, we expect you to configure your security settings. So that's exciting. I have another exciting project that I'm excited to talk about today, or show, after Josh. Josh is going to basically do the intro, where he builds an API using spring web flux, and then I'm going to build a React UI on top of that. And the reason we wanted to do this is because you always hear from pivotal and many folks in the Java community about their reactive APIs. And reactive APIs are pretty cool, but what about when you actually put a UI on it? When you put a UI on it, is there anything in the UI world, in particular in React, that will allow you to have a reactive front end that actually gets data when it comes from that back end? So that's what we are going to explore today, and show you. I actually do have a plug, if you want to. Do you? Yeah. Do you? And don't kick out the microphone. Yeah, no, the one that we got working by the skin of our teeth. Let's see. What a day. Thanks, boss. Oh, I'm so excited about this. Stay. Where's my, yeah. I'll put it over here. In my backpack? Right down there. No, no, don't. Just put it in the backpack. Otherwise, it'll be gone to the ages. Hi. Hi. Yeah, look at that. Woo, I am, you are not going to believe that demo almost didn't work. And I figured out that in order to get it to work, I needed to be using Java in spring. But I was using PHP. Of course, it wasn't going to work. It failed utterly and completely. So I fixed it by turning it around. Let's see. Get status. Huh? Yeah, you want me to share my screen. But hold on. I'm still hiding the rabbit. I got to stuff it up a little bit. I'm getting on the stage. Here we go. So like I said, he's going to build the back end. I'll build the front end. It's basically going to be almost like two separate talks. But we decided to ditch the slides. So we will post slides afterwards. And maybe they'll match up. But everything is being recorded. It is broadcast live on YouTube right now. And tomorrow, we'll probably do some editing that video so we don't have the first 30 minutes of just people shuffling around or whatnot. I mean, that's the best part. And my son, Jack, over here is doing all of the video stuff and making it all work, so I'll give him a hand. Woo! My daughter is probably horseback riding. She got her driver's license, like a real driver's license now, so we see her at like 8 and 9 at night instead of like at 4 when we go pick her up. She does do a lot of horseback riding though. So hopefully she's out of there. Out there, she's got a big show coming. Does the adapter spin? Do you remember when the Apple could design things? Ah, sweet nectar. All right, turn down the lights. All right, take it away. Thanks, buddy. All right, so all right. Yeah, this code is not there. You won't find it there. It's not there. Don't bother with that URL. That's a lie that I did to throw you off the trail. You go here. Actually, I think Matt and I will have it somewhere. But in the worst case, you can go here to the repository that we just created here. And this will have, in the absolute worst case, it'll just have a giant read me saying go here to the actual URL. So this is the URL where what I'm going to type right now will be, and this will be the thing on which Matt will work once he, so there's that. Now, a little bit about me. We said no slides. It's important if you have questions, comments, feedback, obviously by virtue of the format of what we're doing tonight, we have time. We can sit here and chat and have a discussion and engage in that discussion. We have time together. So of course, I can answer questions I'm happy to. But that said, there's also my Twitter. So if you have questions, comments, feedback, whatever, find me on the Twitter, I'm happy to engage, obviously. And then, of course, email. So if you have email, how many of you are using email? I'm just curious. Anybody here using email? I'm not really a big email person. But it's an option, and I respect that. So if you want to use it, that's fine, just understand. I'm a wee bit, a sink. And my responses tend to be a little bit delayed. It's better than Slack. So I guess that's at least something. I have a friend named James Ward who said that while he's not entirely sure, he thinks based on CPU activity alone, that Slack was mining for Bitcoin, which I 100% that could be, that's real, that's real. You may have noticed I'm using a brand new MacBook Pro. A brand new MacBook Pro 2018, with all the mushrooms and anchovies and toppings and everything, fully loaded. And the reason I got this, the reason I was so enthusiastic about being able to get this is because with 32 gigs of RAM, I can now run both Slack and Chrome. So here we are. Anyway, moving on, there's that. A little bit about me. I work in the Spring team. If you know Spring, then you've probably used some of my bugs, and I'm sorry about that. They made a toy out of me, which I think is kind of cool. I do training videos. These are on Safari. How many of you know Safari? It's an all-you-can-eat buffet-style technical marketplace for content. If you don't have access to it, get it. It's great. It's like Netflix, except that you don't get stupider. So that's that. Lots of different videos in all manner of different topics. The latest and greatest of which, of course, is this video on Spring Security by the one, the only, the amazing, the inimitable Rob Winch, lead of Spring Security and myself. And of course, I do books. I wrote a book in 2017 called Cloud Native Java. It's something about which I'm very proud. I was in St. Petersburg, not Florida, talking to somebody, and they were asking me to sign a copy of the book. And I said, I'd be very happy to sign a copy of the book. And I don't know that I should have been so surprised at what happened next, but I was. You see this nice person, college-age-ish, I don't know, person handed me a copy of the book, and I was still talking to said person. And I started to muscle memory my way to signing the book, because that's what I was doing. I was in the throw of doing that. And I looked down to realize that the book was in Russian, which is fine in and of itself, except that I didn't know that there was a Russian edition of my book. So I now live in a world where behind every corner, in every shadow, looking behind every door, there's possibly another edition of my book in another language about which I'm not yet aware. That's an interesting place to be for me. Makes my life just that much more mystery, mysterious. So there's that. I've got a book that I'm working on right now called Reactive Spring. This isn't done yet. So just hold on to that thought. It'll be ready eventually. So anyway, we're going to talk about that. We're going to build Reactive Code today. We're going to build an application based on a small, what I've, what Matt could do to doing a tutorial with him sometime last year. He said, we don't have to really, we don't have to figure, it doesn't have to be too much, Josh. I know you're a busy guy, basically, he said. And it doesn't have to be huge. How about we do a light blog together where we can demonstrate how these concepts play well together. Anyway, like 50 pages later, we had our blog. Was that one blog, or did we ever divide it into small pieces? It ended up being three. Oh, yeah. Three generous blog chunks. So yeah, that blog then inspired me to write this book. So that book, full circle, and back where it started, thanks to Matt. Now I've got more work somehow. So there's that. And we're going to talk about some of that stuff today as well. And of course, we're going to talk about it in terms of all the latest and greatest stuff in the spring ecosystem. Then of course, Matt will take us home and take my theoretical working code and turn it into something useful. And we're going to build a new piece of software here, of course, on my second favorite place on the internet. My first favorite place on the internet, obviously, is production. I love production. You should love production. You should go as early and often as possible. But if you haven't gone to production, you can begin your journey here at start. That spring that I owe. If you need inspiration in the early morning before a cup of tea or coffee, start that spring that I owe. Oh, curses. If your children are restless and can't sleep, start that spring. And if you suffer from indigestion, after a long night of alcohol abuse and PHP, start that spring. So we're going to build a new piece of software. We're going to call this the Profile Service. And it's going to serve and manage profiles. And we're going to build it using the reactive web support Lumbuk to make Java just a wee bit less tedious. And we're going to use the reactive MongoDB support. And we want to use the newfound, newfangled, Octa support. This is just today, right? Am I the first person to do a talk? Demoing that checkbox? That's a little weird. You want to do the honors? Nah. OK. Like, I was going to just let him press this button, but I did it for him. So there's that. I mean, he did all the work of getting it there. Did you who? I tested it. I broke it a couple of times. OK, that's better you than us. So that's great. We have the now Octa support. So that's our basic application. And I think I'm satisfied with those selections. So what we're going to do is we're going to build a web application. You can use Spring Boot and Spring in general to serve a number of different use cases, a number of different niches, including batch processing, integration, web processing, all sorts of different kinds of workloads, stream processing, messaging, all these kinds of use cases. But today we're going to focus tonight, rather. We're going to focus on building a web application. And in particular, we're going to build three different endpoints. Three different endpoints that then the client that Matt builds will connect to, or to which they will connect. So we're going to build this application. I've downloaded the zip file into my Downloads directory here. Like so. I'm going to open this up, ProfileService.zip. And we're going to bring that into our application and into our IDE. I'm going to use IntelliJ. How many of you are using IntelliJ? Just curious. Show of hands. Show of hands. OK, very cool. Very good. Good stuff. I love it. What about Eclipse? Also great stuff. I love Eclipse. Good stuff. OK. What about NetBeans? Also awesome NetBeans. Right on. Love NetBeans. Visual Studio Code. Oh, that's. Did you ask that already? Do you see what I'm seeing here? Like at least five, six people. Seven? Yeah, more than NetBeans. Whoa. Maybe it's just a Denver thing. What's in the air here, you know? High altitude? I don't know. I like Visual Studio Code. I've never seen that many people in one place using it. That makes me happy. So we're going to build a new application. By the way, there's a good Spring Boot plugin for Visual Studio Code. So the Java support comes from Red Hat. Yeah, Red Hat. The debugger comes from Microsoft. The Spring support from Pivotal. And what other universe do these three companies all work on the same project? Makes me happy. I love that. So we have a brand new application. Can you all see that? Is that too small? Should I make that fine a little bit larger? Just a little bit. 22. Good stuff. Look at that. All right, can you see that in the back? On the screen? In the cameras? OK. So we're going to build an application that manages data of type profile. Like so, it's just going to be a simple object that stores IDs and an email. And we're going to have a DTO, an entity that manages that data. And we're going to describe it using an object with getters, and setters, and two string, and hash code, and equals, and all that. I just use Lumbock. I love Lumbock. How many of you are using Lumbock? Just curious. I've gotten progressively lazier over the years. And so while I was a big fan, initially, of just using straight Java wherever possible, I realized that I just couldn't do this in good faith on the stage anymore. So there's the modern Java way of doing that, right? That becomes a one-liner in Kotlin and Goovy and Scala. But that is arguably the longest single stands of code in my code page and my application today. So rather than do all that, I use Lumbock. And what I want to do is I want to have an application that manages data that's going to be persisted as a document in a collection in MongoDB. Now I have MongoDB running on my local machine in the background here. And then in order to be able to persist and work with and interact with instances of this entity, I'm going to create a repository, so a profile repository that extends the reactive Mongo repository. So there we are. And I'm going to, there we go. Now I'm going to comment out some things, because what's going to happen is that that's going to start up. I've got an auto-configuration that's going to start up and talk to MongoDB. It's going to connect to MongoDB. And at the same time, were I to leave the octa support in here, it's going to start up and do some work as well. Work that I have not yet prepared for. It's not yet configured. So I want to take that out for now. Matt, he'll do it. Make Matt do the work. So there we go. We've got a repository. We've got an entity that we've got in the database. I'm going to just create some sample data so that we have something with which to work. For now, so we're going to say initializer. And this is just going to be a bean. It's going to be a spring bean that implements the application ready event listener event rather. There we are. And there's my event listener. And it's just a spring bean, so I'm going to tell spring to manage instances of this bean. And when this application starts up, it's going to inject a instance of this profile repository, this thing that I've just created that's going to allow me to interact with my low-level data tier. So I'm going to say flux.just a b c d. So I've got some names there. I'm going to take each name, rather email. Let's just say those are emails. And new profile, null passing in the email. And then I'm going to take each one of those and save it to the database using my repository like so. Now I want to write all that to the database. I'm using reactive APIs here. This is all a publisher. What I have here is a publisher of type profile. It's a stream of data. It's a thing that will materialize asynchronously and possibly on separate threads. It could happen also concurrently. I don't need to really worry about that, though. There's a schedule behind the scenes here. But the benefit of this mechanism, the benefit of reactive programming, is that it lets me model a synchronous IO, something that I know is going to be happening underneath the hood in a way that makes sense for a higher order business logic concerns. And so to make this example as clear as possible, I'm going to show you the most painful code that I can. So github.com, octa developer, here we go. So this is my code that Matt foolishly put on the website there. So here's a simple example. Suppose I wanted to build an interface called reader. Where in, I support reading a file. And for each byte payload wrapper of data, there's a consumer that gets called when there's new data. So I've got two implementations of this very simple interface, one that's synchronous, one that's asynchronous. So let's think about that. We go down to the synchronous version. And you can imagine how this one looks. This one's very straightforward. Very straightforward indeed. It says, given a file input stream using Java 7's auto-closable, create some bytes. Create a byte buffer. And then read from the input stream data into the buffer starting from this offset to this offset. And as long as the in.read method doesn't return negative 1, then deliver a bytes payload object to that consumer. The callback back with the consumer. Very simple. Just reading from an input stream. Nothing fancy about that. And the thing is, this is just a file input stream. So reasonably, we can surmise that it's not going to take a long time to get the next sequence of bytes from the hard disk. Assuming your hard disk doesn't just blow up or fall down or fail catastrophically, that's going to be pretty quick. It's just going to pull the data off the file system and into memory, and you're going to be able to process it pretty quickly. But imagine that instead of a file input stream, just imagine this could have been some sort of socket input stream, where the data is coming from another buffer over the internet. The same code would work. I could swap out the input stream type here and substitute it for some other input stream type. And it's exactly the same logic. But what happens when there's a network connection? What happens when there's latency? What happens when something goes on such that I don't get all the data as fast as I wanted? Now, in between the raindrops of bytes here, in between that in.read call, the execution has stopped. We say it's blocking. It's not moving to the next line. It's sitting there, just waiting for the next byte to arrive. And when that'll happen, we don't know. And in the meantime, we're stuck here waiting for this as a client thread we're executing on. That thread is being used for the purpose of doing nothing. It's being monopolized for this input. It's not good. And the reason this isn't good is because threads are pretty expensive. Threads are a very expensive resource on the JVM. They take a lot of system resources that we don't readily have available. So suppose for some reason you wanted to have 1,000 concurrent requests. The naive approach might be to say, OK, well, I'll have 1,000 threads. Do you have 1,000 cores? If you don't have 1,000 cores, you've already failed. You're not going to get 1,000 truly concurrent things. Beyond the number of cores, it's just an illusion. It's just scheduling. But let's say you did have 1,000 cores. Could you do that? Well, remember, each thread on the JVM takes about a megabyte of RAM. So now you've got an extra gig of RAM you need for your application, just to have those threads. Before you've done one thing, one opcode of anything, one instruction, just to start the application. You need that extra gig. So really, you can see that there's a limit at which pretty soon that you're going to hit where it doesn't become useful to add more threads. At some point, there's a saturation point. Is it your RAM? Maybe. Is it the number of cores you've got? Possibly. And if it's not either of those, then you will just have the problems with your scheduler. You're just not going to be able to move from user space down to the operating system where the scheduling is done and then back into user space fast enough to simulate a 1,000 concurrent thing per second. It's just not going to happen. OK. Well, how do we fix this? I work for a cloud computing company. So the obvious answer is that you should buy more application instances and scale horizontally and pay my salary. Obviously. If you've done the right thing and you've been scaling out your applications using 12 factor sort of style microservices and all that, then your applications are as ready for that scale out as possible. But it's a little glib to say that that's the only way, right? It certainly, there's got to be some way to be a little bit more efficient here. It should be possible in 2019 to handle 10,000 concurrent requests on the same machine. And this is not a new idea. But I use that very specific number because that's a famously hard number to get to. It's a C10K benchmark, right? How do I handle 10,000 concurrent requests? One way to do that is to be more fruitful with how we use our threads. Imagine that instead of sitting here blocking, imagine instead that we ask for the data and then we return execution immediately. And we say to the operating system, look, here's a file descriptor. You manage this file descriptor. When there is data available, let me know. Interrupt, basically. Call back into my code and let me know. But in the meantime, I'll be over here doing something else. And that way I can reuse this thread. I can repurpose this thread. The operating system can manage that pulling of the data of the file descriptor. It can handle thousands and thousands of file descriptors much more readily than we can handle even just 1,000 threads. So if we take advantage of that mechanism, this mechanism that's been built into your operating system for at least 20 years, if we take advantage of that mechanism, we have something very powerful. One way to do that is to use asynchronous IO on the JVM. So here's the asynchronous implementation of that thing I just showed you. Same interface, except that now, a little bit more tedious. We're using Java channels from Java NIO. We're saying, I want to read data into this channel. I'm creating a file channel and reading data into the buffer first to get it started. Then I keep doing this in a loop. And as long as I keep going, this is not going to block. So when I call this, I call this, and I give it the pointer to this. This is a completion handler. And the completion handler is what gets called when there's data finally available. When I get data that's finally available, I take the buffer, I extract the data into a byte array, I put that buffer into the consumer, the original consumer, my consumer, the one that's in that reader interface, and so on. Now, this is asynchronous. This is what we want. And yet, as you can see, it's a whole heck of a lot more complicated, markedly more complicated. And this is, I think, why most of us don't write our code in terms of either the input stream and output stream abstractions or Java NIO channels. We think about the world in terms of higher order abstractions, things like collections, aggregate types like foo, and bar, and customer, and person, and product, and order, and whatever. These aggregate types, like collections in our business domain types, like entities, these things map to our business logic. And we use types that map to our business logic. And if they happen to map to the underlying machine model, that's great. Well, collections don't map to asynchronous IO. They don't serve what we're trying to do here. You can't use asynchronous IO conveniently with a Java collection. So what we need is some way to express this idea of a stream of data, a sequence of data, that will be eventually available. It's not here right now, but maybe in the future, maybe in the next nanosecond, maybe in the next week, maybe in the next year, whatever. So we need that thing, and that hasn't been available in the JDK for the longest of time. So eventually, four different companies, Pivotal, Netflix, the Eclipse Foundation, that's not a company, it's an organization and a fine one at that, but not a company. And of course, LightBend, TypeSafe, all got together and found the common ground in what we're trying to do. We extracted out these very simple types into something called the reactive streams specification, four very simple types. The first and foremost of which is a publisher. A publisher is a thing that publishes data to subscribers. Subscribers consume the data on the onNext method. When there is an error, the onError method gets called. And finally, when it's done processing the data, the onComplete method is called. I kind of glided over this because I want to make sure we come back and focus on this. If I, as a subscriber, subscribe to a publisher, I want to make sure I have some way to signal to the publisher, hey, slow down. I can't handle too much data. Remember, with the first example, that synchronous blocking IO, you're never going to have more data in memory than what you have in the body of that while loop. You can't overwhelm yourself because you're reading 104 bytes at a time. And then you block, you process the data, and then you go back into the while loop again. You're never going to have, in a single foul soup, you're never going to have more than 104 bytes at a time, or whatever the size of the buffer is for you. But with the asynchronous IO, who knows? You're going to just keep asking for data. And who knows if it's all going to come at the same time, or staggered out over the next year. So this subscription object is very important. The subscription gives you the ability to say, I only want n more records. I want to stagger the rate of consumption. I want to stagger how much data I am given from the publisher. This is called flow control. And if you've ever done network programming in university or something like that, you've had to think about this. In the reactive world, where everything old is new again, in the reactive world, we call flow control a basic concept of any kind of network programming. We call that back pressure. That's just a fancy marketing term for flow control. All we're doing is surfacing at the API level this very simple concept that between two disparate sources and sinks of data, there might be one that is going to go faster than the other. And that might overwhelm the other. So you need to have some way to mediate that conduction of data. And if we want to cancel the flow, we can do that as well with this. So I said that there are four types in the reactive stream specification. The fourth one is called a processor. A processor is a bridge. It's a source and a sink. That's it. If you understand those four types, if you understand the publisher, subscriber, subscription, and processor, congratulations. You're certified reactive. You can start a startup in Silicon Valley, get millions of dollars in funding, and blow it all and whatever they do. Now, we understand these basic types. These types are so ubiquitous, so natural, so obviously useful that they have since been baked into the JDK. They're now part of Java 9 and later. So you can say, I want to go to Java Util concurrent flow here and there. This is a nested type. So Java Util concurrent flow dot processor, flow dot subscription, flow dot subscriber, and flow dot publisher. So now they're in the JDK as well. Now these are very basic types. These give us the ability to describe asynchronous streams of data, but they don't really let us operate on those streams of data. We have no operators, things like flat map and filter and these things with which we become accustomed when we deal with the Java 8 Streams API. So we need those kinds of operators. So different projects provide their own operators. Pivotal's Reactor and Netflix's RxJava both provide operators above and beyond these very simple types, compatible with these types, but above and beyond them. And so we are using Reactor in our application here. Here's our application. I'm going to create a publisher. It's called a flux. It's a Reactor stream of data. It's a publisher that is infinite, potentially. It's 0 to n. It could be 1, 2, 3, or a trillion, or infinite. A flux is a stream of data, but it's a publisher on which I can do things like map and flat map. So now I've got a publisher of data called Profiles. And what I want to do is I want to first delete everything in the database to clean up the database in case. I'm going to say delete all. Then I'm going to say I want to write all the data to the database. And then finally, I'm going to say profile repository.findall. And finally, when I'm done with that, when I'm done constructing my publisher pipeline, I'm going to call subscribe. And the subscribe method is how I activate the pipeline. Unless I subscribe, what I have is inert. It's static. It's like a Java 8 Stream. You have to have a terminal condition, a terminal function for each. So I need to subscribe. And the way you do that is you provide, if you're using the reactive stream specification, you use a subscriber. And those have those methods that I showed you. Subscribe for on next, on error, on complete. There are some nice convenient overloads that come from Reactor, though, including Consumer. So here, I can say profile, profile. Or better yet, I can just say system out print line. Or better yet, I can use Lumbock and say log for J, turn that into lambda, turn that into a method reference, and actually just turn that into Lumbock. Ah, much better. So we started with the worst possible code. And we ended up with the worst possible code minus 1. So there we go. Let's run this and see what we get. Oh, dear. Now, I wish that this was a little bit slower so that I'd have more time to drink water. You notice that it took 1.656 seconds on my machine, which is a bit of a bummer. You can actually make that faster. And I think this blog is kind of interesting. It's called How Fast is Spring. And there's some things you can do that make it even faster if you want that are, I think, worth exploring. Distraction free mode. OK. I'm just going to add these to the VM options here. I've just added no verify. And xx tiered stop at level equals 1. Sorry? Period. Awkward. Thank you. Good. So let's see if that gives us any kind of benefit. So what was that before? That was 1.65. OK. 1.3. So there we go. We saved 0.3 seconds, which makes me feel better. But now my water problem is worse. So anyway, we've got now data in the database. So what I'm going to do is I'm going to build a REST API to serve this data up and to manipulate it. So let's do that. We're going to build a REST controller, profile, REST controller. And we're going to support three different endpoints. We're going to support GET profiles. We're going to support GET profiles by its ID. And we're going to support POST profiles. OK. So that Matt has something with which to drive the creation and reading of data. So I'm going to say get mapping. I'm going to inject. Actually, before I bother building the web stuff, I'm going to build a service that allows me to sort of insulate my low-level persistence logic and handle coarser-grained business logic at a service level. So I'm going to create a profile service. And I'll make this a service bean. I'm going to inject the profile repository. OK. Enter. And I'm just going to create some methods that support my use cases here. So a mono of profile by ID, string ID. OK, we're going to come back to that in a second. We're going to have a flux of profile. Now a mono is a publisher that produces 0 or 1 records. A flux produces 0 to n records. So these two are actually fairly straightforward. I can just do find all. Good. And we can say this, that profile repository that find by ID, ID. All right, so there's that. And we need a third one which is to support creating the data. So a mono of profile, create. Create string email. Return this, profile repository that save new profile, null for the ID, passing in the email. Now when this gets created, I want to publish an event so that other parts of my application can see the new state change, so that it can see that there is a new record in the database. And this could support a whole, you can imagine, all sorts of different use cases, status notifications, logging, monitoring. And also, things like event sourcing and CQRS. This is pretty interesting in that respect as well. So I'm going to create an event to communicate with other components in the same JVM that there's been something that has happened. Profile created event extends application event. And I'm just going to create a constructor. And it's going to take a profile created event. And I'll pass out of my source. So in order for this to work, I'm going to say whenever there's a successful save, I want to now publish an event. In order to do that, it's an application context event. So in order to do that, I need an application event publisher. I'm going to inject that into the constructor here. That's actually, if you put a break point, you'll find that this is actually typically a reference to an implementation of the spring application context. So publisher.publishEvent, new profile created event, passing in profile. Go type system. All right. So there's my, there's that. There's the find by ID, all and create methods. OK, always in terms of publishers. And I'm going to use that here when I build the rest endpoint. I'm going to say get, I'm going to root this whole endpoint. The whole resource will be rooted at forward slash profiles. And then for a single one, it'll be by ID path. It'll just be for all of them, rather. It'll be a very straight pass through to the service. So I say return this.service.all, publisherEvent. It doesn't matter. Inject that. And I want to have a endpoint that supports finding data by its ID. So it'll be a profile by ID path variable string ID at get mapping ID. So I'm creating a relative path. It's forward slash profiles, forward slash ID. This.service.byID passing in ID. There's this. And then finally, we want one that supports creating data. So I'm going to have a post endpoint. And this will be a publisher of response entity of profile. And somebody can post to this endpoint a JSON structure. That's the request body. And it'll be a profile that's going to be coming in the incoming request. And we're going to use that. We're going to say return a response entity dot created, uri.create profiles, profile.get ID. Oh, sorry. And then we have to actually call.save. So it'll be this.service.createprofile.getemail.map profile, and we are.build. So what I'm doing is I'm saying, when a request comes in to save a record, call.create on the service, take the resulting saved profile here, take that, and then use that to send a response back saying it should be status 201. It's been created. And also send the location. That's good restful practice. Whenever you post data to a restful endpoint, you should return a location header that shows where the new resource can be found. That's what I'm doing here. I'm using just a very simple static method in the response entity to do that. So now that should work. Let's see if that works. Let's just see if our rest endpoint is working as expected at this point. So we know that we've got at least four endpoints there. So localhost, 8080, forward slash profiles. That should support the get use case. There's four. Now I'm going to post some data. And by the way, let's do the by ID as well before I move on. There we go. That works. I get a single record by its ID as well. Now curl minus h content hyphen type application minus d, quote, quote, curly bracket, curly bracket, quote, quote, quote, Jason. And foo, HTTP, localhost, 8080, forward slash profiles. Everybody got that? And there it is. There's the new one. Email is equal to foo. So we've got the rest endpoint. We've got a reactive rest endpoint. At no point in anywhere in this request chain am I blocking? Every byte that's being sent back and forth so far is using, ultimately, it's using that asynchronous API I showed you below. So at no point am I sitting there on a thread waiting for something to happen. Now this is, by the way, only applicable for things that are IO bound. You can't rub reactive on something like Bitcoin. It's CPU bound. That wouldn't scale. You're going to still be thread bound in that case. You can't make that better. Fibonacci, password encoding, cryptography, security, password encoding, it's one of those things where, yeah, it's probably not going to be what you want if you're doing that work on the server here. Although, that's kind of interesting because Matt just solved that problem, didn't you? When you use Okta, you're outsourcing the encoding of passwords to somebody else's server. So sure, they're wasting threads, but it's not your thread. That's great. That's a good use case. So anyway, we've got now our rest endpoint. Matt's going to need a service end event endpoint and a web socket endpoint in addition to this. So we've got one way by which we can look at this data. Now, let's look at it in terms of service end events. Now, I have so far just kind of built the service. And what I want now is to have a way to monitor the stream of data. I want to be able to monitor the flow of new data off on the side here. And I've already laid in place some of the machinery required to support that. I'm publishing an event whenever there's a save operation. And so I can now use this. I need to build something that responds to that event and then forwards it on to those who are interested. So I'm going to create a new component here, a little bit of glue code, Profile Created Event Publisher. Because I am nothing if not concise. It's going to be a thing that listens for events. It's an application listener listening for Profile Created Events. And it's also going to be a consumer of flow sinks or flux sinks of Profile Created Events. It's got to implement two different interfaces so that it can be sort of the go-between between two different components later. So the first interface here is on application event. Whenever there's a new event, I want to enqueue it. So I'll create a queue, a blocking queue of type Profile Created Event. And I'll just store that here. So it'll start ejecting things that exceed the queue size until somebody consumes it. It'll start blocking. So here, I'm going to say events.offer Profile Created Event. And then over here, on the other side, I'm going to use an executor, which we'll bend here in a second. I'm going to use this executor. I'm going to say this.executor.execute, new runnable, passing in this runnable. And I'm going to say while true. And then I'm going to perpetually take from that queue, basically. So whenever this is going to get called once, whenever I create a new publisher, it's going to start executing against that queue. And so while that's happening, I'm going to say events.take. I'm going to just pass that into the Profile Created sync. So basically, I'm pulling the queue, which is going to be having things put into it out of in separate threads. And as quickly as I can pull things out of it, I'm then passing it to this sync that I'm being given from a reactor. And we'll see where I get this in a second here. But I have to also note that there's an exception. So I need to either swallow it or just do something with it to reflection utils, re-throw runtime exception. Et voilà. And there we are. So there's my executor. There's my bit of glue code. Now we can use this now in other places. So let's see if we can use it in the server-send-event use case. Class SSE controller. And this is going to be an endpoint that produces server-send events. Now server-send events are a content type. And the browser or any other client that knows about this content type will know to not close the connection as soon as the first results come back. It'll know just to keep the connection open and just let the data stream as long as it can. The benefit is that this is a great way for servers to communicate to clients. It's a unidirectional channel, though. It's server to the client, not the other way around. It is not really a great protocol. It doesn't really, it's not a great application-level protocol, right? You couldn't use this to replace an actual message queue, for example. It doesn't support binary data. I mean, unless you do base64 encoding, there are no headers, you know, and there's no way to do client requests to it. But it happens to be one of those things that's pretty trivial to get going. And most browsers know how to make it work, so we can start with that. It's going to be called SSE Profiles. And what I'm going to do is I'm going to inject the profile created event publisher here. I'm going to create an endpoint here that's going to return a flux of string SSE. And it'll be this.publisher, I'll say private, final flux profile created event. And I'll say this.eventflux equals flux.create this.publisher.share. And what that does is it tells, I'm creating a single instance of this publisher, that I want all clients to have access to. So if I have two clients consuming it, and they're all both connected, they'll both get the same data, basically. It's like a topic in message queue part-offs. I'm telling it to retain the instance of the publisher and then share it, which means to say, let multiple subscribers connect to it. And they can all get the same view of the data. And that publisher, of course, is the one. The reason that I'm using flux.create is because I'm giving it a consumer, and that consumer knows what to do when it's given a flux sync. And that flux sync, what that's doing is it's acting as the source, sorry, the sync for data that's being published, or rather consumed from the blocking queue. So now, all I need to do to make this work, as I say, this.eventflux.map, and I've got a PCE here, a profile created event. I'm going to turn that into a string. Actually, I could probably just do this. I could probably do that, but let's try doing map PCE. And I can show you that you can explicitly control things like marshalling to Jackson. So I'm going to say, given a thing, I'm going to turn it into a JSON string. I'm going to create a method here that just says string JSON from a profile created event. And all I'm going to do is I'm going to say objectMapper.writeValue as a string PCE. And that requires a throwable, an exception, so I can either surround it with tryCatch or use Lumbuck's sneaky throws, which makes life just that much nicer. So JSON PCE. OK, there's my service end event endpoint. Let's see what that looks like. All right, so we've got profiles there, same four. It starts up, it leads everything, it adds four to the database. So we now have four. Now let's read some data. So SSE profiles over here. And then we're going to say curl. I'm going to do the curl to write data. As I'm writing data on the right, you can see the service end event updating on the left. It's an updating stream. I'm not sure if you can, it says foo each time. I'm using the same command over and over. But if I say one foo, you can see it says one foo. That's pretty boring. In between, I mean, it works. That's the benefit of this. Reactive is nothing if not boring. That's the way it should be. There's nothing phenomenal about this. That's the whole point. So that's a, like I said, service end events are a great way to get started to test out the end to end. But really, what we really want is something a little bit more dynamic, maybe web sockets. Actually, if I'm honest, the ideal is something like rsocket, for which Spring Framework 5.2 in 2019 will have inbuilt support, but which you can use already today. And rsocket is a true application framework, an application protocol rather. It supports messaging exchange patterns like request response, request stream, stream in, stream out, and request, or fire and forget, where you just send a request and you forget the response. You don't need the response. True messaging exchange patterns, as opposed to HTTP, which is more will to document protocol. You can ask for document back. That's the sum total of what you can do with HTTP. It's geared for that. So rsocket is great. But maybe as a makeshift sort of integration, we can use web sockets. And that has the added benefit of being something that works very nicely with browser-based clients. So let's do that. Let's use web socket support in Spring Framework 5, building upon the foundations here. But just to state my own curiosity, can I just try that and let's see what happens? Would that work as well? I think it would. I'm just gonna return a publisher of profile-created events as opposed to doing the Jackson, Jason marshaling manually. Let's just restart this. Okay, what do you think? Let's try. Over, under, and whether this works or not. Okay. It does work. Never mind, I should have just done that. I did more work than I should have done. That was already, I was home-free. I don't even need this object mapper. Don't need that here. Don't need this. So that's the sum total of what it means to get service and events working, okay? Now, let's do web sockets. Web sockets are a bit more fun. So here, we're gonna say, we're gonna have a configuration class. It's gonna be a web socket, web socket configuration. And here, you've got three different beans that you need. You need the web socket handler. We'll come back to that in a second. You need the handler mapping. We'll come back to this in a second. And you need the web socket handler adapter. Rolls right off the tongue. Okay, we'll come back. Actually, we can do this one. Thank you, there we go. Now, new simple URL handler mapping. And I'm gonna set a few things. I'm gonna set the order to be 10. I'm gonna set the URL map. I'm gonna tell Spring how to take a handler, a web socket handler, this one, and mount it as a HTTP URL where web socket clients can then find it, right? So I'm connecting the mapping, routing infrastructure in Spring to the web socket machinery in Spring, okay? And so I'm gonna say, here's a URL map. I'm gonna give it a Singleton map with WS profiles as the key, it's just any map, but I don't get one endpoint here. And the value will be the handler, okay? And that's the sum total of that. And now, the handler itself is where things get interesting. This is where we actually do the work of creating a web socket stream that's gonna publish updates about the new profile created events. And so here, you can see the contract is fairly straightforward, right? We're going to create a publisher just like we did before using the application event publisher, the profile created event publisher rather, this one, you know, P, there we go. I'm gonna say profile created event publisher, flux.create, profile created event publisher.share. Just like I did for the server to send events, I'm gonna store that, and this I can put there. And my job now is to say, web socket session dot, oh sorry, it's gonna, I'm gonna say share.map, and I've got a PCE here, and I wanna send that as a, I'm gonna encode this one, so I'll inject the objectmapper here, say objectmapper dot write value as string, PCE, just as before, we place that with this, time exception, and then I'm gonna take that and turn it into a text message, a message to be sent in the web socket. So I'll say JSON, websocket session dot text message, JSON. And so what I have at the end of that is a publisher of web socket message that I can then send using websocket session dot send. So let's clean this up a little bit. This logic here could be extracted out into a method, so I'll do that, I'll say private string, JSON from profile created event PCE, hat sneaky throws, return objectmapper, name it here, private final, objectmapper, I'm gonna say objectmapper dot write value as a string PCE, JSON from, this becomes cleaner, get rid of that, JSON from PCE, method reference, okay that works anyway. And there we go, so that's my web socket code, oh the handler itself of course becomes this, so it's a session, I'm just using web socket session, okay. Good, okay, so that's my entire, that's all the business logic required to set up web sockets, I'm saying get this thing that has the updates that we saw in the service and events, the same stream of updates that are being published whenever something is saved, that same stream I wanna subscribe to it, and then for every new thing that comes in, turn it into a JSON string, turn that into a text message, a web socket message that I can send over web sockets, and then send it, right, we're already straightforward. In order for that to work, my code needs to compile, that's the first and arguably most important step. I need a reference to this bean, profile created event publisher, that's this thing here, I'll extract out the dependency like that, and it compiles now, and I do need a way to test my web socket code, so I'm gonna create a static file here called ws, oh sorry, static, goodbye, directory ws, static, sorry, resources static, and a new file in there called ws.html, and in here, I'm not gonna write the code myself, because I hate it very much. All right, look at that, life is hard enough, life is hard enough when you have a compiler and a type system, this is just, no, no thank you. So what's gonna happen, it's a web socket client, very simple, it's gonna connect to my local host machine on port 880, for such ws, for such profiles, when there's a message, I'm gonna listen for the event and just alert the message, it's the simplest JavaScript client I could get away with while still claiming to have written JavaScript, okay? This is why we have Matt. Alrighty, let's see, local host 8080, ws.html, and we're gonna create some records over here, view developer, JavaScript console, ws profiles, what is the end point that I had here, ws, ready? There we go, message from server, source ID, one foo, et cetera, okay? So we do that again, we get the updates. So now, I can actually take it a little further here, curl, http, localhost, 8080, sse profiles, I guess that doesn't, anyway, there we go. So there's our simple web application. I did, I mean, can we agree I did some JavaScript? I get credit for that, right? Like, technically I didn't just leave it all to him, right? This application speaks web sockets, service and events, it can speak HTML and all that stuff, but it speaks HTTP and REST. It does all of that in Java code in 274 lines of code, which, you know, I'm not really proud of that, but hey, this is the breaks. You clean that up a little bit here, let's see. And I've got this thing here for Matt. Where's that initializer? Here, profile, reset. Okay, so there's a bean here, that far to remove this bean to initialize the sample data, then it drops down to a more healthy 237 lines of code with judicious spacing and so on, and that's Java. So it's Kotlin and Goovy and Scaldet becomes like 150 or something like that, it's just dramatic, you know? And that's the best code that we could get. It speaks to the database as efficiently as we can get, it does all the web service endpoints as efficiently as we can get. Is it production ready? No, there's a few things missing. Obviously security, Matt's gonna talk about that, but then also a little bit of care, a little bit of care is required when it comes to reactive applications and they're ASCII artwork. Now this artwork here, I think is very well done, right? This artwork is the artwork in the Spring Boot application that we have had in Spring Boot for a long time. And I'm a big fan of this artwork. People who know me know that I care about this and so I'm always on a quest to better the lives of people who care about their banners. And it's for this reason that I wanna take a brief moment to talk about what I consider to continuously be a blight on the Java ecosystem, a true offense, something that I consider to be beyond the pale in every sense. Do you see this checkbox? Do you see this one, this one right here, this checkbox, this one, that one, do you see it? That one, that checkbox once clicked suppresses the output of the ASCII artwork. What the hell, why is that there? That's a dumb feature. I don't even know why it's there. And as always, I wanna remind you that I have tried to get this fixed and I did what all people would do in this situation. I went on the internet and I cried and I got a message of hope from Jan Sabron. He's a software developer by passion at JetBrains and he responded with this message of hope. This is Jan right here. This is him, this, that's him right there. Boop, he sent me this message of hope which I will share with you today right now. He tells me all the time, don't worry, Josh. It's gonna be fine, Josh. The next release will surely have the fix that you need. Don't worry, it's gonna be okay. Just wait, just be patient, relax, he says. Every time I talk to him and I'm just not sure. It's very hard for me to believe that he's on the level because I'm not sure that this is gonna come, you know? But hope springs eternal. Anyway, Matt, help us out, buddy. We'll take a... I think we're gonna take a few minutes break, is that true? Hi, brother. Do you want this one? Yeah, careful, it is topsy turvy, it'll slide, so. Make sure you don't let it slide. Yeah. Would you unhinge me? Wanna hook me? Thank you, sir. And then the power one? Oh, is that yours or mine? I mean, that's yours. Power one's mine, yours is in your back. I see a Bruce Snyder in the back. So do you, I'll go check this code in right now into the Git repository. The initializer is what you need, right? Yeah, yeah. Thanks for coming. The best part's still to come, you should stay. Okay, log in, it's online, I think, right? Okay, thanks for coming. Peace, have a good night. Thank you, sir. Reservation is... We have a reservation at day 30. Is Bruce here? Bruce is right there. See, he's got short hair now. There you are. I was like, I thought I saw a ghost in the back. How you been? Oh, buddy, how are you? It's been a long, long time. Oh, here you go. I'm glad I'm here, like... Are you okay? I haven't seen you since before, I was like, I haven't seen you in person. I mean, how are you? I looked you softly. Thank you, Greg. Josh said we did write a 65-page blog post on this, and when we showed that to my editor, she was like, no, that's a little too big for one blog post. So the final series here you can see is 25 pages. I did write that up until four in the morning before I had to present it the next day at spring one, so glad that worked out. But the beauty was that Josh wrote the first two and certainly I helped him and did a bunch of editing on him, but all three series are available on the OctaDeveloper blog, and it starts with the reactive programming in general, and then just using Spring Web Flux. And so Josh, check that project in, right? It's on GitHub, so let's see if he got that initializer in there. Oh, okay, so everyone gets to look at my Twitter. Hope this works out. On some Starbucks, Starbucks man, there we go. So we'll copy the code, IntelliJ, forgot to do it, get ignore, but that's okay. So here's all the code in here, that initializer there, low import, we'll start it up. So I just want to make sure all those end points work, just like Josh showed they did, and we'll go from there. Okay, we started, we're connecting to Mongo, and he did put it in this reset one, right? So we need to adjust and use that. Active profiles is reset, and we'll restart it. Now we should be able to go to, for example, HTTP, 8080 profiles, and we're getting profiles, right? It puts four in there, and then at the same time, we have SSC, it's an event profile. Right, and if we screen that one. He used command, I'm gonna go ahead and create a new script for it. So I go to create a new batch script, and this is doing the same thing, right? It just posts a new profile, so we can go create, this guy here, just 30 seconds, we create it, shows up. Right, and the last thing is making sure those WebSockets work, so we'll go host 8080, WSH2ML, so resources static, WS, there it is, 404 on the save icon. We have all those endpoints working, and now what I'd like to do is create a React app that talks to those endpoints, and I'm gonna use a few different techniques to basically get that streaming data and show it on the UI. So to begin, what I'll do is I'll create a React app in here. So this is a tool called create React app. You can invoke it with MPX create React app, and then we'll call it just React app, because we're fancy on naming. And then I like TypeScript, so you can do dash dash typeScript, and it'll actually create TypeScript for you. So this is like the scariest part of any demo, right? Create create, yep. So the last time I did this, it was on stage at spring one back in September, and it wasn't create React app itself, it was this TypeScript add-on that they had on the time. So only in the last month has TypeScript support been added to create React app. And at that time, for two hours of several years, that script didn't work. It was a minor bug that someone checked in, and it was during my demo. So I had to do the same thing, and then the app didn't create, and I was like, well, I can just show you the code, I can't run it. And so I'm happy to be able to run it today. So you can do MPM start, or you can do Yarn start. Of course, you have to be in the project, so React app and MPM start, and we'll just show you what it looks like. Bare bones. So I have to do some compilation because we're using TypeScript, and you can see it's just a simple file. So I have a full set of instructions here. This is the repo where we store all our code. So we have tonight's code that will show up, but that's obviously gonna be lacking tests and stuff like that. This one has some more tests in there. In the React app branch, it's actually got this demo ADOC, which is a script I wrote, and a bunch of shortcuts. So I can't type as fast as Josh, or it's prolific. So when I do the API part, I kind of just pre-record the code and spit it out. So with the React app part, the reason I show you this is, I don't memorize all the steps. So it's nice to look and see if I missed something and that's why I do it. So we'll go ahead and open this up in IntelliJ script here. The first thing we're gonna do, we're gonna modify the app.tsx to make a request to the server and actually grab those profiles. We can actually add a component did mount. This is how React works. So in the component did mount gets called when you actually initialize the object. So we'll do that again. You can see we make a request to localhost 3000 for profiles. And then we set it to local data and we actually set loading as false. So then we also need to create some interfaces. So we'll create a profile interface and this one will have an ID that's a number. It'll have a email that's a string. And then we'll also have a app props. So another interface called app props. That's just empty for now. And then an interface called app state. This holds the state for the things that can change in a React app, right? This is where you hold your state of your application. So this will have an is loading. And that's a Boolean. And then we'll have those profiles and that's gonna be an array. So TypeScript looks a lot like Java, right? The only real difference is they define the actual variable and then the type, right? You see that in a lot of other languages. Java's one of the few that has the type and then the variable. And then once you do that, you can put these on the component. So you can say this is app props and app state instructor that takes those in, sets the profiles in the state to nothing and is loading to false. So now we have the component did mount. We'll get called. It'll make that call to the server side. And we're gonna wanna actually list the data that comes back. So things, so it's still loading. It's just gonna return that it's loading. That should do it. So everything looks good. We can start it up here. PM start. Who thinks it's gonna work? We got one that thinks it's gonna work. Why is it not gonna work? So the reason it's not gonna work is right here. Our server is running on 8080. Client's running on 3000. Like gonna be a 404. So to make it work, you can go to the server and set cross origin resource sharing. So it says, hey, you can talk to me from 3000 and then you change this to 8080. But I found it easier a lot, especially when you're just getting started to have proxy, local host, any requests that it doesn't recognize to its own files, it'll send to the server. Now we can do the MPM start. Okay, and we're getting those variables from the server, right? We got A, B, C, D, we got the few that we entered, those random ones. If we went back to our server and we restarted it, then it should clear out those ones that we sent in there or refresh that before. So I'm gonna make this into a profile list. So I'm just gonna copy the file and I'm gonna actually change it to a component. So this is one of the things I really like about React. Like the first time I did this, I was like, oh, that was kind of intuitive and kind of easy. So let me show you. I'm gonna go ahead and change every instance of app to profile list. So that one, that's cause we're just rendering the actual component, right? So take that out, take that out to the top, the SS file in there, okay? So now we have basically a component that's self-encapsulated, right? It just handles fetching that data. And we can go back to the app one and basically undo everything. And then all you have to do is profile list, right? So that's how you embed one component and another with React works out pretty well. So now we can go to our profile list and say, okay, let's start with the first type of data fetching. And that is going to be intervals. So if you're familiar with JavaScript, you might be familiar with set time out and the ability to do things on intervals. So this is the most primitive way I could think of. So you see here, it does a component did mount and it goes and fetches this data. So it does a similar thing, uses a fetch, which is a standard part of browsers now. And it goes and grabs those profiles and then basically every second, it will go and call that method again. So it's getting all the data each time, right? So first of all, it's not very efficient. So up here, we'll define an interval variable, just make it a type any. So we have that and then we have in our list. And you can see it's kind of janky, right? It's actually refreshing that whole page. So one of the things I want to do is I want to create a stream. Instead of just that create.sh, I'll create a create stream. So we can have more data coming in. You can see, so this just does a loop up to 120 seconds and every second it enters a new record. So we go over here and create stream. Then it starts adding those and you start seeing them but it's fishing the whole list, right? So that's not very efficient. The next method is going to be using RxJS. So RxJS is a nice library for doing reactive stuff on the client. You can install it with RxJS, MPM install RxJS. Then we'll go back to our profile list and we'll say, okay, instead of this guy, use RxJS. So it's got the same variable name but as soon as that installs, then it'll resolve those imports. So a little waiting. Any questions at this point? Anyone using React? Okay, we got about 10. How many people using Angular? It's about the same. So we have this debate in my company, right? We're talking about enterprise developers. What do enterprise developers use? Obviously, we know they use Java. We know they use .NET. Maybe not so much Node, right? Like Java and .NET are kind of on the top. And then what about Angular versus React? People on my team think Angular. I'm like, Angular, yes. But I think React's in there too. So show of hands again. How many people using Angular? Say 15. How many people using React? Yeah, it's the same. So I'm gonna go back and tell those guys. I just told them on the camera right there, right? React is enterprise, all right. All right, so now we have RxJS installed. These imports should resolve here. Close that guy down. Indexing. There we go. Import those. Those are all from RxJS. You can see them up here at the top. Save it. MPM start again. We'll come back to the same browser window. I mean, it's nice to have that loading in there, right? Or you don't even know what's going on. So this is interesting. You always restart, right? Number one thing you need to know if you wanna be in support, just reboot. And when you talk to that guy, you're like, really? I know that. I already did that. RxJS types. I'm sure that it doesn't find it for React. I did do type React. I mean, it's similar to my failed demo at spring one, right? But it totally was working up until that point. It's weird that RxJS killed it. This doesn't work. I'm just gonna remove RxJS and we'll go back, right? So it added two packages, which is strange. Even though MPM install should have done that. Okay, so there we are. Just MPM install, fix it every time, right? So now it's adding it, but you notice it's less janky, right? It's smooth. It's still grabbing all those records and it's still bringing everything back. And so it's still not quite as performing as we'd like it to be. So I'm gonna go ahead and restart the server so there's not as many records in there. And if we go back to the script, the next two things are web sockets. We like web sockets, so if we go here and change this component did mount, you'll see what we're doing here is we're hitting localhost 3000 profiles the first time. We wanna grab all those records and then every time a new record is added, we're just going to that 3000 WS profiles and grabbing that one record, right? And then we'll parse that JSON out of there and we'll push it to the profile. So it's much more efficient. We're just grabbing that one instead of refreshing all of them at once. So the one thing that will happen here, I won't show you, I'll just fix it already, is there's a set up proxy file that you have to create for web sockets or web sockets aren't proxy. But that's what that looks like. It uses HTTP proxy middleware and actually proxies that WS on 3000 to the 8080 there and says, you know, web sockets are true. Then we go back here, it's still running and we should be able to reload. But we gotta restart it because we created that set up proxy script. Okay, create a stream. The proxy, you can do it. It's okay in here. Oh, it's there now. We'll debugging on stage is always fun. Oh, it doesn't like the non-unique keys. Come on, I'm gonna do that before. It's all about those unique keys. So there's a duplicate ID in there. So I gotta restart it on the server. Actually, I haven't seen that before, so at least I know it exists now. What's that? It is a warning, but it's also not grabbing those web sockets. Skip that one. Let me look real quick here. Profile ID, not that much. Let's move on. The last one is event source. So with event source, just like Josh had that service end event, you can actually do react service end event, which is what? So there is in JavaScript this event source object, right? It's native to your browser and you can go to those profiles and get them and do the same thing we did with web sockets basically. So we'll start, it should be running still. Let's see if this one works. So on the server, you'll notice I wasn't able to get event source working over a proxy, right? So that was the problem where I first started this and that's why it's very important to have this event source on open method I found because I was seeing this in my console log is saying, hey, I'm making the connection, but then on message would never happen. And so this was one of those two hours of doing the same thing over and over again, right? And not getting any different results and being like, why? And then realizing, oh, it's on the server side. So in this service end event controller, if you add actually on the method, just get mapping here, you can add cross origin. And if you want to be more secure, you specify the origins and we'll specify local host 3000. So it's a bit more secure. And then if we restart that, this time it'll work. Just A, B, and C. So that's all working. The next thing I want to do, stop that first of all, is add authentication with Okta. So I think this is important because this really highlights that there is some inefficiencies with web sockets in the sense that they're more difficult to secure than just HTTP. So I'm going to start on the server side and the server side has a maven palm, right? And I think when we originally created this it might not, or it did have Okta in there. So we'll go here. This is the eight o'clock lights off kind of thing. We've had that a few times before. Remember, DeVita? DeVita, the lights will go off and the screens will go up. And it was like, where's the music? Like if only we had music, we would know. Right? So I added that Okta starter back in there and then I'm going to refactor this to be YAML. Just because I like lines of code. And then my shortcut is Okta. And so you can see here, if you do Spring Security that one is application. They have many more lines of code. So almost 20 lines of code to configure OIDC and with our starter it's much easier. But that's really all we do. We're a thin wrapper on top of Spring Security and they're all support. The only thing we do is we simplify the properties and we automatically map. If you have a group's claim, if you have your users in a group on Okta and you specify that in your ID token, then those will actually get mapped to Spring Security authorities. So that all happens automatically for you. So if I was just to do those things, all I have is a starter in the palm and I have properties here and I restart. It'll actually require authentication now. It'll require me to log in to get to any endpoint. So if I were to go to localhost8080 profiles, happened so fast you didn't even see the redirect. This time it redirected me. The first time, it does happen pretty fast. So people always complain about, hey, this third party provider and I have to go and redirect to him, you didn't even see the URL change. So it doesn't always happen that slow. So I can log in if I can remember my password and now I can see there is no home page. So you get a 404. This is one of those things in Spring Boot that people are like, is it working or not, right? Because we have no home page so there's no thing but if we do profiles, then it'll work. So that proves that the server site is working. But the problem is that if we were to hit it from the client now, it would redirect us, right? And the client would get a redirect and it would be like what? So we actually have to turn this server into a resource server. They call it no off terms. And what that does is it allows us to have basically a access token that we send into the server and then that grants us access and authenticates us to Spring Security and all that. So I'm gonna create a security configuration class. And so you'll see here, we have enable led flux and enable reactive method security. We are turning on or making CSRF so it's actually, I'm using the wrong shortcut here. Hold on, because it doesn't have everything in here. Shortcut is SS configuration. There we go. And it's formatted better. It's in package statement. So this, different from Spring Security of using MVC, you usually extend Web Security adapter. Here you just have a beam that's a security filter change with led flux. So the reason I'm saying with HTTP only false on CSRF is so in a normal React application you're gonna wanna have CSRF on. And so by doing this, it allows the CSRF to be sent in a cookie that the JavaScript can read. By default, it will send it in a cookie that the JavaScript cannot read so it can't actually send that CSRF token back. So you'll wanna send it so it can read it and then in the React application you'll actually have to take that CSRF token, put it in a header and send it back. So you read it from the cookie, put it in a header, you send it back and then everything with Spring Security works as far as their security mechanism. Just WS Star, you'll notice that's our Web Sockets endpoint. I am not securing that because it is not possible to secure Web Sockets with Web Flux in Spring Security. It's not implemented. They would love to, they don't have the bandwidth. If you use in Spring MVC and Web Sockets you can secure their endpoints. They do have a way to do that with Stomp but if you're doing Web Flux, you don't. So I'm gonna show you a workaround here. Basically what I'm gonna do is instead of going and grabbing that single or sending the whole object from the profile on the server in the Web Sockets, I'm gonna just send the ID. Which I think is, you know, it's kind of a grid, like it's not that big of a security thing so once I have that ID then I'll go back to the server and I'll get just that object. So it's a little chattier. This OAuth2 login, what that does is still if I hit the 8080 endpoint, it'll make me login. If I didn't have it in there and I just had this OAuth2 resource server in there, what would happen is I'd just get an error that says you're not authenticated. So I kind of like the two-way street where I can say, hey, my API is protected but you could login and see it if you had the information or you had the credentials but if you send us an access token and you enable the resource server, that'll work too. And then, what's that? Right, so ours was piggybacked on those. So everything that I'm doing today, you can do with Spring Security with twice as amount of the number of lines of code. That's it, right? So they're dependencies, they have like three or four dependencies to do the client login and the resource server. And then there's Jose for Jots. So that's four dependencies or you can use R1. And then like I showed in the application YAML file, you can use 20 lines of code because it's YAML or you can use five because R is simpler. So I'm pretty sure R's would work with anything but with Kiko or any other server, I just haven't tried it. So then we also set up cores, so this allows us to get rid of that proxy, right? We're not worried about that proxy anymore because we're eventually gonna deploy these on different servers, but we want the server to be locked down, we want the client to send that access token. So this is something you have to do once you do Spring Security. So those cross origin annotations, when you're not using Spring Security, work great. As soon as you add Spring Security to the mix, you're gonna need one of these guys that configures cores. So just so you know that. So now I can restart that server. And then on the client, I mean it's getting close to time, right? So if you've always wanted to do this, thought it'd be fun, see if it works. Release a project on stage. So I wrote this blog post today about using Angular Schematics to simplify your life. So what you can do with Schematics, you can create a brand new Angular project and you can run one command, that octa to it. Very proud of this. Because I used to struggle on stage, right? Because you know what I had to do? Seven steps. Now I can do it with one. So what I did yesterday is I made a work with React. So here's the pull request. Merge that. Delete the branch, there's no going back now. Dev octa schematics. Get checkout master. Get pull. That would have sucked if I forgot that part. All right, and then you gotta change the version. So we'll do zero dot six. Not gonna do the release notes till tomorrow though. Zero dot six dot zero release. Get push, origin master. Well it hasn't worked yet, it's just published, right? So hey, I released some software on stage. Now what we can do, go back to our steps. I did update these steps. So all you have to do now is run npm install on the project. So we're an intelligent, close this guy out. Right here, npm install octa dev schematics. It should get the latest one. Maybe I could have done it faster because it does take a little while to do npm install. And then there's this command. Schematics octa dev schematics add off. So run that. And it prompts me, what's my OIDC apps issue or URL? So I got that right here. I an ID, got that right here. And it goes and adds the dependencies I need. It creates two files for me. Updates my package.json and it updates my app.tsx to have what I need in there. That's kinda cool. Now if we look at app.tsx, it has this configuration. It's got an off interface that has login, logout. You can check if the user's authenticated. And then if you go to the home, this is basically the landing page. Since that app.tsx is no longer the landing page, we have to go to a different one. This basically checks all the authentication and then it has a login and logout button. So we can just add the profile list. And we're also gonna wanna add, we're gonna wanna pass the off down. So this props will pass down to the next component. And then we have to go here and say, off is off and we import that from the app. Now everything should work except if we try it, maybe it's still running. I don't trust that, like npm start. So now it's got a login button. Takes us to our server, we're already logged in. So it comes back and we still have the event source stuff in there, right? And you'll notice down here in the bottom, it says 401 unauthorized. So we need to pass that access token and now we can go to profile list and we'll just take this one out and we'll start with react token. So this goes to 8080 profiles and you'll see it passes in an authorization header that it gets from our react SDK. So we pass in that off, it gets access token from there and then it should all work. Oh come on, you wanna work, try incognito. Whenever you're working with authentication, incognito can be your friend. So we don't want localhost 8080, we want 3000, log in, it'll make us log in. Still not working. It says 3000 isn't allowed on my cores, but we did create this guy here. I think it's in the wrong directory, right? This is not in the main one. All right, so now awkward. And that's because Spring Boot does a component scan by default so it'll look in the same directory as that profiles application. At least that's what my hope is here. There we go. All right, so you restart a few things a few times and it works. So the last thing I wanna do is take this web socket and change this from instead of sending the whole thing, right, we'll just send the profile. So profile, profile, or the ID. We'll do PCE, get source and we'll just say data put and we'll put an ID in there. Profile.id, send that back instead. And then we'll go back to our client. The web socket didn't work last time, but maybe they will this time. So again, it's gonna go to use that bare token. It's gonna go get all the profiles and then it'll go get just the ones that are sent. And when it gets that message, it'll parse it. It'll grab the ID and it'll send that ID with those headers and grab that object from there. So let's get our stream going here. First of all, back to our client on stream CSRF token. That's because we're actually not passing in anything to the client. So we're not passing in an access token, right? It's not gonna actually be able to create anything. So create stream auth, I have a shortcut here and I'm passing in an access token. So if I go to OIDC debugger, I can create an access token. I'm just gonna set the state to that. In access token, copy it, put it right here. Now the stream should be able to send those to the server and it's creating them. What about our client? Come on, client, profiles undefined. Not getting that message back, okay. I'm not gonna need to debug it too long, but the one out there does work, right? So if you want the source code that works, I mean, I can sit here and debug it and put some console log messages in there, but it worked the last time I did it. And there's also a screencast online that shows everything from soup to nuts what we did here. And yeah, I think that was all I had. It was cool that I got to release it and that actually worked to install it with React. It does work for Vue as well. So I'll write up the release notes for that tomorrow. It's called Schematics. It's in a GitHub repo and it's basically Schematics is a way of manipulating a project that you would create with Angular usually, but React also works. At this point, I think 8.20, our reservation's at 8.30. Well, we lose it at 8.30. We lose it at 8.30. So, any questions? Keep them short. We do have t-shirts though. So I'll reward you if you have a question. If you don't then, you know, we'll just... So no questions, oh we got one. No, so we have a Spring Boot starter that works with, the question was, is there a particular version of Spring Boot that you need to work with Okta? And the answer is if you use in Spring Boot 1.5 we have a starter for that. If you use in Spring Boot 2.0 we have a starter for that. 2.1 we have a starter for that. So you just need to match up with our versions. If you have questions about that, ping me on Twitter or whatever and I can help you up.