 Hellooo developers! My name is Matt Raebel and today I'd like to show you how to build a full stack application using Spring Boot on the back end and React on the front end. Let's giddy up! This screencast is based on a blog post that I wrote and published back in October. You can see there at the bottom though it's been updated in December, just a couple days ago. So full stack Java with React, Spring Boot and J-Hipster running on the OpZero blog. You might be wondering, aren't you an Octa guy? Yes, but OpZero is an Octa product now, so hey, I like to use that too. At the bottom of this blog post is a GitHub repo that I'll refer to in a second, but I wanted to go through just the table of contents here. We're going to get started with J-Hipster 7, change our identity provider to OpZero, test it with Cypress, and then we'll implement crud on photos so you can upload photos. And basically what we'll be doing is creating a Flickr clone and making a nice layout and making that all look good. And then we'll turn it into a PWA and deploy it to Heroku. So in this GitHub repo, I have a demo.adoc file, adoc for ASCII doc, and I have a handy dandy ASCII doctor plugin. So if I click raw, you'll see there it formats it nicely. And I can put that on the left and then open up the terminal on the right. And the first thing we'll want to do is verify I have Node installed. So Node 14 or above, Java 11 or above, 17 should work just fine. I'm just going to use Java 11 today, and then Docker composed. All right. And then I recommend SDKman if you don't have Java installed, so you can click on this link to go to SDKman.io and learn how to install it there. And then if you're using Windows, you might need the Windows subsystem for Linux for some of these commands to work. And if you're a savvy Windows developer, I'm sure you can figure out without using that. The brackets at the end of some of the steps indicate IntelJ Live templates I'm going to use. And what that means is I basically prerecorded some code, and I type a word or two, and it spits out a whole bunch of code. So you can go to my GitHub repo right here. If you want to use any of those and import them into your IntelJ instance. And this was the table of contents I went over. And normally, when you do full stack development with Spring Boot and React, you'll create the back end with like start.spring.io and the front end with create React app. And today, what I'm going to show you is jhipster. jhipster, you can find at jhipster.tech here. That's basically a full stack application generator. Start as a yeoman generator. And it generates, you know, the back end in Spring Boot, the front end in Angular, or React, or View. And so that's what we're going to use today. And it basically simplifies a lot of things. And if you didn't want to use Spring Boot on the back end, we do have support for MicronautCorkis, Node.js, and .NET. And why am I using React? Well, it's the most popular. So you can tell I'm easily influenced, but you could easily use Angular or View. But, you know, according to Google Trends, most people have issues with React, or at least they're searching for it, right? So let's begin by getting started with jhipster7. First thing you'll need to do is npm install-g generator jhipster at 7. I already have it installed, so I'm not going to run that command. But you can see if we run jhipster-version, then it's version 7.4.1. And so you can make there a full stack Java app or directory CD into it, you can also use a take command, full stack Java, and it CDs into it for you. And then you can run jhipster. And this will prompt you for a whole bunch of options. These options on the left here are just the ones I'm going to override for the most part. I'm just going to keep the default. So monolith application. Base name is Flickr2. We don't want to make it reactive. We do want to change the package name to comauth0flickr2. And for authentication, we'll use oauth2 and openID connect, SQL, Postgres for production, h2 for development, hcache for our caching, and just a regular second level cache for hibernate, maven, note to the registry, note to any options, choose react. We will use the admin UI and scroll down to united for the boot swatch theme and dark. And you can choose whichever one you want. That's just what I'm using for this demo. Internationalization will say yes. And my ancestors are finished. They built the sauna before the house up in Montana. So I'll click that and then Cyprus for tests. And no other generators. That took about three and a half minutes to run. That speed will depend on your internet connection, the hardware you're using, and whether you're recording your screen or not. So since I'm actually recording my screen, it does slow it down a fair bit. By default, J-Hipster ships when you choose oauth2.0 with a key cloak container and Docker. So if you were to look at source main Docker key cloak, you'll see the definition for that. And you'll notice that it imports the realm configuration as well as the user. So that, you know, basically sets up your clients, your users and everything for you automatically with J-Hipster. And you'll run this Docker compose command right here to start that up. And you can also use JH key cloak up, which is a plugin for Omize ESH that J-Hipster provides. So if I were to type JH key cloak up as an alias, you'll see that's the command that's going to use. So we'll start that container up. And then we'll start our app up. Once everything started, we can open it up in local host to 8080. And then click sign in. And log in with admin admin or user user. Those are all defined by default. There's no entities yet. But if you're looking at administration, you can see like all the metrics that J-Hipster has driven by spring boots actuator, health checks, as well as swagger API. So you could actually have your front end developers just interact with this if you want. But we like being full stack developers, right? And even the ability to interact with your H2 database. And if we were to go back to home and switch to finish, you'll see the translation works as well. And then we can go ahead and log out. Put that back on the left. I did want to show you that Cyprus is integrated by default, or at least I chose Cyprus, right? So not by default, you get to choose that. And then if you run MPM run e to e, that'll actually start up Cyprus and run all the e to e tests that are generated by default. J-Hipster has about 70% coverage on unit tests and integration tests throughout the code base that's both back in and front end. So Cyprus is just adding, you know, more tests to the mix. And if you were to generate entities, it would run those tests as well. So right here, it's just testing all those things we did under the administration menu, going through the logs and configuration and making sure all those, you know, render properly. That took about 30 seconds. So the next step is to go ahead and cancel out of this control C, and then open it up in IntelliJ. And we want to switch the authentication to be us zero instead of key cloak. And the cool thing is spring security OAuth is what we're using for the OIDC implementation. And you just have to override a few variables to make that work. But to override the defaults, let me just show you where that set application dash dev and look for 9080. And you'll see those are the default settings for, you know, OIDC and key cloak. So it's just that issuer client ID and client secret, which is a very secret, you should never store your secrets and source control, by the way. So that's what we're going to do here is we're going to override those, but we're not going to store them in source control. So we're going to create a dot off zero dot env file. And then we'll copy and paste all this in there. No, don't add it to source control, please. And then go into get ignore and be like never add it to source control, please. Right. So star dot env. And then log into your awesome account or sign up if you don't have one. So I'll do this in another browser, open up Firefox here, and go to sign up. If you don't have an awesome account, I already do. So I'm going to take this login, use that instead. And whatever mechanism you use to create your account, make sure and use that again, because otherwise you'll end up with multiple accounts and multiple accounts is fine. You just might not be able to remember which one you started with. So I started with GitHub, and I've deleted all my tenants. So it'll prompt me for a new tenant here as soon as it prompts me for my UB key. And then the tenant domain, you can change it to whatever you want. But I'll just use the default here. Let's see if we can refresh and I'll give us a new one. Yep. And we'll create that account. And then once this loads up, you can go to applications, create application, name it whatever you want, J hipster, baby, and regular web applications. And then the main thing we're going to need is this redirect URI right here, which is set by spring security. So if we were to go to settings, and down to the allowed callback URIs, and local host 8080 for logout. And that's it scroll to the bottom, click Save changes. And then we want to take and modify those variables, right? So first of all, it's our odd zero domain goes right here. And also down in the audience. And then the client ID, right here. And you might be wondering where that audience comes from, if you were to go back here and go to API's, you'll see that matches what's set up right here. And now we need to add a couple roles. So I'm just make this a bit bigger so it expands there. And then user management roles, we'll need a role user and a role admin. So let's start with that role user. This is what J hipster expects by default. And so we'll just do J hipster user there, create it, go back, create another one, role admin. And if you're an admin, you'll see the administration menu, otherwise you won't, but users can modify all entities as well. And then we'll create a new user. I'm just going to use mrable at gmail.com and password. Alright, so now you need to make sure and add those roles, right, that you just created. So role admin, role user. And then the thing that trips people up a lot, and it definitely tripped me up in the beginning was this right, it's not actually activated yet. So you can click edit and change the email, and then set it as verified. You could also open up your email and actually verify it that way. Alright, so everything set up there, back to us zero, we forgot to set up the groups claims. So if we were to sign in here, hopefully it just takes us right in. And this is what we're going to need for the auth pipeline rules. So you go to auth pipeline rules, create just click the empty rule, we'll call this group claims, and scroll down and replace this block of code. So what this does is it adds the preferred username from the email. And it also does some mapping from the roles to a groups claim that goes in the access token. So then we can save that. And if you want to see where all that happens, if you go to security configuration here, you'll see there's a user authorities mapper and that basically handles all the logic of extracting those claims. I'm not sure why we're getting some red, but we're just going to run it through Maven. So shouldn't be an issue. Also, if you want to actually make it so you didn't have to click through the UI that much, there is this issue that I created for the author zero CLI, that will add support for Jay hipster, we haven't locked the CLI. So I figured it'd be cool if I zero had a two. And then if you want to use octa, we actually have that documented in Jay hipsters documentation, as well as everything that I just went through here with us zero. Okay, so now what we can do is we can source that file we created, right, let's make sure it's got everything in there. And then source it to set those environment variables, and then run our app again. And you might notice the red squiggly lines got resolved. That's because I went over here while that was loading, and did a reload project and that fixed it for Maven. So now if we open up localhost 8080 here, and click sign in, we'll be redirected to us zero. And as long as you remember those credentials, you should be good to go. And now we're back and we're logged in. And we have the correct permissions because we can see administration. So that'll work nicely. And if you did want to use Cyprus to test that you could, you would just use these commands right here. So export Cyprus e to e username, whatever you have for us zero, and e to e password. And I probably could do that since you already saw my one password, but I won't because it does, you know, take another 30 seconds, but then you can run it all here. And just to warn you, when you do start adding entities, what happens after you get to a certain amount is also zero actually kicks in its rate limiting, and the Cyprus tests start to fail. So be aware of that look for rate limiting headers, and the server logs, if that does happen to you. And what I recommend is obviously you can just use key cloak in CI, and then you're not using us zero, you're not paying for it and works quite well. So now let's create some data handling for this flicker clone. So JDL is what J hipster has for its domain language. So we know we're hip, because we have a domain language. And it allows you to model data in your app and generate entities front. So we have this JDL studio, that'll pull over here and put on the right here. And if we were to take this JDL below, you'll see what it looks like. Put it in here. And you can see we have an album entity, a photo entity and a tag. So there's a relationship from album to user, many to one, photo to album, many to one as well. And then many to many photos can have many tags tags can be on many photos, and then some pagination rules. So you can mess around with this and it'll actually, you know, do validation and everything on your JDL. And then when you're finished, you can, you know, save it right here. So since I already have it on my clipboard, I can just go and hit and put, you know, flicker.jdo and copy and paste it in there. And what this will do is you can import it with J hipster, JDL flicker.jdo. And this will basically generate all that you need for these entities, it'll generate liquid based changelog files. And it'll prompt you to override any conflicts do a for all. And it'll generate all the table definitions. And it'll generate all the back end code, the test for the back end code, the front end code, the test for the front end code. And since we're using Cyprus, it'll generate those N10 tests as well. You'll see that was pretty quick. So we can stop our app back here and then start it back up. And just to let you know, there is ways to actually make it detect when those changes have happened. So on the front end, if you're on npm start, it does use browser sync to look for new changes in files. On the back end, it use spring boot dev tools. So that will actually if you recompile things, it will pick up those changes and reload your app. But you do have to recompile them. So it's not just smart enough to notice that there's new files. And if you want to see all those new files that created, you can click on the commit tab right here. And it'll show, you know, all of the back end code, all the front end code. And then what files it had to change to actually add those into it. So some translations there, and back to our project. And so open it up. We're logged in. Now we have entities. So you can see albums. And this is what's called fake data from faker.js. So if we were to look at any of these, we can actually edit them, right, and make a change there out of two, save it. And then it actually saves it right with two on there, you could delete it as well. And all that's working. I like to get rid of the fake data. So let's go ahead and do that and application dev.yaml search for faker, and remove that as a profile. And that will not populate it with fake data. And then if you remove target h2db, and restart it, that'll all get rid of it. So I'm not going to show you without it, because obviously, you know what that looks like. But the photo entity has a few properties that can be calculated by reading the photos exif data. So that's exchangeable image file format data. And if you use your phone to take pictures, which often many of us do, you will actually have that data in the picture. So there's no reason to like make the person actually put in, you know, what date it was taken in, you know, all that kind of stuff. So drew notes, metadata extractor library will help us do this. So if we were to open up our palm dot XML, and go down to dependencies, we can add it just at the top here. And you might notice this little icon, this is something that IntelliJ used to just reload automatically. Now they make you click on that to reload it. So make sure and do that or those dependencies won't show up. And then in photo resource, we can make some changes to actually grab that data. So if you go to the structure here, and go to create photo, you can find that method. And then right in here, we're just going to copy and paste this try catch. Right. And so it's going to set the metadata from the photo, and then do some image processing. And the set metadata is something we need to create. So that's my little Java shortcut here, or IntelliJ shortcut, Java metadata. And then it spits out all that code for me, and does the imports. And then up here, it will warn that, hey, you know, you got new exceptions there. So it looks like it might have handled that. Nope. So we can add with IntelliJ's help here. We'll add some more exception catching there. And if it doesn't work, then it'll log it, but the photo should still get saved. So now we can remove the fields from the UI that actually allow the person to set those. So in photo update, TSX, you'll see that's in source main web app app entities photo, we can go in and basically rather than displaying the height, width, taken and uploaded values, we'll hide them. So search for photo height. And we'll grab these all the way down to, let's see, uploaded. All right, so there's four fields there. We'll grab those. And we're going to replace this with metadata rows as a variable, metadata rows. And then we'll go up to the default values here and set them. So search for a default values. And right here, and we'll go ahead and say const metadata equals all that that we copied and pasted, right, those fields there. We need to div around them. So hold on. All right, now that's working as expected. And then down here, we'll say those made of data rows, right, data rows equals is new. Don't show anything. Otherwise, show them. And then everything else is the same. And then down in the return block, that's where I added the metadata rows, like just just make sure it's in their image metadata rows. Yep, just like we have in the code there. And then the album. And we can actually go to photo spec. Now we'll want to remove them from our test, right, because Cyprus might actually try to set those and that test will fail. So that's not good. So search for height. And all those. So just, you could comment them out, but, you know, I'm going to delete them. And then stop the maven process, which we already have stopped. You can also use fkill CLI as a MPM command. So you can make sure it's not running on 8080 there. And then start it up again. And make sure you source off zero. And open it up, sign in. And if you were to go and add a new photo, let's see, I have a few in my file system we can use here. Let's see, here's a good one. Old half a the bus. Bottom off eBay in 2004. And he's pretty awesome today. But you'll notice, you know, it's not looking great, right? We can add another one. Just so we have a few of them in here. This is a autumn in Montana. Save that one. Create another one. All right, so we have a few images in there now, but they still aren't like looking that great, right? They aren't in a grid. So you can use react photo gallery for that. So that's a component you can start with MPM. So I'll go ahead and install it here. And then we'll need to open up photo.tsx to add it. So the first thing is to import it right up here at the top. And then find props and put this shortly after it. So we're looking for a match here. There we are. And then we can just set up this photo set, right, which basically takes our photo list and maps it. And it converts to a base 64 image, and then sets the width and height. And and this is basically saying, Hey, if there's so many photos, you know, display them this way, if there's more than do it a different way, and then add a gallery right after the H2. So look for a closing H2 here. All right, that's in the right spot. And then save all our changes and restart. Well, we only made front end changes. So we can actually just use MPM start and does browser sync. And it'll proxy to the back end. So we don't even need to restart the back end. Fires it up, make it a little bigger. Go to our photos. And now you'll see we have a nice grid feature pretty slick, huh? If we go back to our instructions, you'll see it talks about liquid base and faker there, which I already did. And then there's also a light box feature you can add. So the react photo gallery docs show how to do this. If you were to go here to react photo gallery to show you how to do it. And I actually already did it in the source code for the GitHub repo. So if you were to look at that or a diff of the necessary changes, you'll see it's a new dependency. It's some new imports. And then just some things to make lighthouse all work. So that works quite nicely. So the next thing is to turn our full stack job app into a PWA. So for a PWA to exist a progressive web app, it's, you know, trying to be like a mobile app on a device must be served over HTTPS, it must have a service worker so it can work offline. And it must have a web app manifest. So for HTTPS, you can set up a certificate on local hosts, but I rather just deploy it to production. So we'll deploy to heroku to see that. And then to force HTTPS, you can do that in your security configuration. So let's just grab this and go back to IntelliJ and open up security configuration. And we're looking for that frame right there. And then we can paste that in there, Outdent that. And what this does is it basically only looks for an x forwarded proto header show most cloud providers do this. And the beauty of this is if you're ever running on Kubernetes, it won't do a 302 enforce it for certain URLs, right. And so we just want it to force HTTPS when we're in a browser. And then for the service worker and source main web app index, we need to uncomment some code. So go into index here. And search for service worker. And there it is and uncomment that. And now we already have a web app manifest. So here to look for that, you can see it's already in our project. So that sets up, you know, a number of different J hipster logos there. And the next thing is we can now deploy to heroku. So you'll need the heroku CLI installed. If you don't have it, or you don't have a heroku account, go here to heroku.com, sign up for free. And then for the heroku CLI, you can get that from the dev center here. If you just Google for heroku CLI, it'll show you how to do that. And then we can go back to our app and just basically run J hipster for heroku. And it'll prompt you for the name. I'll do clicker three. And we'll put it to the US. And we'll compile it on heroku. And like I said, you can use whatever version let's be daring and use 17. And what prompts you for a lot to a thought to just say no, we'll configure it manually. So the heroku deployment will take a little while to run takes about six minutes, could take longer, depending on your internet connection could be faster. But it is actually building the whole app on heroku and installing the main dependencies, mpm install and everything. So as you can imagine, that might take a bit since that is going to take a while, we can proceed and set up us zero while we're waiting. So I'm just going to set up these variables and a little scratch pad here. And then we'll make sure and grab them from our off zero dot env. So first of all, that you are I, or that domain, so we just grab this part line ID, make sure you don't have that dollar sign in there. That's secret, make sure and get the whole thing. And then that auto domain should be working right here. So we can actually put this in a second terminal window. What we can do is use heroku config set to basically set those. And since we have those variables already defined, when we run this command, it'll populate those. That's all done. If you were to run heroku logs tail, there's a good chance it didn't start up because it couldn't connect to key cloak, right, because that's configured by default. And so that's why it's crashing here. So we'll run this command to, you know, reset those environment variables. And you can see, oh, we did have an issue with the audience there. So that one's not being set properly. So I kind of messed up there. Let's just go ahead and put this. I was just supposed to be the domain, right? My bad. So heroku config set audience. Let's see, we want to actually be this guy right here. And then this value right here. And so you'll notice it did start up just fine with that value. What'll happen is if you log in and it comes back to your app, then it will fail to actually validate that audience. And so that's where the the failure will happen, it won't happen on startup. So now since this is set as a get remote, so if we were to get remote dash v, you can see heroku, you can do heroku open, and it'll actually know how to open your app or what URL it's running on because right here, it says local host, but that's not right. So now if we were to click sign in, it sends a redirect URI that is configured for this actual server. So it doesn't actually match. So that's why also zero is complaining here. And if you were to go back here, you can grab, you know, this URL, and you need to add it to your awesome zero dashboard. So I already have it going here, I can go into my applications, and go into J hipster baby settings, and that allowed callback URI, right, it's going to be a bit different. So comma and number three. And right here as well. And we don't need all this trailing stuff. So scroll down, save it. Now if we were to go back here, where it's running and refresh, it'll actually work now. And we're logged in. So we're up on heroku. There isn't any data in here, right, because we didn't add any. But if we wanted to add a photo, we certainly could. And that should all work. Talking to Postgres on heroku. There it is. So that's all working. You can test it with lighthouse. So there's a feature in Chrome. If you were to open up Chrome developer tools, it doesn't matter if you do that or not. And you go to lighthouse, and click generate report, it'll actually go through and audit your app, and show whether it's a PWA or not and give it some scores on like it's, you know, it's ability to actually do stuff. So I think if I was on the home screen, this might do better. But I've also had some issues with lighthouse recently. It's not just J-Hipster apps. It's any app. It actually doesn't even complete. So it just like hangs here the whole time. So as an alternative, a web page test, which I recommend using, you can go here and actually test your website there. And while that's running, we can also do security headers. Let's see how our security headers are. Oh, that's flicker two, which doesn't exist, flicker three. So look at that. We're getting an A is a PWA. No, lighthouse is still having issues back here. And web page test is still running. Started 18 seconds ago. And you can see we get a bunch of A's there. So that's pretty good. That's it. You streamline your path to being a full stack Java developer with J-Hipster. If you're not familiar with Java or React, if you read the blog post, it's got some links to tutorials that basically show you how you can get started with all of those spring boot Java itself and react. And of course, you can go to the GitHub repo here, us zero full stack Java example. If you like this screencast, please follow me on Twitter. I'm Adam Rabel. My team is at octadev. But us zero is also very important to follow. And us zero has a YouTube channel smash that subscribe button. And my team has a YouTube channel as well at octadev. So I hope you have a wonderful day and enjoy being a full stack Java developer. Cheers.