 Hello, developers. My name is Matt Raible. Today, I'd like to show you how to create a spring boot and react crud app using spring boot three and the latest version of react, which is 18. So let's get it up. This screencast is based on a blog post that we published back in June of 2022. And you can see here it's used to react react and spring boot to create a simple crud app. I did update it recently. So it's using the latest spring boot three. And if you click on the code repo here, it will have a demo script at demo dot adoc adoc for ASCII doc. And if I click on the raw version, I can see a nicely formatted screen that kind of has the instructions to create everything. So the blog post has all the details. If you want to read through that, it's got the same code in it. All I did with this demo script is condensed it so it'd be easier to create this screencast. So we're going to use a lot to an open ID connect to secure things after we get it all working. And then I'll show you how to package it all in the same artifact so you could ship it to production. And you can also still use the productive workflow that you're used to with react where you just do npm start and everything's running. You can change code and you know it refreshes automatically. So you can see on the prerequisites there we have Java 17 node 16 and octa CLI. You'll also need the OZ zero CLI if you want to use OZ zero portion. So I will go through the OZ zero portion and then I'll show you how to do octa portion as well. So the brackets at the end of some of the steps indicate the intelligent live templates that I will use. So you can find the template definitions at mrable idea live templates. You can see I just updated those recently. And we'll start with creating an API app with Spring Boot. So we'll navigate to start that spring that I'll And put that on the right there. And they recently changed the default to cradle. So when I originally wrote the tutorial I use Maven so select Maven Java Spring Boot three zero zero there and then calm to octa developer. And then the artifact is jug tours. And the dependencies are JPA and H2. And web. And Lombok. Okay so we have all those and now we can click generate. And then open that up expand it and then we'll open up a terminal window and open it up in IntelliJ. But tell you on the right there and we'll start with creating a JPA domain model. So we're going to create a model directory right here. Our model package. Right. But we can we can actually do it as a Java class and do model and call it group. And then I have those IntelliJ shortcuts I talked about live templates. So here's the group class. It's got an ID and name and address the city state or province and country and you might be wondering what are we developing. So I'm developing a jug tours application. Jug stands for Java user group. And I like to do these Java user group tours where I go to somewhere like Ireland and I hit a few cities and speak at each city. And it's just a lot of fun to get to know the Java community in the U.S. I plan on doing a couple this year but it might just be you know fly out in back because doing a tour in the U.S. Well they're far away from each other. And it's not like Ireland where you can take a train between cities very easily unless you maybe go to the East Coast. So we have a group just to designate our Java user group. And then an event would be you know Matt is speaking on Wednesday or whatnot. So I'll go ahead and create a new event class. And then again SBR event is the shortcut after that. And so you can see it's got a date title description and then attendees and then we can create a user for those attendees. And so now if we go back to group everything looks good. Everything's compiling. And now we can create a group repository. We'll create some default data by creating an initializer class or just part of spelling it. And what this does get a clear picture of it is it implements command line runner uses that group repository and it just goes ahead and creates some sample data and inserts it into the database. So when I first wrote this presentation I was planning on speaking at the Seattle jug the Denver jug the Dublin jug and the London jug. And I'm happy to say that I've spoken at all of those since I wrote the post except the Denver jug but I will be speaking there in February. So you know kind of hit them all. And then we'll start the app and you could start it right here with you know IntelliJ. And we should see that data loading up and you'll notice that it does warn us that we need annotation processing for Lombok. So we'll go ahead and enable that you will need the Lombok plugin. If you don't have the Lombok plugin installed it will actually probably fail to compile. You know these classes so you can see it printed out everything so it's proving that that initializer is working and so we can stop that we don't need it anymore. And then if we create a group controller class in the web package this will allow us to crud groups. Take a closer look at it. First of all there's a Jakarta is part of Spring Boot 3. It used to be Javax right for Java EE I think 8 but 9 switched to Jakarta Jakarta EE now. So we do need to add a dependency in order to get things to compile if you go down to like right here and IntelliJ has some nice code completion. So we can do Spring Boot Starter validation and then it'll complete that for us. And now if we go back to our class you'll see now it's trying to compile. Well usually there's a there's a Maven thing here that says hey refresh Maven so let's go back and see if it's there. Now you got to go over here and be like hey reload it. Now if we go back to our class everything compiles. So it's just a group repository or group controller here takes in that group repository does a find all for the groups you know to get a group it does find by ID. And all of those methods are created for us by that JPA repository that the group repository extends from and then to create a group pretty simple and then update one similarly and deleting it. So all pretty boilerplate so far and then we can restart our app and hit that groups endpoint so I'll go ahead and just use Maven this time show you that that's possible too. And then I can use HTTP IE which has an HTTP command to do HTTP 8080 API groups. You can see all those groups are returned. So that's working well. And now we could post a new group using a command like this. I'd love to go to the Salt Lake City Java user group because well it's winter time and they have excellent skiing there. And then you could you know make sure and that that worked with API group by yep. And then you could you know update it to say I'm on the slopes. That's the address. So that's there now. And then of course you could delete it and not delete it. You know our API is all working as far as just you know crudding groups in a sense. So now we can create a react app to be the front end for this. So I'm going to use create react app for that MPX create react app and you don't need the at five. But here's the thing there's going to be a new version of create react app at some point and it might not work with this screencast. But if you use this version I can pretty much guarantee that it will. So please use the version because then everything will work. And I did want to point out in this demo script just to scroll up a bit that you know I have all these shortcuts with IntelliJ live templates. But if you expand this it has the actual code in here. So if you want to do the tutorial yourself you should be able to use this demo script and not actually you know use my shortcut. So it's a it's a nice way to just you know see things working. Of course you can also clone the repo and just follow instructions in the read me to get everything working as well. So just expand the project there so we can kind of see what's created created an app directory here. It's got our default source from create react app in there. And if we were to look at package.json you can see it's using react 18.2. So we can CD into that app and we can install bootstrap five react cookie four. Reactor out or six and react strap. These are all the latest versions but like I said I put the versions on there because in the future there's a chance that they wouldn't work with with the new version of reactor. And then in index.js you'll want to add a path to that bootstrap import bootstrap. And then we can call our spring boot API and display the results. So modify app.js to do that. And what this does is it has groups and set groups it sets the state for those and then it uses this effect here to set loading to true fetches those groups and then sets those groups as appropriate. And you know if it's loading it says loading and then just list them out. So now make sure the spring boot app is running it is so we can do MPM start. Ah there's one thing I forgot to do. I forgot to proxy from any requests that aren't going to the react app to the back end so we can add a proxy thing right here. So those requests to API groups will actually go to localhost 8080 now and might need to restart for that since it's package.json. Now it's all working. So that was in my instructions here. I just you know got a little greedy little eager. So make sure you know that's all running and you should see that default list of groups. And so now react is all about components and we don't really want to render everything in our you know main app.js. So let's create a group list and then populate it with similar code that we already have in this you know main app.js here so called group list. You can see it's very similar it's got the group and set groups and the loading calls that API groups and then it also has a new methods for deleting groups and you know it basically formats everything nicely. So it looks good and then adds a couple of buttons to edit or delete them and then puts it on the table. We also need a navbar to make things look better. So this is app navbar.js and this has a link to the home and it's got this is open set is open that's you know using an effect to determine the state of the toggling the navbar and you know showing these things. And so most times and in this demo you might not even see that toggle because it's basically meant to be responsive. So if we squish the screen down you don't want to show things on top overlapping each other on a small screen so it turns into a toggle. So hopefully I'll remember to show that to you and then we'll create a home as well. And so this just links to managing your job tour and then we'll change the app.js to use react router to navigate between components. You see it defaults to the home element and then if you click on groups it'll go to that group list we can just create it and then to make the UI a bit more spacious add a top margin to bootstraps container class here. And now everything should be updated right here so you can see we do have that toggle right but if we made this screen bigger. Then it would show those items in there so then we can manage our job tour we could see well edit doesn't work because we haven't created that group edit component yet but this is all working and looks good. And so now we'll add a react group edit component and this has an initial form state of you know blank items so basically if you want to create something new it would default to nothing in there and if you want to you know set the defaults for some reason you could. And then for group and set group it uses that effect there and then navigation it uses the navigate and grabs the ID if it is in the parameters. And then if the ID is in there it you know doesn't fetch anything or does fetch it and if it isn't in there and it's you know defaults to new then it goes ahead and doesn't grab it and then if any changes happen when you click submit it sets that group. And then handles to submit and you know fetches basically going to that endpoint that we set up for put versus post and if the ID is already there it does a put because it's just updating it and if it's not it does a post because we want to create a new one and then it sets the headers and sets the body to it we have as a group. And then down here we have that app now bar and of course the title changes on whether we're editing or creating a new one and then we have the form groups for the various input elements and then there's some CSS here for you know specifying the rows and some things I did to make you know the elements look good on the screen. And then the submit button will save it and you can also cancel. So now if we go back we should be able to edit these groups. Oh not yet. Maybe I need to restart it. Oh we didn't add it in the beginning man read your instructions Matt. So we need to add a new mapping for it. To react router and we don't have exact true here but you know good enough and then. Edit import it. And now it should work so you can see we can add that or modify that Seattle jug and that's in Seattle obviously if we save that then it shows up there. We could also add a new one for instance garden state jug which I hope to speak at in 2023 now it's there so that's all working and now we can add authentication with us zero. And this is just using an open ID connects so even though I'm saying like us zero it should work with any identity provider so first thing you need to do is modify the palm dot XML to have the spring security dependencies. One thing I did want to mention is that you might normally be like you know I want to actually have my react app you know do the authentication and send the access token to the back end. Well not really a great reason for that actually doing the authentication on the back end is more secure so that's why I recommend this way and you know if you want to use the CDN to pull in the front end artifacts you certainly could. If you want to host them on a different server then that's when you would need to do that pattern where you do the authentication on the front end and you communicate you know to the back end but that's only necessary if you have like different domains for the apps but. The what I'm showing you here today is the most secure way of implementing OAuth with spring boot and react and so there's no authentication happening on the front end because if the front end stores an access token well it's storing it like local storage or a service worker or whatever and it's better to store that access token on the back end. Do the authentication on the back end store it all and just let spring security handle it for you it's just easier and you know frankly more secure. So you can add the spring security dependencies in the palm dot XML so first thing I'm just going to format from tabs of spaces because yeah I'm that guy so SBR spring OAuth is my shortcut here. And you'll see we're adding spring boot starter security security config OAuth to client and OAuth to Jose. So those are all the dependencies that you need to do OIDC login with spring security and then the octa spring boot starter does exist. And what I found is that there are some hard coded endpoints so if I tried to use it without zero it actually went to the octa endpoint so that is something that I hope to get fixed in the next you know few months and then it'd be sweet because you wouldn't have to add all these you know spring security dependencies you just have to have one. And any time you can memorize any code I just love it right so you just memorize four lines of code then whatever this is 16 lines of code. So now what I recommend is installing the octas off zero CLI so I already have that installed and if you don't have it you can get it from. I'll get up here. Zero zero CLI make that a bit bigger so you can see it and it's just a nice tool to actually not have to do stuff in the browser you can do things much quicker so that's why I recommend it. So you can run us zero apps create and what I recommend is sitting in alias for it so because it's just hard to remember type of zero small characters so I just do a and then eight apps create and so we're going to spring boot. Let's react. And no need for a description here and it's going to be a regular web application and then the callback URL is going to be standard spring security callback URL so local host 88 this is for its you know IDC login login they call it what to but it's really IDC code. Zero and then for the logout URLs we're going to need to we're going to need the local host 3000 for and running it as you know the react app and then we're also going to need 8080 for and we're packaging it with spring boot so we'll need both of those. And then you'll see it prints out all our details so we have our zero domain right here and we have our client ID right here. And so now you can modify application properties to contain those values. And so the first one is that domain. So grab from right here. Right there. And then the client ID. And then the client secret which they don't show by default but you can use also zero apps open. To grab it from your browser so it'll prompt you for which app you want to open. And then I logged in with GitHub when I first did it. And you can see here's my application I just need to copy that client secret. Right and you see I'm storing my secret in source control so generally this isn't a great idea. You could use like a dot in the file instead and then source it before you start it. I'm just doing this for convenience so never check your secrets in the source control. Back to our instructions. We have everything in there. You can also use a zero dashboard right that's this right here so if we were to go back to applications and create a new application. Right you can name what you want and then make sure and select regular web application just use the same callback URLs and everything will work. And so let's verify it works right started up. Well it's not going to work quite yet. I might get back here. It just might not display anything so obviously I'm going off script because this isn't in my instructions but localhost 8080 here. And it prompts me to log in. You could continue with Google. I'd have to let's try my account there. And then the reason this doesn't work it actually authenticated me successfully but there's no mapping in Spring Boot for the default. You know slash. So that's why it gives me a standard 404. So if you used to Spring Boot you used to that message. Now I also want to point out that you can do everything you know with Octo as well. And you might be asking. Rable like you've been talking about Octo for a while and why are you talking about us zero now. Well that's because we bought us zero like what a year and a half ago. And we just discovered or recently reframed things. So we're leading with us zero. So if you're doing employee apps or apps for your company we recommend using Octo because it's good for companies to allow their employees to log into all their apps. And if you have partners that you know want to do apps then we recommend use Octo's customer identity or Octo Siam. But we've realized that the us zero customer identity solution is better for developers and I think you've probably known this for years. And you know I've known it only recently and it's a real pleasure to work with. So as a company we're leading with us zero when you need to embed authentication in your apps or you know obviously redirect is the best way to do it. Or if you need to secure your API so those apps can still be added to Octo in the Octo integration network. But you know going forward you should use us zero if you're doing customer identity it's just easier and you don't have to talk to any sales people. So as a developer that's always an awesome feature. So to do the same authentication that I said with us zero with Octo you can add the Octo Spring Boot Starter and then you install Octo CLI. You're on Octo apps create use the default URL because you choose Octo Spring Boot Starter will default to you know the same type of URL that we used for us zero just as Octo on the end. And then configure the default you know logout redirect your eyes and then we're going to make some changes in the next section. And so to modify those to work with Octo you just have to modify the user controller that will create to use Octo and then the logout method. You'll need to modify that a bit to work with Octo as well. And then the home.js that does the logout the parameters to do logging out of the identity provider is just a little bit different between Octo and us zero. And personally like there is a moment in time in the future where you don't have to make these changes. Right because what you see here is we're grabbing an end session endpoint from the metadata that open ID connect provides on Octo and also zero should have that same end session endpoint they just don't. So when I first started working with it I was like why why don't you have this endpoint and and they're working on they planned at it so hopefully that'll be there soon. And you can see all the difference is between Octo and us zero by clicking this URL and looking at you know the diff here so you can see you know those are a bit different dependencies are a bit different. And then down here you know there's a bit different in the logout URL and in the application properties. So that's about it. And now we need to configure spring security. So to make spring security react friendly we need to create a spring configuration file or a security configuration file. So we'll do that in a new config package config security configuration. And there's a number of things going on here. First of all you'll see hey it's like why didn't you you know import everything and there's this little maven thing here. Click to load the maven changes and then everything could should compile. And first of all in spring security five there was authorized HTTP requests if I change use that it should show me it's deprecated. Maybe maybe not well it is so the reason I'm using authorized HTTP request is because it's denied by default so authorized request is allowed by default. So if you have any URLs in there it'll protect them if you say to but if you say if you don't specify them it'll allow them by default. And so with authorized HTTP requests it's more secure and it's saying you know deny by default. So I had to add not only slash but index dot html because spring security also does more filtering. So it's not just on the first request but forward request it'll filter for those as well. And then static is another one that's where our CSS and JavaScript go and then these are actually files that'll be served up by the react app. So I had to add those and then we want to allow API user because that's how we're going to use and see if the user is actually logged in. And then for CSRF we're going to have a cookie CRF token repository and we set HTTP only false and so this means that the cookie is can be read by JavaScript. So that's where we're setting it to false and then this stack overflow kind of explains that you know this guy was like hey CSR protection not working with spring security six and he went through all the stuff he figured out the solution. And then there's this explanation that goes into the spring security documentation and it basically you know there's a new what is it XOR CSF token request attribute handler that is more secure. And it's used if you display or hide the CSRF token in an HTML page so it adds a bit more randomness to that. And we just don't need that because we're never displaying this on an HTML page where we're going to read the CSRF token from the header or from a cookie and then we're going to send it back in a header. So it's fine to use the default from spring security five at CRS of token request attribute handler. And then there is something that we do have to do which is add the actual CSRF token to a header so it can be put in that cookie. So we're going to create it right here and so this is recommended by spring security folks and I've got you know you can read that link for it. This basically just takes that CSRF token from the request puts it in the header and then it sets it as a cookie because of that. And then so we're adding the filter to do that. And then there's also a request cache and how this works is it's overriding the default request cast. So when you come from localhost 3000 you're using react to develop everything it'll go back to 3000. If we didn't have this here it would actually go back to localhost 8080. And then I added this check as well because if you're at localhost 8080 slash groups and you stop the server and restart it and then refresh the page. It doesn't send a refer because only sends a refer when you click on a link. And so in that case I found that if you grab the request URL you can get that same sort of behavior. So yeah it is misspelled in real life. That's always fun. And so we created that cookie CSRF filter and now we'll create that user controller. And so what this does is as a few methods in it it you know grabs that 0 registration there and that's so it can get the issuer. And it gets the user from here and you'll see if the users know if there's no authentication principle present it'll just return 0. And that's because we want to indicate to the front end that you know no one's authenticated. And then to log out it just grabs that issuer URI from the registration and appends the log out that it needs for zero. And then has that client ID and returns all that data. And of course it invalidates the session as well. And so you'll also want to add some user information when you're creating the groups because you want to have this so everyone create can create their own jump to it. Right. It's not just me. It's Josh Long or James Ward or someone like that wants to do a job tour and you want to build this site so everyone can create their own job tour. So we'll go ahead and create a user repository. And it extends from JPA repository. And it's a user string. Make sure that matches. Yep. So it's like why isn't it compiling. Well it needs to be an interface. And it doesn't really need to be public. So we can add a find all by user ID to the group repository. And then we'll inject the user repository into the group controller. And use it to grab or create an existing user. You know and adding a new group. So we'll go into the user group controller here. Yep. And we'll add user repository. Or maybe it doesn't need to be public. Let's see. Let's do it. The field for it. And then we can modify this groups. Right. Because we want to find all by the current user now. So we'll add a principle into the arguments. And then we'll find all. By user ID. Let's go get name should do it. And that'll grab the subject. The SUV claim from the ID token. And then we can create the group. And we'll modify this. Just using this method here. So instead of just posting it with no information. We'll add the user to it. So we need to add this authentication principle as an import. And then our user which we created earlier. And you'll see it grabs the principles attributes. Uses a sub claim as a user ID. Text to see if the user already exists. And then it you know either creates one or just adds the existing user. And then saves the group. And then we can modify react to handle CSRF. And be identity aware. So we're going to start by modifying index. That HTML. I don't know if we open that one yet. So index. Yes. So not HTML. And we're going to use the cookies provider so we can grab that CSRF cookie. There we go. Thanks. And then cookies provider right here. And they'll modify home to call that API user endpoint. Because we want to see if the users logged in. You can see up here at the top it's got some. You know setting up the state with authenticated and set authenticated. And the user and all that. So it calls that user. With the credentials included. And. Comes back. It's the data if there is any. If it's blank sets authentication of false. And then for the log in it's just redirecting to the back end. So this is actually not mapped by spring security. But API is protected. So because it's protected it will prompt you to log in. Or make you log in. And then the log out just does. You know logging out. And that's how it all works. So. Works pretty well. And then down here we got the log in and log out button. So you know those are rendered accordingly whether you're authenticated or not. And then we'll update the group list to have similar changes. So. We need to specify the cookies. We can use the use cookies effect for that. And the cookie name. And import it. And we'll need to modify it down here. The headers that are sent. Right. So the first one is for delete. XSRF. And you want to specify that credentials are included. Everything else is the same. And then for the group edit you have to do the same thing. So. Actually that's a mistake. I will grab this right here. Already did it for me. And then down for the. Headers. Let's grab that from here. And then for the credentials. Make sure that's right. Looks right. And then we should be able to restart and using both. So. Let's see. Make sure that spring boots not running. I'll just start it up here. I'll start this one as well. So you do have to start at the root. We'll fix that groups thing in a minute. But now if we log in here. You'll see we're already logged in because we didn't log out of us. All right. And if we manage our jug tour we can say. We're on our list. And it's all working. All right. And if you could say well the boulder job is cool too. You can edit it. And that's all working so. We have successfully integrated. Authentication in this app and made it so you know our users. Can see only their information. And so the last thing I want to show you is configuring. Maven. To build and package react with spring boot. And so you can use the front end Maven plugin for this. And you'll need to add basically a profile section. To your palm dot XML. And some properties. So you can see what this all looks like here. We're going to basically. You know let's make that a bit bigger. Make it easier to read. We're going to specify just the versions. Of the things we're going to use node 16. NPM 8. And the front end Maven plugin which this has been. The same for a good year. And by default we're just going to have the dev profile. So that doesn't expect or build. Like the react app. But for production we're going to use this Maven resources plugin. To filter. Through our classes. And make sure and specify that hey the active profile. Is prod. And that makes it so. You know. Spring boot is aware that hey we're running in this state. Where we have react in our app. And so this. You know we'll build the front end Maven plugin. We'll build from that app directory. It'll install mode so you don't even need. Not installed on your machine. And I'll stall NPM do that NPM install and all that. And then it sets that. Prop. And so you know we'll modify the palm dot XML. And then we'll add this to application of properties. And this value will be replaced. By the resources plugin up here. Open up palm dot XML. And what those properties first up here at the top with our Java version. And then down at the bottom of the profiles. And we need to modify the application of properties here. To have that spring profiles active. And then now we can stop the. Client. And we can run. And then spring boot run dash P. Pro to activate that profile. And you guys spell it right. Oh. Sorry running on port 8080. So that is F kill command I used to. Kill things running on certain ports. Now we can look open up local host 8080. Yeah. Make it a bit bigger. Again. And look at that run 8080 instead of 3000. And we can manage our jug tour. You might be like hey didn't you add Denver jug and Boulder jug where does go. Well. Those got deleted because by default each two leads data every time you restart. So you could configure it to store its date on disk. But just the default is to you know lose it every time you restart. So you know everything's working here. But if you go to refresh. I said it doesn't work. And that's because you know if you start from the root then all the routing happens via react and react router. But as soon as you like try to hit an endpoint directly it expects spring security to handle that. So you do have to make some modifications so that works. So we're going to add a spa web filter which basically you know uses or extends a spring class and then grabs the path and make sure that you know if the user is authenticated and the path doesn't contain a dot in it because you know you don't want to like you know do any redirecting for any of the like.js or.css files and it matches any other path and go ahead and just send it to the index. HTML and let react handle it. So this is a spa web filter that will create in our application. Under Web here it looks like that and then we need to add it to security configuration because we want it to invoke at a certain point. Just make that a bit bigger and happens after I'm just going to put it before that cookie one. Happens after they're authenticated because we're checking if the user exists. So now if we stop and restart and all works is expected. Pretty cool. The other cool thing is you know if we were to run MPM start like that still works. So the workflow that you're used to using you know where you can add. Let's do the next job. That's all works right. So you can have the nice react workflow that you're used to and you can also have you know spring boot running on the different part. So that's pretty slick and I hope you enjoyed this screencast and it helped you understand how to integrate react and spring boot three very securely. And so you can find the code on GitHub. Right. It's at this this URL here octa spring boot react to credit example. Of course the blog post is here so you can read through all that if you want the nitty-gritty details of everything. But thanks for watching today. If you want to find me on the Internet you can do it on Twitter or rabaldesigns.com is my website. You can see it right there. And then my team is at the dev and we post you know tutorials and videos like this one. And of course you can subscribe to our YouTube channel and get more content like this that'll brighten your day and make it just a better world to live in. Thanks.