 Hello, developers. My name is Matt Rabel, and today I'd like to show you how to develop a cool cars application with Spring Boot 2.2 and Angular 8. You can find me on Twitter at mRabel, but more importantly, let's talk about what we're going to build today. We're going to use Angular 8 and Spring Boot 2.2 to basically create a Spring Boot API that has a list of cool cars, and then on the front end we'll consume that list and we'll also go out to GIF you to get a cool animated GIF that matches the name of that car. So to begin, Spring Boot 2.2 has a number of enhancements. JMX is off by default. It's using Jakarta EE dependencies, but the biggest thing is the performance improvements. So they've done a lot to make things faster. I believe in response to Quarkus and Micronaut because those frameworks start up so fast. Lazy initialization is on by default, and those are the biggest things that I've seen. Of course there's many more things you can see in the release notes. We'll be using 2.2.0 M4 today. But more importantly, I think, is the release of Angular 8 because this is a big deal. It's a, you know, major release, and they've done a bunch of things, including aligned it with Angular Material and CLI, so it's synchronized across the major versions. But they also do differential loading by default. So if you're using a modern browser, you'll get a modern build from ES 2015 code. If you're using an older one, it might be a bit bigger, but it'll be ES5. The first thing we should do is actually look at my instructions. So I created a set of instructions that mimic what is in the blog post. Instead of having to read the blog post, you can just see all these steps that we'll go through to write the code. And so I use IntelliJ Live templates to pre-record a lot of this code. If you want to use those same IntelliJ Live templates, you can just grab the jar from my repo and import it. Instructions are right here. So I'll look at the raw version of this, which will give me an ASCII doctor. Nice, pretty view. I'll put that on the left. And then on the right, I'll open up a terminal. And I'll start by, instead of going to start.spring.io and selecting JPA, H2, Rest Repository, Lombok, and Okta, I will actually just use this shortcut. I'm using HTT Pi and it's basically going to download everything for me and use 2.2.0 M4. So we can create a directory. We'll call it Angular Spring Boot and see the end of there. And we'll unzip that demo.zip into a server directory. And if we go into server, we can open that up in IntelliJ IDEA. And I did choose Okta as part of that process. And so it's not configured yet. We don't really need it yet. So I'm going to go ahead and comment that dependency out. And we'll start by creating a car entity. So this is in the demo application directory. And I'm just going to do everything in one file because it makes it a little bit easier to see it all instead of creating separate files for each Java class. So I'll start with a car entity. You can see it uses Lombok Annotation. So we don't have to actually write out getters and setters. Makes it a little easy, especially for demos. And then we'll have a repository, car repository, which extends JPA repository. And that gives us all the crud kind of methods that we might need. And then repository rest resource will expose it at a slash cars endpoint so we can do all that crud. Not so great maybe in the real world because anemic domain models aren't a great idea to just expose your tables right on the web. But it works well for demos. And then we'll need some data. So we'll go ahead and use a application runner. And we'll go ahead and add a number of cool cars, a Ferrari, a Jaguar, Porsche, a Lamborghini. And then we'll have some that maybe you don't want to drive. Maybe you don't want to be seen in, especially if you're in high school, an AMC Gremlin, a Triumph Stag, Ford Pinto, and a Ugo GV. All right. So now we should be able to start this up and actually see those cars printed to the console. Okay, so that's all working there. And you might have noticed at the beginning that I am using Java 11. So it's pretty cool that Spring Boot 2.1 added Java 11 support works, of course, with Spring Boot 2.2 as well. So we'll create a cool cars controller now. You can see this is just a rest controller here. Uses that car repository. And it goes ahead and grabs all those cool cars, filters them to make sure it's cool, and then returns a rest. So if we restart, now we can hit that cool cars endpoint. And we can see those are coming back. Okay, we can also post to our repository rest resource and create a new car. So for instance, post 8080 since local host is the default, we can say equals bwbus. Now created it and then we could update it and give it a different name. You can see that works. So we can put post. And finally, we can delete. And there we go. It deleted it. So now, if we were to look at all the cool cars again, it's not in there. So it wouldn't have been filtered out. So then we'll use Angular CLI to develop the client side. And I already have Angular CLI 803 installed, I believe let's confirm that. Yep, 803 right there. So we'll create a new application. And normally, you can just do ng new client. And then it will prompt you for the other options. But I like to do routing enabled styles just CSS, and then we'll enable Ivy. So once that client is created, we can CD into it. You can run ng serve to see what it looks like dash, oh, we'll open it in your default browser. You can see there and open it up as a tour of heroes and just some basic documentation. So we'll close that browser and go back to our instructions. You'll see one of the first things I mentioned is to add Angular material. This is very easy with a ng add command. We'll just choose a default theme. And choose the defaults for the rest. Go ahead and open up this one. And then tell Jay. The first thing I'm going to do is create a car service to talk to the back end. So you can do that with ng g for generate s for service, shared car car. So that generates that and then I can navigate to it and fill it in. It's going to depend on HTTP client. So private HTTP, HTTP client from Angular. And then we'll have a get all method. This will return an observable type any. And that's only because I'm lazy and don't want to create an actual car interface in this application. But you could certainly do that. It only has a name and an ID property. And then in here we can use another shortcut, which is a HTTP client. This is from another set of live templates that I'm using. And so then we can do local host 8080 cool cars. And that's really all we need for that service. Because we're using HTTP client, you have to go into your app module and add the HTTP client module. And now let's generate a component to actually show or render that list of cars. So we can create a car list component and g generate component car dash list. And we'll go into that car list component. And we'll go ahead and change this to an H two that just says car list. And then we'll use a div here. And car of cars. And in here we'll do car dot name. So obviously we haven't hooked that into the car list component. That's why we're getting this red right here that says it's an unresolved variable. So in the car list, we'll inject that car service. And then in the ng on init, we'll do this car service. Get all subscribe to it. And we'll take the results. And we'll put them into this cars local variable. And then we'll add that variable. And we'll make it an array of any again, just because I'm lazy. Okay. And then the last thing is to go into the app component and get rid of some of this boilerplate. And we'll add that car list as a component here. So now we can start the client and you serve it up on 4200. And you can see it's rendering. But there's an error about cross origin request being blocked. And that's because on the server we haven't actually enabled cross origin resource sharing. So we'll go back to the server. And then this cool cars will add cross origin. Now we can restart the server. Now our client should load up just fine. And now we're getting those cars. So the next thing I want to show you is how to add angular material and, you know, make these components look good. And then also how to get that animated GIF from Giffy. So we'll switch back to our client. And the first thing that I'll do is go into basically the app component or the app module here and add the imports we need for angular material. So you can see there's a button module, a card module, an input module, a list module, and a toolbar module. We'll use all of those. So then we can just import those from angular material. Make sure you get the right one. So we have that working. And now in the app component, we'll make this into a better looking toolbar. So it's using the matte toolbar in the primary color. And then we'll also go into this car list component and make this into a angular card. Okay, so it looks the same, but you'll notice we have an avatar. We're using a list avatar from angular material here. And we're actually pulling in that Giffy URL, which we haven't done yet. So might not look perfect. Let's see how it looks. localhost 4200. We'll have seen this before it does give some mornings there, but restarting it usually fixes it. So if you add something like angular material and don't restart, then it can cause problems, but restarting it usually gets rid of those. Okay, so now we can reload here. Our localhost 4200. And you'll see we're getting that list of cars, and we have a placeholder for the image. And it also looks like angular material a bit. So we'll create a Giffy service. First of all, I'll just go ahead and create this manually. So Giffy service dot ts. And then we'll go ahead and use my shortcut for it. And step through this since angular six, I believe, you don't even have to, you know, register your services in your module, you can just use injectable and provided in the root. And that'll register it for you. This Giffy API, and the API key is something that I had to create. So you can certainly use mine for demos, but there's no guarantee it's going to always work or that it doesn't get deleted at some point. So if you want to create your own developers dot giffy dot com dashboard and create truth. So in here, we're using HTTP client, we're going that Giffy API with the search term. And we'll go ahead and pipe the results of that to a response data. And then we'll grab the first image from there. And this is an important optimization here limit equals one. If you don't do that, the limit is like 25 by default. And so you'll get a whole lot of data and you'll never use it and your application will be very performant. And then if that doesn't work, then dancing cat. So hopefully we won't get any dancing cat responses. We'll see how it goes. So to add that to the car list component, we'll add it as dependency to the constructor, Giffy service. And then down here, we'll go ahead and say, through our cars, go ahead for each one and grab the associated image that matches. So now we should have everything we need over here. As soon as that finishes compiling, now we're actually getting cars. And so I saw this earlier when I practice this demo. And that is for some reason, Giffy doesn't like Lamborghini and Bugatti because it does set cores headers on those or doesn't set cores headers on those but it does for Ferrari and Jaguar and Porsche. So let's open this up. Oh, well. So not sure why that is not sure why they don't come back with the 404, but that's not really the point of this tutorial because we're just trying to show you, you know, how to actually talk between two apps. And then I'll also add Octa for authentication. So we have Angular, Material and Giffy done. Now I'm going to add an edit feature. So I'll generate a car edit component ng gc car edit. And then in the car list component, I'm going to add a link to it. So instead of this car name here, go ahead and change that a bit. Grab that out. And so we'll just use a link. But you'll notice we added matte dash button on there. So it'll look like a button or it'll, you know, have a square like a button around it. And we'll use router link to go to that car edit component. And we'll pass in the car ID. And then I'll also add a add button. So it uses matte fab color is primary. And it goes to that router link of car add on the next component, we're going to be using forms module. So I'm going to go ahead and add that right away forms module. You'll basically get errors from Angular if you don't add a lot of these components into your module. So now we will go ahead and modify the routes in the app routing module. So instead of these routes, we'll use ones to go to the car list component and the car edit component. So you can see their car list, car edit. And car add also goes to car edit. And then we'll modify the edit component. So it has links to actual, or it has logic to go and edit a car. So you can see here it's an app car edit implements on a net and on destroy. And it takes in a whole bunch of dependencies here. Well, the real logic is right here in this ng on a net. It'll basically grab the ID parameter from the route. And, you know, these TS lent rules change all the time. So if I do that, then that works. And then the car service will call get on the ID. And then we'll go ahead and get that car and set the href. This is just a shorter indicator that it's actually an existing car. And they'll go ahead and grab a giffy image for that car. And then there's also save where it calls save on the car service and remove where it calls remove. So we need to add those methods to the car service. So we'll just have a couple of variables that define the main API and then the car specific API. And then we'll have a get a save and a remove for doing all the different CRUD operations. And then go back to our TS it should everything should resolve now. So there's no more red lines. And then we'll create a form for our data. So you can see here this is named car form. And when we submit it, it calls save sends the whole value of the form. And we just switch whether it's add versus edit based on whether there's a car name. And then we use a hidden field href to determine if we should save or edit that. And then there's a car name, which has validation, it's required. And then there's a submit button and a delete button that calls remove. And the submit button won't even be enabled unless, you know, there's data in this field. And then you can also cancel just goes back to the list. And it displays a GIFI URL. There should probably be some logic around here. We can do NGF on this one that says car dot name. So if that exists, then it'll show the GIFI URL. I'm probably even better to do the GIFI URL. So if that exists, it'll show it. Otherwise it won't show it. Put this car list component, it's already there. Oh, we can remove it now from the app component.html. And then let's see how we're doing then G serve. Now we refresh. Now we can actually edit. And we can add something like the ID buzz, which is the next Volkswagen bus. And you can see, look, it gives us an error down here about cores. So we're trying to hit that cars endpoint, not cool cars. And we're having cores issues again. So in Spring Boot 2.1, what I was able to do is add a cross origin right here. With 2.2, that doesn't work. Not sure why, but it does not work. So what I've noticed is adding a cores filter can solve that problem. So cores filter, basically, this is how you configure it. We can set the loud origins to go to just our app. You could limit the methods and the headers as well if you wanted to. And of course, if you're in production, you'll want to have numerous values here, not just localhost 4200, but another one for your production URL. So we can take out this one, restart everything. And now if we try to save it, it actually works. And we can click on it if we want to see what it looks like. So I do hope to get one of these because, man, that looks awesome. It's all electric, and still kind of looks like the original bus. So back to our demo. Now I'm going to show you how to add octa. And hopefully this is pretty easy, usually is. We want to uncomment this guy here. So 1.2.1. And then we'll rename this to be a YAML file. This is the configuration for most Spring Boot applications. And then I have a shortcut for the application I already created. So if you're doing this and following along, let me just show you how to create one. First of all, developer.octa.com, go to create for your account. You get a thousand monthly active users for free. That's how you create that. And then I already have one here. And to create a new application, you just go add application. And then you choose single page application. And then you'd be, say, like Angular 8. And change this to 4200. And then click done. And then you'll have the client ID you need right here. And for your issuer for OIDC, that is right here. So those are two values that you need. I already have this Angular Spring Boot application. So that's the value I'm using. You'll see it ends in 356. And if we look back at our code, that ends in 356 as well. So if I were to restart now, my back end is locked down. So I shouldn't be able to actually get to localhost 8080. It actually typed in the wrong one. So 8080. And it actually redirects by default. And that's because I haven't configured Spring Security. So by default, it expects OAuth2 login. And it will try to log you in before it gets to your server. But what we want to do is set up what's called a resource server. And so this is just an API. It doesn't cause you to log in. It actually expects you to pass in an access token. And then it allows you to access it. So we'll create a security configuration class. So you can see this is using enable web security. Extends web security configure adapter. And this is what it used to configure. So it says authorize requests and make any request authenticated. And this is how you set up a resource server with Spring Security 5.1. And then this is something that we add with our octa spring boot starter that gives a browser friendly response. If you don't give that, actually the browser will just give you a blank screen. So that can be confusing. So we'll save that and restart. And if we go to localhost 8080, you'll see it gives us a 401 on authorize, which is what we expect. Now what I'd like to do is commit all these changes to get, just because it's a good idea, especially when we're going to change a bunch of stuff. So the Angular app actually has a get repo. So you'll want to or makes it into a get repo by default, create that one, or delete the dot get directory, and then get init and then get add everything. And we'll say projects created. Okay. So now we have no changes in there. Octa has an Angular SDK that we use to provide authentication to Angular applications. And one of the things the developer evangelist or the developer advocate team at Octa wrote was this thing called Octa Dev Schematics that makes it very easy to add Octa Angular to any project. So all you have to do is ng add Octa Dev Schematics. You'll notice it's smart enough to know I need to be in my project. And this does a number of things. First of all, it'll install the dependency. And then I'll go ahead and modify your project so that it has octa built in. So you can see it added the dependency and it's prompting me for our odc apps issue or URL. So we have that in our spring boot application. This right here. And then the client ID as well. So it takes those it installs octa Angular, and then it installs the packages, and it creates a new module that has a security information creates a home landing page, as well as an auth interceptor, which will add a bearer token or an authorization header. And it updates apps module to add that auth routing module. And then it goes ahead and updates the basic components. So now if we go back to our client, we can see those changes. These are all the new files. And this auth routing module is where your octa configuration is. And then the routes a default route to the home, as well as a callback method that octa can call back to after redirects. And it sets up that authorization interceptor as well. Now, if you were to look in the app routing, we also have a default route. So you'll want to kill that one. And then in this app component, it's configured now to know if the user is authenticated or not. These are all still the same. But the home has similar authenticated logic. And it also has a login and a logout button. So the first thing I want to do is protect the car components. So if we go to app routing, we can add a octa auth guard. So we'll use can activate. We'll specify octa auth guard. And we'll do that for the other ones as well. And what that does is if you try to hit that URL in your browser, it'll redirect you to octa to log in. And then it'll bring you back there. So that's a handy feature to have. And then we can adjust the app component to have login and logout buttons. And still use that router outlet. So we have this toolbar spacer, which will put the actual logout button on the right side. And then if they are authenticated, we don't show them the logout button. We show them a log in button if they aren't authenticated. And then I do need some CSS for that toolbar spacer. And that just uses a flex layout to put it on the right side there. And then we'll also update our home component to use angular material. And you'll notice it gives me a couple red lines that are mac card and mac card content. That's because we have this home component is actually declared by this routing module. And so we need to import the angular material components in here as well, or the modules. So the mac button module and the mac card module. Now if we go back to our home component, the red lines will go away. This should be car list here. And so basically how this works is it'll show a login button if they aren't authenticated. And if they are authenticated, it'll show them a list or a link to the car list. Let's see if it works. So this is an expected error. There's no format with import statements in octa angular. And so that's because there's this issue with ivy that's out there that basically has ivy has issues with packages that are using common js or umd. And so if you scroll down, you'll see there's all kinds of people reporting issues with various modules like ngx cookie service and all that. So it's happening a lot to modules when ivy is released in september. I believe it will be fixed or there will be support. So watch for that. In the meantime, what you can do is you can go into tsconfig app and turn off ivy support. So unfortunate, but it's still opt-in and beta. So hopefully it'll be available soon and work with our octa angular module. So now if we go back to our app 4200, you can see we have two login buttons for some reason. So I must have messed something up. Let's investigate. See if we don't have two router outlets here. Make sure we don't have two homes here. And we'll check our home component. Let's try clicking on one. I think it's because this has this guy in it. So we don't need that. And our car list is a bit messed up. So let's go and make sure that that has the right text. Okay. So we're already logged in. Let's log out and we'll log in again. Props us to log in and takes us back. So one of the cool things there you notice that it keeps you logged in. So as long as your access token is valid, it will keep you logged in. Then you can go to your car list. You could add a new one. I really like that ID buzz. And you can delete it. And of course Ferrari is pretty cool too. So that's the basics of my demo. You'll see show app and rejoice. And you can go and read the blog post if you'd like to see more information about the various steps along the way. If you'd like this screencaster tutorial, I encourage you to follow Octadev on Twitter. That's my whole team of developer advocates. We power the Octadev developer blog. We post all kinds of tutorials on here about Ionic, Spring Boot, Node.js.net, all kinds of stuff. So go to developer.octadev.com. Sign up for a free account today. And if you like YouTube and you like watching screencasts like this one, I encourage you to follow us on YouTube and subscribe to our channel. Thanks for watching and hope you have a great weekend.