 Hey there, my name is Matt Ravel today I'd like to show you how to build a progressive web application with react spring boot and J. Hipster. Let's get started I wrote a blog post that shows you how to do all of this. It's called build a photo gallery PWA with react spring boot and J hipster published on the octa developer blog and it basically goes through some intro stuff and then shows you that you need to install Generator J hipster 5.0.1 So I already have that installed you can see here and We'll make everything arranged nicely So we'll start out by creating a gallery little round command cd'ing into it and running J. Hipster There's gonna be a number of questions that asks us about J. Hipster and the type of application we'd like to create I'll go ahead and create a monolith call it gallery octa developer Or calm dot octa developer Know for the J. Hipster registry, we're gonna use a lot 2.0 sequel Postgres H2 each cash hibernate second level cash Maven and We won't choose any other technologies And we'll use react Nota sass internationalization yes Go English and French since the original creator of J. Hipster Julian de Bois French and Protractor to make sure everything works So you can see that took a bit of time to create about seven minutes and 30 seconds on my Mac if using Linux I found that you can get that down to only a couple minutes So there's some speed difference just in MPM install on the two platforms So now we can verify everything works. This will use key cloak by default. So I'll go ahead and start that Using Docker compose source main Docker key cloak up So J. Hipster ships with key cloak by default configured for OAuth 2 and it has a Docker image that basically Imports the default users and roles and sets up a client for the J. Hipster app And then we can also start up this app mvn from Maven And then we could start another window That runs our end-to-end tests and this will just kind of give you an overview of what the app entails What's in it and and some of the screen so it'll be quick But we'll verify that everything works as well Hmm key cloak failed to start Let's see why could that be Because we don't have postgres up. Well, I'll start postgres if that's what you want I don't think it should need postgres so So after doing some research it turns out that key cloak will Detect if you have postgres on your local host and and use it. So here's here's the JBoss key cloak image And you can see here the database supports H2 MySQL postgres or Mariah DB I've never had it choose postgres before but for some reason it did this time and You can specify the DB vendor with an environment variable. So in source main Docker key cloak. I have added DB vendor here as H2. So now we should be able to do Docker compose source main Docker key cloak up And I'll use H2 instead of Postgres So if you get that problem now, you know how to fix it and then we'll want to start our app Using MVNW and I'm using iterm here in the shortcut is command shift D To do the screens the screen splitting So once the app start up we can run yarn e2e and it'll drive our browser and Show all the different screens that are configured by default and log in the key cloak and make sure that that works You can see there's some nice information as protractor tests that take or tell you when some of them took a little longer than expected So the good news is they all passed and we can proceed on to the next steps So key cloak does have the ability to actually turn on user registration Go to localhost 9080 J hipster when it ships with JWT authentication has a sign-in link on the home page and we're using OAuth it doesn't so That's because the IDP can actually do the user registration for you You can also turn on like forgot password. Remember me and all that So if we do that, then we go to our app localhost 8080 And if we click sign in You'll see now there is a Register link. Well, the other thing you're gonna want to do is you're gonna want to go to roles and set the default role That someone gets added to because if you don't then J hipster limits the user access to role user and role Admin and if you don't have those well, you're just not gonna be able to do anything but log in So we'll set that and I like to set the default users as well. What is fault group under default group? Add users and add it there And now if we open up a new incognito window And go to localhost 8080 And we can sign in and then you can see you can register So we'll just use my information and one thing you don't want to do is for the email use something like mRable plus, you know key cloak at gmail.com because J hipster prevents having plus in the username so that'll fail just to warn you there. I'll just go with mRable Password Then you can see I'm I'm logged in. I'm registered. There are no entities I'm not an admin so I can't really navigate around but hey, it's working. You know, I added a new user So that's pretty cool and just to show you what happens in the actual database I'm going to open this up in IntelliJ We have a user syncing feature or a save user snapshot feature Which means as soon as you log in the app makes a call to api slash account and that will look and see if that user is in the database and it's not it grabs their information from the IDP Spring security handles like grabbing it from the user info endpoint for OIDC and it saves it into your database That allows you to have relationships with the user object using JPA So it's pretty nice feature. I developed it myself. I like how it works and I'll go through that as soon as IntelliJ starts up here It does take a little while to initialize that's because of indexing and the node modules directory is of course millions of lines of code So IntelliJ struggles a bit with that, but after you've done it once then it should be fast from then on So if we look at account resource You can see There's this account mapping for slash API account There's API. There's account and it says is principal instance of OAuth 2 authentication If it is it calls get user from authentication the reason for this else block here So you can still do tests like you normally would without having to worry about an IDP or OAuth 2 being involved So if you click on this Get user from authentication Takes us to the user service and here it basically grabs the details and converts the claim the roles claim from spring security or from the IDP in this case from Key cloak and converts those to authorities in spring security and Then this sync user with IDP is a method that goes ahead and says hey Does this user exist if they don't or if they do go ahead and just you know check when they're last updated and You know if it's after it then you know just update the user If no last updated and blindly update them. Otherwise go ahead So I like it because it's basically a cache of your user information And there is no way within J hipster within this architecture to actually write back to the user table in the database So it's always just a read-only record and the next time that person logs in that record will get updated So you saw how to log in with key cloak Why would you want to switch to octa? So octa is an identity provider as well. There is no Local version that you can download and install it's cloud native. It only works in the cloud But it's great for production because it's always available. It's always on Key cloak you would have to up upload it You would have to host it you would have to maintain it and upgrade it and stuff like that So that's why I like octa also. I work for them. So I'm a bit biased there But it gets multi-factor authentication email support you get basically a thousand users a month for free So I encourage you to sign up for a developer account to make it happen. So to see how it works I've created an octa.env file on my local host that has the information in it that I need If I look at that octa.env Oh spelled it wrong You can see it's got octa with j hipster access token your eyes. Those are my Octa tenant that URL right there and then I have a client ID and a client secret and So to create those here's the steps you basically log into your octa developer account And I'll just show you what that might look like so if I go to admin and Then you'll normally see this developer console at first not the previous screen But you can click on applications and you click on add application And you click on web next and Then you'll basically configure the login redirect URI to be local host 8080 login. That's what spring security uses Group assignments just everyone authorization code flow the best code flow for OAuth and and then you could click done I wouldn't do that since I've already set it up But I also want to show you that you do need to set up the roles in a claim So in your default authorization server You'll navigate to claims And you'll see I have one for groups and one for roles. You can name it either one. It'll work with both So if I was to add a new one just to show you what that look like and call it groups You put it in the ID token You set it to groups as a value type and then a regular regular expression and do dot star Which means everything and then you hit create so I've already done both of those so I don't need to Unfortunately the audio for this screencast stopped recording at this point and got all jumbly So I'm gonna have to do voiceover for the rest of this and we'll make it work that way I Showed you how to configure self registration with key cloak. Now. Let's see how to do that with octa If you log in to your octa tenant You'll need to switch to the classic UI Up in the top left corner and then go to directory self service registration and You can enable it. It's disabled by default and You'll want to specify that you want to add it to the sign-in widget and Assign it to a default group called role user and so as part of the blog post I went and created those users ahead of time a role admin and role user to match up with what Jay hipster has and Then you can accept the defaults except for the custom URL Which you'll want to set to local host 8080 for this example for production You'll want to change it to your actual production URL Now let's configure the application to use octa instead of key cloak I'll source that octa dot env file with my settings and restart spring boot and So what that file does is just override the access token URI and all the client ID and client secrets that are specified in application dot yaml Under source main resources config inside Jay hipster or inside your app There's also other customization options via our live widget. You can see we actually have a way of modifying The widget in real time and seeing what that looks like you can modify the CSS You can add various features and basically make it look just like you want it to so it has really no octa branding It just has your branding Once the app is up and running you can hit local host 8080 Click on sign-in and Now you'll be using octa instead of key cloak since I've already logged into my octa tenant You don't see any sign-in screen. You just see that. Hey, you're logged in as user with the appropriate Email Now you'll notice that if I click login again, it just logs me in again, and I don't see the sign-in screen That's because similar to Facebook login if you log in with Facebook to an application and you log out You don't want it to log you out of Facebook. So that's what we do with the Jay hipster integration There's a blog post I wrote last week that shows you actually how to implement global log out in a Jay hipster app Or basically a spring boot and angular app It's this one here to pull your secure spring boot plus angular PWA is a single artifact If you search for log out in that post you'll see that you can implement local global log out But now let's let's get to the meat of the post and actually create a photo gallery That allows us to crud albums photos tags And we'll use the JDL studio feature for this So JDL stands for Jay hipster domain language allows us to model out how our entities might look Their relationships and if they have pagination you can see in this file that I have an album with a title description and Created date as well as a photo with title description Image blob and then height width the date it was taken the data was uploaded and tags just like you know We can tag anything these days You can select the whole file or you can download it using the icons on the top right I'm just gonna select the whole thing And then copy it and then I will cancel my server and create a gallery dot jh file paste the contents into there and Then I'll run Jay hipster import dash JDL and Specify the file name and this will create everything you need to crud these entities They'll create the relationships between them It'll create the spring boot code and the rest endpoints It'll create the liquid base files that it needs to create the tables. It'll create integration tests it'll create unit tests and Yeah, it's pretty slick and it'll run yarn to basically build everything compile everything and Make it all work There's a number of fields that can be calculated instead of input by the user For instance, the image is height or the width as well as the taken on date or the uploaded date And so we can use Drew Drew notes is metadata extractor library for that and So all you need to do to basically integrate it into your project is add a dependency on the library in your palm dot XML So I'll go ahead and copy the dependency information group ID artifact ID and the version Open palm dot XML And then Jay hipster per night provides a nice little gap right under the Jay hipster framework dependency or you can paste in new ones and Then I'll modify the photo resource in the create photo method To set that metadata or to read it and then I'll copy and paste the set metadata method just below it Now even tell Jay set up so it automatically imports unambiguous imports We just need to add one for Java time instant So you can see here this reads the date digitized sets that if it's still null after it goes through there Then it sets it to now sets the the data was uploaded and then it grabs the height and the width as well the set metadata throws that Image processing exception, so I'm just going to change this to throw exception and now that class should be good to go So just to show you what it looks like before We actually added that logic. I'll log in and upload an image and you'll see that if we don't specify Width and height then it won't have one So now we get to photos click create a new photo And just pick one I have on my hard drive here nice picture of the arc de trance My wife took a few years back before we were married Beautiful photo and click save And you'll see there's no height no width invalid dates for taking and uploaded so now we can restart Spring Boot API and I'll grab that new code. I could also just Compiled it or recompiled it within IntelliJ and Spring Boot dev tools would have restarted it for me Now I'll add a new image Now this is a bug that I noticed that if you actually refresh the page in React and jhipster 501 it takes you back to the home page rather than the page you were on That does work an angular It's just a bug that's broken in react and I added a an issue for that so no worries. It should be fixed soon So click create a new photo this time. We'll go ahead. It's like that same photo Give it a different title And click save And now you can see the height and the width are calculated as well as the taken and uploaded dates So now a number of those fields You can't really enter because they aren't read So in the UI, I'm gonna go ahead and hide Those fields when you're creating a brand new photo or uploading a new photo So open up photo update dot TSX and in the render method There's all these properties that it grabs from the photo entity itself and right under there I'm gonna basically grab all the rows for height width Taken on uploaded date and I'm gonna put those into a variable so we can basically show them or not show them so grab all that and I'm gonna call it metadata rows So I'll create a new const variable called metadata And you work on with react every component or every JSX needs to have a root component So I'm gonna wrap everything in a div then I'll paste all that in there and Then when we're showing this for edit screens, we're gonna want to make those fields read only we can still display them But we don't want to allow the users to modify them So I'm gonna add read only to all the fields And you'll notice that it's camel case that's because we're in reacts JSX and It's not reading the actual HTML attributes So once I have that in place I can create another constant and call this one metadata rows And if the record is brand new Then there'll be nothing it won't show those rows Otherwise, it'll show the read only fields and there's also Protractor tests that set those fields. So we'll go into photo dot spec dot TS and We'll find that code that's setting them since they won't exist anymore We're gonna want to delete those and then if we're not gonna set them We might as well really remove the code that actually deals with handling that And now we can actually use yarn to start just the front end and it uses webpack dev server to proxy to the back end and proxies the API slash API to the port on 8080 So yarn start and then you don't have to rebuild the front end and restart maven We'll also open the browser window for you to localhost 9000 I can go and look at the photo entities We can create a new photo and you see those fields are gone And if we were to edit this one you would see that they're read only So cool, that's working Now let's add React photo gallery the component. This is from neptunian and It's pretty slick library because it basically gives you a flicker like layout in a grid and Makes everything kind of fit together has features like light box Dynamic number of columns and leave and allow you to to drag and drop things to make it all work So the light box components pretty slick You've probably seen light box before but you just click on the image they can navigate between them It's like a zoom-in feature So I'll open up a new terminal because I don't need to stop yarn start everything should work without it and Yarn adds the exact number instead of a range For the version so I like to do that so this video will always work Even if there's a new version of react photo gallery As long as you use six dot zero dot two eight everything should work So open up photo dot TSX add an import for the gallery component and Then we'll leverage the existing photo list We'll map that and grab the URLs and the width and the height and calculate whether it's a Wide photo or a tall photo or if it's a square photo And so that's what the the numbers there are for and then right under the Heading the photo heading we can add the gallery component pointing to that photo set list So as soon as the dependencies done installing And we should be able to refresh our page and see the changes Now you can see it's displaying that in a grid format. There's only one so can't see it that well So let's go ahead and add another one. We'll do a picture of some old Volkswagen buses now. We have two So it's looking pretty good We can add another one. I don't have any that are tall so Won't really make a difference. I'll just skip that part Now let's turn this into a progressive web application So progressive applications must be served over HTTPS They must register a service worker and They must have a web app manifest that Gives information to install them so in the index dot HTML. That's where the service worker gets registered That's actually commented out by default so go ahead and uncomment that and then There's the web app manifest This defines your Installation settings like your name that the user will see as well as icons that they might see after you've installed it on a phone Or on a desktop So I'm just gonna change these to be a little friendlier and then to set it up So it's always going over HTTPS when you deploy it to something like cloud foundry or Heroku you can actually look for an X forwarded proto header And so in security dot or security configuration that Java You can add this code that says basically if you see that header force HTTPS So that's a great way to to force it on those platforms So we'll go ahead and paste this code in here that says hey if I see that header make it secure and So the work box web pack plug-in is something that works in web pack to actually generate that service worker for you So if you were to look into the web pack directory into the prod Configuration and you will see the code in there for that The beauty is that this only happens when you do a production build So normal development how you don't worry have to worry about your browser caching too much information To verify everything works. Let's deploy it to Roku where we can run lightbox or lighthouse Sorry and and confirm that we have a bona fide PWA So you'll run heroku version just to make sure you have the Roku CLI installed If not, you'll need to go and install it. There's links in the blog post to do that Even though there's a number of errors here. You can see that it does print out that I have heroku Installed so now I can do J hipster heroku And I'm gonna cancel all these other windows just so there's no resource contention between files No prompt me to name my application on heroku. I've used gallery dash PWA in the past when I practice this demo So I'm gonna use gallery dash PWA dash screencast this time and We'll choose a US and I'm gonna use get to compile it on heroku So this will this will use the existing get repository push any commits that we've had and then Overwrite files to add the heroku plug-in to maven and it'll start building it on heroku So you can see that took about eight minutes if you're actually doing this and recording a screencast It seems to take forever So I've sped things up and spared you that you can do heroku logs dash tail to see if it's actually started on the server side and you'll see that it has so we can do heroku open and And there it is it's up and running in production if we click sign in though It's still trying to get to key cloak So to fix that you can actually run this heroku config set and This is also documented at J hipster tech slash security under the OAuth section for both cloud foundry and Heroku so this will set those environment variables and restart The app for you. So now we can do heroku logs tail again And see if it's restarted and the nice thing about doing it this way. I think is that your GitHub repo where you store your app will have the key cloak settings if you're on a plane It'll work with key cloak everything's fine and then in production You'll go to octane because all your client ID and client secret are in environment variables It's a more secure way of storing that information than actually storing it in the application Dot yaml file do heroku open and now we can test how we're doing on a PWA first. I'll log in Because I think that's a bit more accurate Oh, this happens when when there aren't any variables So if you do security and there's nothing there that means you didn't do Octane be ahead of time And so now if you echo security, it should be something that right client ID And so before I just set it to a bunch of nothingness so back to grabbing this code here Trying that again So yeah, the first time I saw that I was like what like I just configured all this So that's because there's no environment variable set it You basically set it to nothing and this is kind of indication it prints them out when you did set it to something so We're almost there on This particular test I got a hundred on progressive web app and accessibility So that's really nice now. I'll do it with this new one here Heroku open and log in Oh, the redirect URI isn't in there. So that's important to know We have to configure our app to have that new production redirect URI. So this is Gallery PWA screencast we go into admin switch back to the developer console applications And let me see which one this is I'm gonna guess Huh, easier to look need to go into the application under general and you got a whitelist all the login redirect URI So I need to add a new one here And it's best by logging at the end save it And now I'll be able to log in so you can see I'm logged in as mrable there and I can generate a PWA report See what we get 91 not bad. I got a hundred last time. You're on it a couple times. You'll get a hundred too So so that's it. I hope you've enjoyed this screencast of building a react photo gallery of spring boot and Jay hipster and OAuth if you're interested in learning more about all those there's a number of links on this blog post here and Thanks for watching and hope you have a great day