learn how to build web applications in Java with spring boot 3 you'll learn about Spring's Fundamentals by creating a rest API that communicates with a database and is supported by a comprehensive Suite of tests by the end of this course you will have learned what you need to start building your own web applications with spring boot 3 Dan Vega created this course he is a spring developer Advocate course creator and speaker welcome to this course building web applications in Java with spring boot 3 my name is Dan Vega I'm a spring developer Advocate at broadcom a Java champion and really excited to be here with you today on this journey so I want to start off by thanking everyone at free code camp for having me I'm a big fan of free code camp and I'm a big fan of the courses that are on the platform so I'm excited to be a part of that so today we're going to go on a journey together and learning the most popular Java framework around for building applications and that is spring spring is massive there are so many things that you can do with it we're going to kind of narrow it down today but we're going to have a lot of fun I will go ahead and leave some links if you want to learn more about me dana. deev is my homepage I have a YouTube channel so if you enjoy videos around Java and spring you can visit me there also if you want to learn more about spring and continue this journey I'm an instructor on Spring Academy which has a bunch of free resources for learning Springs so go ahead and check them out there with that I don't have any slides we are developers I have a GitHub repo with a readme in it so if you head over to uh github.com danan Vega FCC for free code Camp DS spring-boot D3 I'll leave the link in the description below uh that is the repo for all the code that we're going to go today but more importantly the read me that we're going to jump through right now so there's a quick agenda on here um I don't want to dive too far into this CU we'll talk about that as we get into it but module one just a quick introduction I want to make sure you understand who I am uh really quickly what are the outcomes what are the prew resits for this course what should you know and then a real quick intro to what is spring why why should you care about learning this thing module two is we're going to create the project we'll get familiar with the IDE and how to run the code and where to put your code and how to write the code and some things like Dev tools and logging so that'll kind of get us started get our feet wet get us off the ground module three is hey we're building a rest API here today using spring MBC we're going to do this in memory we're not going to talk to a database yet we'll kind of again walk before we can run and we'll we'll talk about all the mechanics to build a rest API from there in module 4 we'll switch over our inmemory collection of things to a database so we'll talk about all things related to setting up a database in Spring module five is talking about the rest client if you in a spring application and you need to talk to another service this is something we have to do in a lot of organizations how do we do it in Spring what are the different options how can I use them finally module six is testing now I know we don't usually save tests for last but I feel like when you're learning something new trying to throw in the mechanics of writing tests at the same time can be a little bit overwhelming so normally I would write a particular class and then write a test for it kind of tdd style if you will in this case we're going to write the application and then I'm going to come back and talk to you about what's included in spring for testing which is nice you don't have to opt in it's already there and we'll talk about some of the tests that I would have written along the way uh just to give you an idea of how to write tests I'll leave you with some resources and that'll be the course it's it's a lot of information packed into a pretty nice time uh but I think we're going to have a lot of fun with this so quick who am I I'm a husband and a father I have two daughters hashir Dad we live outside of Cleveland Ohio I am a spring developer Advocate at broadcom so I get to go around and talk about spring but I want to make sure we understand that I have been an advocate of spring long before anybody was paying me to do so uh this goes back years I've been a big fan of spring uh spring was previously uh held by pivotal and then by VMware VMware got acquired by broadcom and that's how I got to where I am now I was recently named a Java Champion which is really really exciting uh so I'm super proud of that I am a spring Academy instructor so we have a Academy where if you want to learn all the different things with spring or about all the different projects in the ecosystem we have many instructors on there other developer Advocates members of the spring engineering team uh so if you want to learn more about that head over to spring. Academy and I've been doing this a little while 23 plus years of development experience in various languages most of which have been on the jvm uh but I've been doing this a long time and I enjoy what I do so if you're going to take this course what are some prerequisites that you should have well first off we should have some fundamentals of java we need to know the Java programming language to build Java applications I would say anywhere from beginner to intermediate beginner if you really want to like if you really are able to like learn on your own great um just some fundamentals of the Java language so we need jdk 17 or more right now the current version is 21 22 is about to come out 17 is the Baseline for spring boot 3.0 apps we're going to use the latest version which at the time is 3.2.3 but uh we need at least jdk 17 to be able to run these uh you can go ahead and check your current version with java-- version on the command line um or you can check out sdkman if you're on Mac OS it's this nice little utility that allows you to install different versions of Java or other uh sdks and manage them in parallel so I can switch between like 8 and 17 and 21 Etc now I am using Mac OS so if you're on Windows um I don't have the equivalent of all these but like SDK man you can use something like chocy to install um but some of the keyboard shortcuts will be different I'll try and explain those as we go uh if you have questions as a Windows user try and ask them and I'll see if we can answer them so if you're a Java developer you should have some a little bit familiar with uh some build tools so once you get past kind of the hello world in Java you need these build tools to to manage your application right like hey these are the the dependencies that my application is going to have these are the build plugins like the steps that I'm going to take to like build an artifact that goes to production two of the big ones in the Java world are Maven and Gradle I'm going to use Maven if you want to follow along and use Gradle that's great too you need an IDE or a text editor I'm using intell idea Ultimate Edition it is a paid version I pay for this I have paid for this on my own monthly well now I think I pay yearly but at the time it was monthly and for the value of me of how productive I am in this tool it wasn't a lot they are not sponsoring this video this is just my personal thoughts on this um but there is a free version of The Ultimate Edition so the paid version you can get a 30-day trial if you've not done that yet go ahead and do that there's a Community Edition which you can use which doesn't have all the features but I'll try and point those out as we go you can also use something like spring tool Suite that is available in Visual Studio code and Eclipse one thing I try to tell everyone that I talk to when I'm teaching is to use whatever tool you're most productive in if that is somehow notepad or a terminal with Vim so be it I want you to be productive whatever tools you use to be productive that's great this just happens to be the one that I'm most productive in so I use that we'll need an API testing tool so uh if you've never tested a rest API we'll go through the mechanics of it but there are tools like Postman uh you can do this on the command line using something like curl uh or HTTP IE which is like curl for humans you can actually like use it and read it and understand it uh intell Ultimate Edition has a HTTP client built-in which I'm a big fan of I'm going to leave you in this repo in the API folder with the postman collection and the HTTP client collection for intell so whatever one you're using you should be able to download the collection and not have to write all these uh API tests yourself Docker desktop is not a hard requirement we are going to use an inmemory database until a certain point and then we'll swap it out for a postgress SQL database but we'll do so using Docker and Docker compose and some of the features in Spring around Docker compose which are really great I'm excited to talk to you about those so that's our prerequisites what is the outcome of this course so a lot of people ask me like how can I learn spring Dan well that's a big loaded question because spring can do so many things we're going to look at that in the next section spring can do so many things so when I when you ask me how can I learn spring boy you better a long time because just the roads that you can go down but if we narrow down this road and we get a little bit more laser focused and you ask me hey Dan how can I learn spring to write a rest API that talks to a database now we have a much more uh focused learning path and that's what we're going to do today we're building a rest API it talks to a database I'm going to teach you some of the mechanics around that some of the things that I learned leared over the years some best practices we'll write some test as we saw and yeah we're just going to learn a whole bunch of those things so what is spring what can it can do what can it do we'll talk about that in a second how to build a web application how to test it how to interact with the database what are we going to build we're building a fitness application that allows you to track runs through a rest API that's not the important part the important part here is to take what you've learned and apply it to your own project after you're done with this course you really need to go through the mechanics of doing it yourself and not relying on me being able to tell you what to do so take this and apply it to whatever you're interested in if you like cooking create a recipe rest API uh if you like lifting weights go ahead and and create an application like that so whatever you are interested in try to apply this after we're done here and that I think that will kind of really help cement some of the things we're going to go through what and why is spring so I'm going to click on this link it's going to take me over to spring.io this is the main website for spring we'll get into why in a second so what can spring do spring allows you to build so many different types of applications Do you want to build microservices so you have a bunch of services in an organization that kind of talk to each other uh there's some really great benefits to building microservices big buzzword these days right uh independently scalable so if we have one application that just needs to scale more than others microservices are great you can build reactive applications so nonblocking applications so we know in kind of the Java world where we have this thread per request we want to be able to not block our applications we want to be able to scale better um that is the case with reactive web applications but um jdk 21 just came out there are these things called virtual threads so if you're in a blocking style application there ways to kind of scale those applications now as well cloud is Big we talk about um and actually I wonder if we go into spring Cloud there's a video that we recently did and I'm going to just jump there now so if we go into projects and you go look at all the different projects in the ecosystem um here's spring Cloud there's actually some videos on here we did a a spring office hours video so this is the podcast that me and my cooworker desan uh run and we did a video where we kind of talked about all the different projects in Spring Cloud at a high level and what they do and this was really fun because we talked about spring cloud is basically the tool to build distributed applications in the cloud and when when you're doing this a lot of common patterns are going to come up that you're going to need to uh handle and spring Cloud gives you the tools for doing that so that's spring Cloud Web apps that's what we're going to focus on today building an MVC application that talks to a database you can also use spring for building serverless applications hey I want a function to sit on AWS Lambda service and when I send it a request it will spin up handle that request do what it needs to do and then shut down we can work with event driven applications we can work with batch applications um so much more another thing that I don't see listed on here that I've been using spring for a lot more lately is building CLI apps so if you want to build a CLI you might think well I would reach for something like bash Dan and that's great but I don't use bash every day so I forget how to like even do the simplest of things so I would be running over to chat GPT and asking chat GPT how do I build how do I do a for Loop in bash right so with spring CLI I can build those interactive command line applications using the tools that I'm familiar with that's a little bit of what can spring do uh if you go into why uh here's some great information on it uh again it's the world's most popular Java framework here's a really good quote from um Dicks Sporting Goods so we use a lot of the tools that come with spring framework and reap the benefits of having a lot of the outof thebox solutions and not having to worry about writing a ton of additional code so again we're starting with a web app but what if you need to talk to a database what if you need to build for the cloud what if you need to build reactive web applications all of those tools are in the ecosystem here all those projects are here for you and they all integrate seamlessly which is really great so spring is everywhere flexible productive fast secure supportive again what can spring do I think there was another quote on yeah this is a good one so if you don't know Netflix is a huge spring user and it says most of our services today are based on Spring boot I think the most important thing that spring has just been very wellmaintained over the years that is important for us in the long term because we don't want to be switching Frameworks every two years so spring has a huge engineering team uh we have releases on the spring framework side every year on Spring boot we have releases every six months and uh yeah I think that's an important piece so thanks Paul for that quote so you can go into why learn about that here you can go into to learn you can learn like an overview how to get started quickly but we're going to do that today today there are some really good guides these are kind of quick 15 minute to 30 minute how do I do this one specific thing so those are great but I'm going to show you those on Spring Academy in a second there's a Blog so get caught up stay with stay caught up with what's going on in the ecosystem and actually I think if I go to overview yeah so here's the latest videos our Spring Office hours is one of the latest videos on here Josh long who's a legend in our community uh has a podcast on Spring you can go ahead and check that out here are some popular guides projects we'll come back to in a second uh I mentioned the spring Academy if you go over to Spring Academy you'll see that there are some courses there we also have these guides these are the same guides that are in Spring IO but not all have been ported to the spring Academy yet the nice thing about these is that you can do this in the browser so this thing I want to build an application with spring boot you go through and there's integrated lab environment where you can walk through and do this yourself here so really exciting check out spring Academy for that then um we have Solutions so if you want to get support at a commercial level check out the tanzo Spring Run time we have some community and even that all important dark mode so quickly we're going to go into projects we're going to click on the overview these are all the different projects in the ecosystem so when you go into a project you'll give you you'll be giv an overview you'll be giving a learn section this is where all the documentation is so here's the reference stocks here are the API doc so if you want to get at the apis that's important and just as important the support timelines what is the uh open source support what is the commercial support timelines so I'm going to go to Spring boot we're going to be going through spring boot today if you go into the learn section and you go into the reference docs here is like Hey how do I get started with spring boot so I can go and click into a section get started these are some of the things we've talked about before uh but just documentation is really great one of the things about spring that you have to know is that it's been around forever right we just celebrated 20 years of spring 10 years of spring boot this is really great but it also means that if you go out there and search for a question on Google you might get 10 different answers and how do you know which one is up to dat which one is the right one so I suggest first line of defense is always starting at the documentation because this is constantly being updated this is being managed by the spring team this is a really good place to start all right and then there's some resources here I'm going to update this the reason I wanted to do this in a readme is so we can constantly update this and help you out I'll put some notes in here if I see issues come up we can go ahead and add those to this repo this is kind of our home for everything that we're doing today so that was our intro we're calling that module one module two is going to be getting started creating your first project writing your first code in Spring and I think we'll go ahead and do that now so I really hope you enjoy this uh course I'm gonna I think we're going to have a lot of fun on this journey and I'm excited about it and I hope you learn a lot so with that let's go ahead and head to module 2 all right so the best way to kick off a new spring boot project is by using the spring initializer at start. spring.io so I'm going to go through a couple options here we're going to create our first project and then we'll go ahead and write some code so we start off with what is the project type this is what is the build tool so I mentioned in the prerequisites that it'd be nice to know if you had some experience with Java build tools like Maven or Gradle and this is where those come into play because you need to pick a project type I'm gonna choose maven if you want to choose Gradle and you've used that before uh there is nothing wrong with that as well um in fact it's the default so uh language I'm going to pick Java you can also use cotlin or groovy and then we need to pick the version of spring boot that we're going to use I recommend using the latest stable version which at the time of this recording is 3.2.3 you can always upgrade this in your application so don't worry about it uh just pick the latest stable if you want so now you got to fill in some data about your project and the way this works is you have a group and an artifact and you usually use the reverse domain so my personal website is Dana dodev so I'll use the reverse of that which is dev. Dan Vega and then the artifact is what are we building here today what is the application called so in this case it's called Runners and we'll go ahead and use that name you could fill in a description a package name um anything else is fine now you got to pick a version of Java so we talked about at the beginning to use uh spring boo 3 you need at least Java 17 I'm going to pick Java 21 but I don't think uh you need to so if you're on Java 17 that's fine now we get to the point where we pick our dependencies so what are dependencies so when we're building out bigger or larger applications Enterprise type applications they're usually made up a bun of a bunch of different projects right it's not just like Java code there is hey I need to like use this project and use that project and use these two projects and that's how you kind of build these larger style applications in the world of spring spring has a bunch of different projects in the ecosystem and it will allow you to kind of construct your application I I liken this to going to the grocery store having an idea of mine in mind of what you're going to cook tonight right if I'm going to make a steak and potatoes and a glass of wine like I understand the ingredients that I need to get as I'm going into the store so as we're coming here to the start. spring.io I need to have an understanding of what I'm trying to build today remember spring does all of these different things it can build all these different types of applications so I need to have an idea of what I'm trying to build here today and we do we're building a web API today so we're build building a spring MVC app that talks to a database now the nice thing is these dependencies are just kind of quick starters like it encapsulates all the functionality of say building a web app but you don't need to know everything you're going to do today for instance we're going to talk to a database at some point but I'm not going to pick the data stuff yet because we're not there yet so when I go into dependencies I'm going to search for web and I'm going to choose that the other one I'm going to choose is the spring boot Dev tools and this is some really nice features for development mode so we're going to choose those and that's all we need from there I want to show you just a quick a quick couple of things you can go to explore and see what code it's going to create for you again this is more of a bootstrapping your application this isn't generating code based on what you're selecting there um so there's that then there's a share button if you want to go ahead and copy this you can send this to someone else and it will prepopulate the spring initializer for them here which is really nice so with that uh you're going to go ahead and click generate you're going to generate that it is going to download a zip file you're going to open that up in whatever text editor or IDE you're using again as we talked about at the beginning I'm going to use intellig Ultimate Edition you can use intell's Community Edition you can use Visual Studio code you can use spring tools Suite with like eclips um there are a whole bunch of different options here but uh if you haven't downloaded a version version of intell yet there's a 30-day free trial for the ultimate edition so I would go ahead and do that um but either way let's try and follow along if you have some questions or you're stuck on this part on how to open a maven project in a particular Tex header ID let me know in the comments and we'll see if we can answer that so that I'm gonna open this in intell and we are going to take a tour of that and write some code all right so we've opened the application here up in intellig I'm going to take a quick tour around one of the things I like to do I just like to rename this to application uh I don't like these long main application class names but you don't have to do that if you're not weird like me so um this is like a normal Maven project structure so it we have our source main Java this package contains all our Java codes so we have our main package here which was created based on all that metadata we filled out at the beginning in the spring initializer and then we have our main application class we'll come back to this in a second we have resources this is where we're going to have like static files or templates if we're building out like a UI uh there's also our properties files you'll also see maybe an application. yammo in here that's also for configuration uh so that's where uh that's our resources then we'll have a test package and under test we'll have Java and then we'll have a package mirroring uh our package structure in our application class so we are in here and then we have this Maven Maven Maven command and these are the maven wrapper so this means that you don't have to have Maven installed on your machine to be able to run this application there's kind of a wrapper included in the project and this is nice because if somebody else downloads your project they don't need to have Maven installed it makes everything so much easier the palm. XML is where all of our dependencies are declared so this is the maven build tool it has dependencies it has build plugins for things that we might need to do again these are the things that we picked at the beginning so if you wanted to kind of drill into these These are what's known as spring boot starters this starter includes a bunch of other dependencies and it's an easy way to get up and running without having to figure out all of the things that your application needs you can uh command click on a a Mac control click on Windows I think uh to look at the other dependencies in there so all of that is kind of the basic project structure that we get uh right out of the box all right so the main application class here is the uh it contains the main method so you know in Java every Java program needs a main method public static void main takes an array of strings uh called args and then in here it is uh using the spring application.run method passing in the class name with the args and this is how the main application runs so now that we know that let's figure out how to run the application so we can run the application a couple of different ways here in the IDE so we have these uh play buttons so you can run the actual class you can run the actual method uh you can come up here and hit the Run button so I'm going to just do it here and we're going to go ahead and click run you'll see some things going on in here one of which is hey the port that you're trying to run on is already in use uh so you may have that if you have like other applications running uh no big deal uh let's just go ahead and take care of that right away um so one thing you can do is use this tool called JPS and see which ones are running on which port in this case I know that I need to kill um this particular one so 92464 92464 464 Dan and now we should be able to go ahead and run our application and everything's running we'll come back to like what some of this Council logging is in a second but I'm just going to stop it there so that's one way to run it another way is by using Maven so we said that there's the maven wrapper included and we can actually run this from a command line I'm using the terminal integrated in my ID you could use uh whatever terminal you use pop open that and go ahead and run this using Maven so I'm going to to say Maven so so look at this so we have mvn we have uh mvnw so mvnw and now I need to give it a command now what commands are available to me so in intellig there is this nice little Maven uh Plugin or window that will kind of show you what is available and if you look in plugins hey there's these things what about spring boot plugin Well Spring boot has a bunch of commands one of which is spring-boot col run so we know that's one thing that we can do to run the application we can say spring Das Boot call and run and then it'll run the application does pretty much the same thing that uh our play button here does in the IDE um so I tend to go that way if you need to stop this you need to control see that and then I'm just going to close this out I will continue to run it this way but just wanted to give you that option because um that's how it's typically run on the server right it there is no ID there's no play button on a server it's run through that Maven W command so that's how we can start our application uh let's take a look at um creating some code the nice thing about spring boot is that it doesn't really put any uh restrictions on you on where you kind of create code that's a nice thing for me that's also a con I like to be told where things should go because if you're not sometimes you can kind of shoot yourself in the foot right so let's take a look at um some examples here of where you could put code and where you can not put code so this is the default package this dev. danan vega. Runners I could easily come in here and create a new package and maybe call this um fu. bar and inside of here put uh some kind of class let's just put a class that is called the welcome message right so inside the welcome message I would will create a Constructor actually let's just create a a method so we'll say hey I want to return a string uh we'll call this get welcome message welcome to uh the spring boot application and if you look in the bottom left I have like tool tips to show you like some of the keyboard shortcuts I'm using you'll also notice that I'm getting some assistance on code that is through uh co-pilot uh it's a great little tool so if you notice that uh it'll just kind of help us speed things up a little so I have this uh get welcome message I have this welcome message thing I'm going to mark this with an annotation uh we'll talk about more about annotations as we go but essentially what this should mean is that this class is available to spring so in theory that's what it should mean now if I go into my application and I say um VAR welcome message is equal to new welcome message uh I could do that right and then I could say welcome message dot what is the what did we say. get welcome message. Sout and we'll just print that and we'll go ahead and run this so in this instance let's take a look down here let's actually make this a little bit smaller because it's in the way so we have our message printing down here you'll see it in a second it says welcome to Spring boot application so this this is fine when we are controlling the instance of the class but as we will see throughout this course we are uh spring is an inversion of control framework meaning we kind of flip the onus on the framework to handle all of these instances for us anytime you see new we probably shouldn't be doing this this is a place where spring can handle these things for us so what I want to do is ask spring for that particular uh welcome message and see if we can use it in this case it's not going to work because we've made it outside of the default class uh so so we're in um outside of that main class you can also put this in a um default package so let's do that continue and let's move this so this is what's known as the default package where there is just no package right because it's in the um Source main Java where there's no package declaration so this is also going to exploit this issue so now what I want to do is um I want to go ahead and just get all of I'm I'm going to try to get an instance of that welcome message class again not to overload you right away we'll talk more about this there is this huge container of all the classes in your application called the application context and we can ask the application context for a particular class in this case the welcome message um so I want to try and do that here so what I can do is say hey this is the context and hey context I want to go ahead and get a particular bean and we'll get it by its name which in this case should be welcome message and we'll create a variable of that so this just kind of shortcuts in um intellig to kind of create this so I'm going to say welcome message right and that should work but what's going on here um it's saying hey I don't know what that is what is welcome message I don't see that and in fact even if I was going to make this an object and try and get this out of here let's just sis out welcome message let's go ahead and try and run this it's going to say hey I don't know what you're doing I don't have a particular Bean called the welcome message now Bean is one of those terms that like scares people I know it like what is that what's a bean a bean is nothing more than an instance of a class with some metadata around it so just think hey when you see the word Bean this is an instance of a class that the spring container this huge application context this container of objects is managing for me so all it's saying is I don't know what this welcome message is that you want to do that you want to access this is because we are outside of the main package so my first tip here with put with writing code is make sure it is within the main package so if we move this welcome message into here and now we go back to here and we say welcome message welcome message is equal to context. getbean um and what we can do is just say let's cast that to a welcome message and then get this out and then we'll go ahead and rerun this and now we should go ahead and print that out again and we actually just print out the we don't have a two string in this class so we print that out so that was just a long way of saying hey don't put code outside this mean package or in the default package because when we get into using Springs dependency injection inversion of control it's not going to work all right so you don't need to ever do this this was just for um kind of demonstration purposes there let's go ahead and rerun the application and everything is working so we have this log we have this Council here of things going on and let's just talk about some things that are going on in here so first off there's this Banner so it's saying hey Spring this is spring boot this is the version of spring boot that you're using and then there's some default logging going on so the nice thing is you don't have to configure logging out of the box this is already done for you if you were to start a new Java project a new Maven project you'd have to like figure out how to get logging up and running this is already working for you and so there's a bunch of things the framework is going to log for you and then you can add your own logging if you need to so let's try that real quick so in um any class you can go ahead and add a logger I have a little keyboard sh shortcut for this but all we're doing is saying private St private static final logger log and again if we look at our Imports we can see that this is coming from slf4j um that is the default logger in Spring Boot and we can say log factory. G log git logger for this particular class again this is something I create a shortcut for this is something I don't want to type out so whatever ID or text editor you're using um I suggest maybe creating a shortcut for that now that I have a logger I can say loginfo and I can say our application has started successfully now when I go ahead and log this I can see that this is there now I have a log message saying that this started successfully now if you you shouldn't be brand new to the Java world so we should understand that there are some different levels of logging like debug warrant error Etc Trace Etc and we can kind of change those logging levels what do we want to see in the loging so go ahead and check out the mentation uh to dive a little bit more into that so what we see here is that um we have uh no active profile we'll talk more about those later we have our Dev tools uh Set uh so we have Dev tools enabled which is good uh what does Dev tools do for us so Dev tools does if we go ahead and do this when we hit save it should automatically restart the application for us so that way I don't have to constantly like make code changes and restart something now you'll notice it didn't change and that's okay depending on what text editor ID you're using it might be automatic it might be something that you have to change so if I come in here and I go to build and I go into build tools Maven um we are looking for the compiler build project automatically so I want to say hey go ahead and build this automatically so I'm going to just add this loginfo in here and something changed and let's go ahead and click save and see if that changes it and what we're looking for is that automatic restart so you can see it restarted something changed and now I could just close this and constantly work on my application now it's only going to restart when we change our code like the something that's happening behind the scenes is not going to restart this so this is nice because I don't have to remember to always restart my application the other thing Dev tools does is it sets a lot of sensible defaults so um we don't have any examples of this right now but like later on when we use something like an inmemory H2 database when you're using this in development mode you'd probably want the H2 console enabled this is a UI that you can go in and like see your database uh tables and columns and rows and Etc and so in Dev mode I of course I want this on I don't want to have to go like enable this it automatically enables it for us so that's Dev tools um and that's logging let's go ahead and start to write our application out let me go ahead and clear some of those Imports I'm going to save this and I want to uh start to write our application now what we're going to be building here today is just a simple Fitness application to track runs I like to go out and runs so I want to track different runs that I'm doing and uh it's not that exciting but the important part here is I put this in the documentation as well is I want you to go through this today learn the kind of mechanics of building this application out and then take this and apply it to something in your life if you like to cook make a recipe application if you like to lift weights make a a lifting application if you like to um uh go out and whatever it is you know uh try to apply this to whatever you're doing in your life so again we one of the things I love about spring boot is it's going to allow us to create code anywhere but this is also a problem we can kind of structure code however we want there's two kind of popular ways to structure code there's more but let's just start with these two there's two ways to kind of structure code you could come in here and say I'm going to package by layer and what are layers so in an MV app you might have things like a controller a Model A service um config repository Etc there are all these different kind of layers of the application and some people and I you know I've did this forever as well may uh structure their application this way the problem with this is is I know where all my controllers are so I have a run controller a user controller a type controller whatever it is is right I know where all the controllers are but the controllers when you're in this controller package will always have to talk to something outside of this package right like a run controller would have to talk to a run service so both of these things need to be public so one of the things that I like to do is use a technique uh an architecture called package by feature so I'm going to come in here and say run run is the feature later on we're going to be doing something with uh users to to be able to work with the rest client so I may have a package called user so now I know that everything revolving around a run is in this particular package I can find everything quickly everything is in the same package it can live in the Java world of hey everything by default is package private so everything can kind of talk to each other in this package so we are going to model our application after a run so I'm going to come in here I'm going to create a new Java class and I'm going to call this run so right away I'm going to just tell you that I'm doing this the verbos way first the long way just to kind of show off some features of java if you're not used to it um so what I'm going to do is hey what what are all the fields that this particular class needs to know about wow co-pilot's on its game today look at this um okay so ID title started on completed on Miles and location yes and look at all this code that it needs to generate it needs to generate a um all of these fields so these are private Fields a public instructor that sets all of these things um and then has Getters for each of these um so and most of the time you have like Getters and Setters right so I might come in here and I might say generate my Getters and Setters let's do that for all of them um I might have a equals and hash code so I might do that for all of those and then I might have a two string so I have a two string and all of that and now we have a hundred lines of code just to represent a simple run in our system of course if you're a Java developer you know where I'm going with this but we can get rid of all of this and in fact I'm going to go ahead and just delete this and I'm gonna go ahead and say uh let's create a new Java class called run and this is going to be a record so now a record has record components so something like an integer ID uh string title let's see I'm going to put these on different lines and we have an integer ID string title uh string started on actually I want to do this as a local date time and we'll do that for this this so this is a local date time and then we have a location which I'm actually going to create uh an enum from uh so let's create why is that oh that's why so let's do that all right now we should be able to it's not letting me create that let's just go ahead and create a Java class called location and this is going to be an enum so it has a specific set of values that we can pick from in this case I'm going to say indoor or outdoor that's all I need to know is it an indoor run or is it an outdoor run so great so that is a record look at all that code we got rid of we're down to 12 lines of code and I could put this on one line of code I just think this is more readable and we have this nice run record that we can go ahead and create instances of runs with so let's actually do that let's I say we go ahead and create a simple run in the system just to kind of test this out so one place I can do this is in the uh application class I'm going to go ahead and delete that so I'm gonna create something called a command line Runner here don't worry about it we'll we'll get into this as we go throughout the course but a command line Runner is just something that runs after the application is started and more importantly after the application context has been created this container of all the beans in the system right so what I can do is I can say um something like this and that would get run after the application has started I just want a simple way to test my run so I'm going to say run run is equal to new run and we need to pass in an ID uh let's see if this is good so uh title uh started on so we are not going to use the string version of this we can actually let's just simplify this so this is a local daytime I don't know why I'm letting co-pilot do all this let's do this without co-pilot so I'm going to say local dat time. now that's going to be my started on I'm going to say local dat time. now. plus now I can add some amount so I'm going to say uh one and then what is the temporal unit so we can say Chrono unit. hours and now we have our completed on so completed on how many miles did we run let's say we ran five miles and what is the location so I'll say location. Outdoors because it's nice today I want to get outside and run so all I want to do is go ahead and log that now because uh one thing I didn't mention here is the class that we created had all those Getters and Setters and equals and hash code and two string a record has all of those components as well the nice thing is though this is immutable once you create this record you'll see there's no Constructor here um there's no all ARS there's basically an all Arc Constructor we create an instance of the run and then we can get at the values but we can't set them we can't change them later and that means that this class is immutable but it also means this class comes with a two string and equals and hash code skitters for all of those fields or they're called record components here but all mechanics that we need to create a run and get all of that information is there so let's go ahead and rerun our application see what we have and now the two string is automatically called it says hey here's the run id1 here's our title our started on are completed on miles is five and the location is outdoors all right so with that I think we have all of the kind of infrastructure every the the knowledge to kind of get around our application we've written some code we have this run we have this location that's really everything we need to start building a rest API we'll call module 2 complete and we'll head over to module 3 where we are going to create a web application together we're going to create a rest API using spring MVC all right so this is module 3 uh web applications using rest apis now we have our application running if you look down in the count so we see that Tomcat has started on Port 880 all this means is that we have an embedded Tomcat server so something that can serve up uh an application and take requests and return responses and that it's running on 880 this means I have an app I should go ahead and test it right let's hop over to the browser go to Local Host 880 I'll just refresh this and you see that there's an error that's because we haven't done anything yet we have not set up any end points for this application to respond to so we're going to do that now and we're going to talk about really quickly uh spring MVC so MBC if you've come from another language another framework you might have done this before MBC stands for model view controller model is the thing or the type that we're going to work with in our case we've already built out uh the run and the location so that is the model the view is how are we going to represent this thing this run in our system sometimes you might display this in like an HTML page in our case it's a rest API so where the view is going to be the Json that is returned as data and then the controller the controller is the traffic cop of our system it is going to take in a request it is going to figure out what we need to do with it delegate to some other service to do things and then return a response controllers are very dumb taking a request return a response don't do anything else so we're going to have to delegate to some other classes to do those things so that's what we're going to start doing is we're going to create a run controller so I'll come into my run package I'll create a new Java class I'm going to call this run controller you can call it whatever you want it doesn't need to end in controller it's just kind of con a convention that you'll see in the spring world and it makes it easier to kind of just look at a file name and say okay I realize that that is a controller so I'm going to make this a controller and if you did nothing else this would not work right so there are uh there are these things called annotations in Java and if you've been around Java you've probably seen them and these annotations kind of add some Behavior to your um classes to your methods to your fields and so you'll see a lot of annotations in spring because it cuts down on the verocity of having to write all this extra code so what we're going to do is we're going to use a couple annotations one is going to be rest controller and it says hey this is a controller it's a rest controller so we we expect the response body to be in some form by default this is going to be Json so we're saying that this is a rest controller now we can go ahead and create a method let's say public and I don't even need it to be public let's say it's a string and we're going to say let's just call this home and we're going to return hello Runners basically our application what we need to do is map this method to an endpoint say when somebody accesses a specific endpoint here's the method I want you to execute so we can do this a couple different ways there is a request mapping annotation and this takes uh both the path and the request method so in this case it would be a get now there are specialized versions of request mapping that I'll probably use the most these are for each of the request methods so a git mapping put put uh post delete Etc so I'm going to say that this is a git mapping to /hello and that's all we need so if we go ahead and rerun our application now there'll be an endpoint for SL hello this method is executed what is returned in this response is just a string uh hello world so let's go ahead and look at this again nothing at the root but if we go to SL hello there is our string that's being returned hello Runners so that is kind of the Crux of that's the getting started of a controller now what I want to do is is really start to build out um a crud controller a crud rest API where we can interact with the runs in the system now the runs in the system are going to be in memory first let's walk before we can run let's create an inmemory representation of all the runs in our application and then we can play with those we can return one we can return all we can create a new one Etc now what I said before was that control are very dumb they shouldn't be doing a whole lot of other things so one thing I could do I could come in here and say hey I have a list of these runs I want you to go ahead and manage these for me we'll call them runs let's say new array list and boom uh we can go ahead and start managing the runs here but again the controller should take in a re request return a response not manage any other logic do anything else so what I'm going to do is split this out into another class and Del at those operations uh to something else so I'm going to call this a run repository so there's a repository uh pattern uh for data access and we'll kind of use that we're not accessing a database but we are going to encapsulate some of that like data access there so I'm going to call this run repository and I'll go ahead and create this here so now I have a list of runs all right and in this run repository the first thing I might want to be able to do is get all of the runs now there are no runs all we did is initialize this list there are no runs in there yet we we'll come back to that in a second so I may want to say hey I want to return a list of runs and this method is going to be called find all and what you should do is return runs great but again Dan there's no runs in the system yet how can we do that so um in a class there are some uh different annotations that we can use in the life cycle construction of a class again we talked about beans and application context we'll we'll start to dive into those more and some of this will start to make more sense but in the creation of this class when it when it's get gets put into the application context it follows this life cycle one of the uh annotations that we can use here is post construct let's go ahead and take a look at that and what does this say uh it says it's used on a method that needs to be executed after dependency injection is done to perform any initialization so this is going to do some initialization in this class just think of that don't worry about dependency injection and stuff like that so I'm going to call this uh this actually needs to be a uh private void a knit and then we can go ahead and add some runs I'm going to paste some code in so we don't have to watch me type this out so the class gets created this method gets called we add two runs to our list now we have have some runs in the system so if we call find all we can get a list of those runs now it's time to start talking about some more of these annotations so again I talked about in the Run controller we mark this with that rest controller if we were to move this away this class wouldn't work it wouldn't be able to respond to requests and that's really what this this rest controller annotation is saying hey I am a class that responds to requests returns responses right so this is one of those annotations there happen to be a bunch of annotations in Spring and again you can kind of command click into them uh this is actually annotated with at controller which is another special stereotype annotation um and at response body so it's actually made up of two annotations but the at controller is actually made up of another annotation called at component and at component is really what tells spring hey I want you to manage this class for me the cycle of this class the dependencies that this class has you are in charge of this class at the Run repository level I haven't done anything yet I'm saying I'm managing this class I'll worry about this class but what we really want to do is tell spring hey I want you to be in charge of this so I could add act component and that would fix things but there's also specialized versions of this one of which is at repository at service at controller rest controller the these are no more than just at component annotations but if you wanted to do something fancy like hey find me all the classes marked with at repository you could so this is now in the application context so spring has an instance of this class Force that's important to remember we'll come back to that in a second so we have this class that has the ability to store runs we have a method that can find all of the runs in the system so what I want to do is go back to my run controller and I want to go ahead and get rid of this and I want to write a method that will return a list of runs because because again the Run repository isn't available to the public the controller is what takes in a request that request is hey I need all the runs and Returns the responses here's all the runs so this controller method is saying hey here's a list of runs I am going to call this find all and how am I going to get a list of runs let's just call it null for right now so now to return all the runs in the system I need to get an instance of that run repository right so one thing I can do is say run repository I could go ahead and create a Constructor I'm going to go none at this time because I want to show you the wrong way to do it first and this is the wrong way to do it so well let's talk about it so I'm saying the Run repository in this class to create a new instance of this just use the new keyword like we are used to doing in Java and create a new instance of the Run repository class as we've talked about spring is an inversion of control framework anytime you see the new keyword when we're creating new instances of something other than say a type like a run when we're creating new instances of classes little alarm Bell should start going off in your head and go why am I creating a new instance spring probably already has an instance of this and it all and by the way it does some other things in there like run that post construct for me to initialize that data so anytime you see a new keyword start to think about that and think okay maybe I don't want to do this because what if this controller takes in a thousand requests so you visit this controller I visit this controller 800 other friends visit this controller every time we create uh every time we hit this controller we create a new instance of the Run repository and that's not what we want there's only one one run repository it's a single tin in our system and so we want to just get the one that spring has available to us and this is what is known as dependency injection so instead of doing this what we're going to do is we're going to ask for an instance of of that so we're going to ask in the controller Constructor for a run repository and I'm going to call this run repository and then I'm just going to say this. run repository is equal to the Run repository that gets passed in as an argument now in intellig here I can see that that worked because I have this little gutter icon saying hey I see a run repository and I manage it I can go ahead and do that for you now just for fun let's take this uh annotation off and go back to our run controller now spring is saying hey I can't autowire one of those in for you I don't have one of those things I don't have an instance of that because you haven't told me about that class that you're creating so um you can uh go ahead and undo that and that will fix that issue now sometimes you will see in older code you'll see an at autowired annotation right on the field itself this is what's known as field injection and this is not um suggested and actually uh intellig right here will say hey field injection is not recommended there are some reasons not to do this one of most is testing if I wanted to be able to mock out this repository and pass in a stub or a different version of it it becomes very hard because this is using reflection so what happens is it's actually doing that on the Constructor but because there's only a single Constructor there with with some arguments uh this is implicit so you don't need to add that annotation so at the end of the day there's a run repository spring knows about it it can inject it into this controller when it creates an instance of it and we have a class that we can now use now we have a run repository now we can say hey the Run repository has a f all method let's call that to return all of the runs now we need to create that git mapping again again there is no there's no mapping there's no endpoint for someone to visit so what I would say is let's go get mapping and I think I have I'm just checking the final and I'll say this is atapi runs that will return all of them so let's uh and actually we don't need to go ahead and restart application because uh it will restart for us so let's go back over to the browser and let's go to SL API runs and let's turn it down a little and now we see the when we execute that endpoint we get all of the runs back so we have two in the system because we loaded two up in that uh anit method and so it's bringing back those two runs pretty good so far let's start to improve upon this a little bit so first off this SL API runs I might start to replicate this or duplicate this over all of the crud methods in my system right so I might have a git mapping for uh SL API runs whatever ID uh for API runs for the post for the put delete Etc so what I'm going to do to like cut down on some of that duplication is I can set a request mapping at the controller level so this is API runs and then every method that has like a git mapping a post mapping a put mapping falls under that base URI right so now what I can say is um this is nothing this is SL API runs that will call find all then I can say SL API runs ID that will return the ID right or that will return just one so let's actually do that real quick let's say run find by ID and uh maybe we want to use the Run repository to find by ID I'm just hardcoding in a value of one because we'll come back and we'll fix that in a second but let's go back to our run repository and let's create a method that returns a run called Fine By ID and takes in an ID and then says that looks pretty good actually we don't even need to throw an exception first and we know this will work so I'm okay with that so let's just do that for now again not the most ideal place to do it but this will work so now I can go ahead and rerun this application again don't need to Dev tools has restarted for me and now I can go to slash runs1 and I get just that specific one um I can't go to slash two or three yet because we've kind of hardcoded that in there and so that's kind of the next place that I want to talk about is uh being able to use Dynamic variables in these paths so we have a slash one here but we really want a placeholder for an ID right we want to say hey whatever is in this um path I'm going to consider an ID and I want you to use that ID now the way that we get that and pass it to our method our fine by ID method here is by using an annotation called path variable so that path variable is going to pick it out of the path and assign it to whatever we create here and I'm going to say that is going to be an integer of ID so we can pass that now now this is dynamically passing whatever is in the path to this particular method and uh should go ahead and use that still saying we have an issue but I don't think we do so um I'm going to go ahead and save let's go back to our browser see if one still works it does let's see if two works it does and now we know that something like 99 is not going to work it just returns an error because we haven't handled build that exception so so far so good this is uh off to a good start all right so one thing I'd like to improve on right away here is the find by ID when we passed in 99 it through an error and so let's go ahead and fix that I want to go ahead and instead of returning a run here what I want to do is actually return something called an optional of run so what is an optional in Java if we go ahead and click through take a look at this it is a container object which may or may not contain a non-al value if the value is present we have this method called is present uh that will return true so it's just a way of being able to uh operate on objects without uh having a n value present right all right so to fix this I'll just remove that and that will return an optional so back in our run controller we're going to have to kind of change things up here what we want want to do is we want to check to see if it's ail if it's there first so in this case I will not return this I'll say run repository. find by dfar is going to return an optional of run we'll call this run and then what I want to do is say if the Run dot so you can do a couple things you can say is empty or is um is present so if it's empty I want you to throw a new exception and we're going to call this let's actually do a response status exception and we can say HTTP status not found and our run not found now we can also throw a custom exception here talk about that in a little bit but if not I just want to return the get method so I'm actually returning the run that we retrieved so this should be a little bit better uh we're actually I saved the file reloaded let's go back to the browser and try to look at run 99 so now we get a 404 not found instead of that 500 message now one thing we've been looking at is just kind of testing this out in the browser but I also want to show us that we can do this in the terminal or from a command line you can use whatever command line tool uh you're familiar with there is curl curl is great because it's installed on everybody's machine but it's also there's a lot of things you have to understand about curl I like this program HTTP iie because I just type in HTTP what I want to what port I'm on SO in this case 880 so this is basically a request to http Local Host 8080 and then SL API runs and we can see that because we've kind of Switched context right we're no longer in the browser we're on a command line we're able to get back the response here here's some of the headers so uh we're using http1 one here's the content type so we're using application. Json here is the response now I can say uh give me just the first one or give me that 99th one that doesn't exist and we'll get a error there now again this is a 400 we can handle this a little bit better uh and we'll do so in the future but at least that's a little bit better than we were doing before so we're starting to move along right we have our controller methods we are starting to build kind of the crud we have the list we have the find by ID now we need to do let's say um we need to create one which is post we need to update one which is put and we need to delete one which is delete so so how can we create a post all right so I'm back in the Run repository I need to create a new method in here to be able to create a new run so let's go ahead and call this yeah what the return type do I need to return the Run probably not because I'm passing in all the info I know what it is already so I'm going to say void create it's going to take a run as an argument and then it's just going to add a run to that list and that's all we need to do there now this run is basically going to be mutable right so uh do we need so that should work let's talk about it from a controller's perspective how are we going to handle handle this so I'm going to create a method uh to create one so I'll say void create and it's going to take in a run somehow we'll come right back to that we'll use the Run repositories create method and pass in that run now here's where it gets a little bit interesting we have this run and what we need to do is we need to somehow tell this controller that this run that is getting passed into us is going to be coming from the request body so if you've ever worked with arrest API for you know that you like hit a certain endpoint and you pass in a body as part of the request to use and that'll in this case be in the form of Json it'll be a Json object with the yid title started on create you know what are all of those fields as part of that request now the way that we tell spring that hey this argument is going to be part of the request body is as you guessed it an annotation we're going to say request body and now it know knows okay this is coming in as part of the request body so this is great um up until now we've been testing everything kind of manually using the browser and the command line which is easy for get requests right because a browser can respond to a get request our command line is easy to use with a get request but now we have to send a post request and we need a tool to do this in so I talked about this in the prerequisites but basically there are a couple options we could do this from the command line it's a lot to remember I'm a visual person I like to be able to see it uh run so there are two tools that we can take a look at here and I have a um in the main repository actually let's go back to the browser if we go back to the main repository you'll see an API folder and in the API folder you'll see a postman collection and a HTTP file this is the intellig collection so if you're in post post man you can load up this collection there's a way to import that um by opening that file and now what I can do is just click on one of these and actually let me close all of these because I think some of these are older uh don't care don't care don't care all right so now that I'm in here I'm in the find all you can see that it's going to Local Host 80 API runs and it's a get request we can send that request we can get the pretty view or I'm sorry where's the pretty view of all the runs in the system right we can go ahead and find by ID we know there's one in there with an ID of one we can get that back now we could start to use the other ones here this is the create one so this is going to send a post request to localhost 880 API runs and this is the request body we see that we're sending it raw but this is also a Json type so we're sending in this request uh um and I think I may need to update this because this one is for probably the end result where in the case of a database we may not send an ID in this case uh I'm going to hardcode the ID in that I'm going to send because again this is an inmemory collection so I'm saying here's my third run send a post request and then H go ahead and make this happen so I'm going to send this and see what happens we get a 405 method because it is not Cloud so let's go back to our code and the reason for this is we haven't annotated any methods in here with a post maing annotation so the only methods Allowed by default are I believe get in options I don't even know if options is by default but what we want to say is hey I have a post mapping here and all we're going to do is use the empty bra empty parentheses here because again that's going to go to slash API runs so I've saved that I'm going to come back over here and attempt to do this again and you see nothing is returned because again we said void don't return anything but I also get like a 200 back and and I'm not really sure like if something got created now one way I could check this out is going over to find all and clicking send and oh there's a third run in our system it did get created but I wasn't really uh kind of notified that it was created so I'm going to do one more thing here and I'm going to add another annotation here called response status and what I wanted you to do is if you're going to return something in this case you're not returning anything you're returning a response though I want you to send the response status of HTTP status. created this is a 2011 as opposed to a 200 and what this does is it notifies the sender that something did happen it was created so I'm going to go ahead and send this again now I see that I got a 2011 created I don't even need to go check anything else I know it's there because of that response status that was sent back to me so just one little nice feature that we can add to go ahead and uh update that okay so we're getting there we're going to go back to our repository we need to add a couple more methods for uh updating and deleting so let's go ahead and do the update let's say void update oh boy you're getting good co-pilot so I'm going to say optional run is hey let's find the existing run that you're asking me to update if it exists uh so if that existing run is present remember the optional returns back uh this optional that has an is present method on it if it is present I want you to go ahead and set the index of that existing run to the run that I passed to you all right so that's one thing thing now let's say um what if we wanted to delete um runs go ahead this is a collection remove if uh the run. ID equals the ID that we passed into that looks pretty good so now I'm going to go back to the controller we're going to create a couple methods here so the first one is going to be a put so we're going to say void update so we're going to get the run just as we did in the create we're going to get this through the request body then we need the ID of whatever um run we're trying to update so at path variable integer ID use the Run repositories to update that that looks good but now we have no way to respond to this yet because we haven't created an endpoint we can do so by using the put mapping anotation and the ID as a dynamic variable because we've assigned it using the path variable so now we can respond to a put request now we can respond to gets posts puts how can we respond and actually let's come back one more thing I'm gonna add one more response status and I'm just going to say no content like it's okay this is a 200 um I'm sorry um instead of sending a 200 this is done we actually have no content to send back to you right just again informing the user of what's going on so we'll do that here as well I'll also say that this is a delete mapping to slid and then we'll just say void uh Delete path variable yes call that so don't worry if we're not following along all these methods don't worry we're just kind of building out the crud of the system we'll kind of enforce this as we go along and we move away from the inmemory representation to say a database call so we've restarted I'm I'm going to go back to postman so now the system has restarted so there's only two in there right now right because we've sent uh because it restarted and when it does it initializes those two runs but now we can go in and we can create one so let's go ahead and create one we got a 201 so we know that's been created in this case we're going to update three so whatever whatever that was before we're going to call this and say update that uh we have a 204 so not a 200 204 says yes everything was done everything was successful but I have nothing to send back to you and that's okay uh so now we know that that's there let's go ahead and look at that and there's our three with our updated um record and then finally let's go ahead and delete one so I'm going to call localhost 880 API runs 3 so if I send that in we also get a Noe content and if I go back to find all I'll only have my two my system so that's Postman being able to test your API that's important I also included a um collection for using an intell and I think I'll do that I'll copy that into this project so let me say API and let me find that and so if you're using the intell ultimate edition you can come in here and just click on this you can actually run these right in intellig which I like not having to leave the ID here is the two in my system if I wanted to get it one by ID I can if I want to go ahead and create one I can all is good now again you can do this through Postman you can do this through intelligent you can do this through curl but as we start creating these methods it's good to manually test these we will write some tests for these letter these automated tests but this is good just a kind of good scene check to make sure everything is working okay all right now one thing like to do is kind of improve on some of the error handling that we're doing here uh we could go into a lot more detail on this but just for the sake of time I'm just going to kind of clean up one thing here so I have this throw new response status exception hey response not found but we can kind of clean this up and actually create our own exception so what I'm going to do is go into main Java into run and I'm going to create something so new class uh run not not found exception right that looks good and this is going to extend the runtime exception class and we can just say run not found but more importantly I'm going to add that response status on here and say hey this is a a not found so I want you to return a 404 so now back in here I can just say Throw new run not found exception uh let's see if that saves let's go back to maybe our test here uh let's go ahead and do this in here and let's just say that we try to find by an ID that doesn't exist so let's copy this and say by ID that doesn't exist and let's say 99 so let's go ahead and try and run this and now we just get that nice 404 hey this is a run not found here's the path so we could see that it's API run 99 so that's kind of one good Improvement uh something else we need to think about is when we're creating these new runs we probably want to validate some data right like if we just accept whatever the user sends us that's probably not going to be a good time we need to make sure that whatever they're sending us is valid data right so there are a couple different ways to do this I'm going to show you two I'm not a big fan of mixing and matching these but I just wanted to kind of show you both ways to do this so one thing I want to do is I want to make sure that um when we create a run so here is a Constructor for a record I want to say if the completed uh if completed on sorry that should be that then what I want you to do is throw a new illegal argument exception and saying hey that completed date that you sent me has to be after started on you couldn't have finished a run before you started it right so that's one one level of validation that we can do another is by using something called the validation API um and this is going to be an extra dependency that we need to bring in so this is one of those things if you're on start. spring.io and you go through your dependencies you can select validation and that will bring it into your project but as I said there are going to be times where you're working in a project and realize you need another dependency and we need to go ahead and bring this in so I'm going to type in dependency here and I'm going to say spring boot starter validation and that's going to come from uh org. springframework dobot and if you're in intelligent you need to click this little reload button that says hey bring in those external dependencies that we just declared and now we can use them so now in my run now I can use the bean validation API and with that comes a bunch of constraints so one thing I could say is hey I don't want this title to ever be empty so how can I do that can use the not empty annotation and you'll see that it comes from Jakarta validation constraints not empty if I look in the constraints package here you'll see a bunch of different constraints that we can use hey make sure that this is an email make sure it's in the future make sure it has a Min or a Max make sure it's not all past past or present there are all these validations that we could take advantage of here so I'm going to put one more on uh miles and make sure that it's positive I don't want you to be able to enter negative five miles because an integer could be negative but in the case of miles that shouldn't ever be negative so now I have some validation constraints around this um this will automatically get run anytime we create a new instance of a run so we're not worried about this one but these are validation constraints saying hey when somebody asked asks if these are valid I can let you know if they are or not so one way we can do that is in the Run controller when someone creates a new run hey please go ahead and validate it so we're using the at valid annotation so before we even call this run repositories create method spring is going to validate that the object that's getting past in is valid based on the rules that we gave it if it's not it's not even going to go here and it's going to throw a 400 bad request again letting the user know that something went wrong so this has been saved I'm going to go back over to my Runners here and I think I have an invalid one in here yeah so here's one let's go ahead and remove the title too so I can say this and I can go ahead and try and post this and right away it's going to say hey that um thing that you're trying to create the completed on must be after the started on okay well that's good I've got some information there um that looks like it's working so let me fix the completed on and the started on so that those are valid and let me run it again and um you are response body 2011 oh because we have a title there oh that's why now this should I think I did the wrong one right um nope that's still sending a 2011 so let's make sure that we are validating this title so run not empty that's true we don't want it to be empty and in our run controller we are saying at valid we actually want to do this here too um let me just make sure that the server restarted it's okay doing a little debugging is fine uh let's try this again let's go over to Runners and let's create a new post and uh now we get our 400 and we're saying here are the errors that are happening with this if you don't see all this verbose logging of what went wrong then you might not have Dev tools on the class path remember one of those things that I said that Dev tools does for you is restart your application when your code changes another thing that it does is send some sensible defaults and this default to kind of log out this um more information on these errors is one of those things so it says Hey validation was run there's a problem where is it it's on the title and the title cannot be empty so so we're seeing some information there and if we go ahead and fix that title which we did in the good example then it will go ahead and run and save our new run so that's a little bit about validation again you can kind of do it at the class level this you could also write a custom constraint for so there were all the constraints that we saw um there's some there's a way to write custom constraints I will say when it involves another property can get a little bit more detailed on how to write those custom constraints so I found this so much easier again I I don't know how I feel about mixing and matching these but I just wanted to show you that you could do that validation there you can also come in here and do that same validation right like if uh title that is empty or is blank then go ahead and throw some illegal argument exception there as well so that's a little bit about validation in your API all right the last thing I want to show you in this module before we move on to talking to databases is we haven't really touched this application. properties yet we really haven't had a need to do so uh so here's where we can start to configure all of the things in our application we know if I I run the application I look at the council we know that uh Tomcat has started on port 8080 because this is the default but most everything can be configured so in the case of Tomcat maybe I already have something running on 880 and I want to run Tomcat on a different port you can come in here and change that so server. Port you see the default is 8080 but if I wanted to change this to 8885 I can do that and run this and I can see that now it's running on 8085 so I need to run all my requests through that Port this is simply to say that there are a bunch of properties that we can change about the way our application is working um you know spring is a convention over configuration framework meaning if if nothing's there it's going to configure something for you but if you want to go ahead and configure it and change something you by all means do so it'll back off and it'll say okay I've been told what to do here these are all the properties that are based on whatever type of application we're building so in the case of a web app we are configuring a server and all the things that go with that I would say look at the spring documentation to see what properties are available based on the type of application that you're building there are also ways to create your own properties I'm not sure if we're going to get to that today but if we can uh I'll sneak something in if not go ahead and check out my YouTube channel uh I know I have some videos over there on creating your own configuration properties so I just wanted to mention that because that's going to be important once we get into uh the database side of things and configuring database connection so I think with that we have uh I think you should go ahead and give yourself a big pad on the back you have created a crud rest API in Spring this is the boilerplate of building rest apis right we have this crud thing that allows us to list create read update delete for a specific uh type in this case a run so this is the foundation for building rest apis we've got that you've got everything you need to to start doing that now what we're going to do is we'll move on to the next module and we'll replace this kind of inmemory thing that we've done so we've done this where we have a collection of runs just in our system and we'll replace this with actually talking to a database all right module 4 talking to a database now if you've been around the world of Java for a while uh you know that it may not be the easiest thing to connect to a database there's a lot of things you have to keep in mind like when I open a connection I have to close it maybe I'm working with a connection pool I have to use some of the um apis that have been around in Java since 1.1 uh to access a database and some of them are clunky may not be the easiest things to use I'm happy to say that spring has many layers of abstraction for working with databases and it's really easy to get started in fact the first thing that we're going to do is talk to an inmemory database and it's super easy to get up and running we're going to do this in our app but I just want to show you here on the spring initializer if we go into add a dependency there is a dependency dependency for H2 database it says this provides a fast inmemory database that supports the jdbc API um and uh supports embedded in server mode so we're just going to use an embedded inmemory version of a database first again starting to like pick up the pace a little we're still kind of walking but walking fast we'll start to run in a little bit we'll change this out to like a postgress database we'll introduce Docker and do a whole bunch of fun things but for first we're going to use the H2 database now to talk to the H2 database I mentioned there are different levels of abstraction one of which is just the jdbc API that's what we're going to use there's also things like spring data we'll mention that in a little bit but this is a really good place to start it allows you to talk to the database connect to it talk to it using SQL if you're coming from another uh plat like language and framework uh it makes sense if you're coming from just Java talking to a database this is a nice level of abstraction on top of that so I'm going to choose that as well why I brought you back here is I wanted to show you another feature of the spring initializer if you go hit explore and actually we're in a project now let's choose Maven if you go ahead explore it'll actually list out those dependencies that we need so this one is a runtime dependency we're not actually going to use this in production we are going to also use the uh spring boot starter jdbc so this is that a jdbc API that allows us to connect and talk to a database so now I can come in and copy those dependencies go back to my uh project I'm going to open up the pom.xml again this is the maven Palm that declares our dependencies I'm going to come in here I'm going to paste those in I'm going to refresh my project and as long as nothing goes wrong we now can take advantage of those so what I'm going to do is I'm not going to do anything I'm going to rerun this application not do anything and I want to look in here and I see a couple of things that are going on first uh the 885s there let's get rid of that I like to run on 8080 that was just showing some configuration changes and now we're back to 8880 and we see a few things here it says the H2 council is available at2 Council again this is because of the spring boot Dev tools that we've included it sets some sensible defaults if you don't have Dev tools you could come in here and say Hey I want to go ahead and enable the H2 Council that's great because we want to disable that by default we don't want you uh somehow running in production with that and and making that available the H2 Cil for those of you who don't know is this nice uh UI that you can go ahead and visit in your browser and manage your database so once we create a table and it has some columns and it has some rows we can do all of that right in our browser and again this is just a good starting point right we see that it's available we also see that the hakari pool this is the database connection pool is configured for some URL so when we talk about databases in Java we have a jtbc connection using a jdbc URL starts with jtbc then the type in this case H2 memory and then some random uu ID uh identifying the database so we haven't done anything yet we just included some dependencies and I'm happy to tell you that you are already connected to a database now we we haven't done anything yet but that's how easy it is to connect to a database in spring now to get rid of this name I'm going to do a couple things here I'm going to say the H2 um let's say H2 oops sorry I don't know what I just did Dan so I'm going to say the data source generate unique name I'm goingon to say no let's not do that and I'm going to say the data source. name is going to be Runners right so let's go ahead and refresh the application here now when I look at this I see that I have a URL of jdbc each two mem Runners so if I wanted to I could uh I could go ahead and copy that um but I don't need to and what I want to do is go over to the browser and go ahead and look at localhost 8802 counil because that's the default you can see I have a jdbc URL so I would copy that out of there if I didn't know it the username is going to be saay the password is not there's going to be no password I can test that connection I can connect to it now and now I have this UI where I can play around with my embedded inmemory database now remember inmemory means every time we restart the application everything is going to change but now we have a database now there's no tables in here we'll change that in a second uh but there's no tables in here there's no data in here but we have something to get up and running with so now what we need to do is we need to be able to like create a schema and say hey this is what my runner's table is going to look like and then we need to create some code that will allow us to persist and read information from that database all right so the next thing we need to do is we need to be able to create a schema for that database now again it it restarts every time the application restarts so I want to have some way of automatically creating the schema and spring provides the mechanism for that what you can do is come under resources create a new file and we'll call this schema.sql this is a a specific name that we're looking for by convention we're looking for this file when it's an embedded database we're always going to run this for you so I'm going to paste in some schema here this is going to create a new table if it doesn't exist and this lines up with the run record that we created earlier it has ID title started on completed on and notice that the way that this um naming convention is so we use the camel case in the record um this is using snake case here I believe that's it I always get those confused um and that's how we're going to name the uh fields or the columns in our table so it started on complete on Miles location the primary key is the ID so with this in place I'm going to just restart the application again let's go back to our browser and take a look at this we'll have to log in again that's okay though once we log in now we see a run table now we can do stuff with a table we can put data in there we can read from it uh we can do this here in the UI but I want to do this programmatically in our application so how can we do that so first off let's go ahead and I think what we'll do is we'll go back to the Run repository now in the final code that you can get on GitHub there'll be two different versions of this the in memory one the jdbc one for Simplicity sake I'm just going to keep this run repository as it is I'm going to delete all of this right so let's just say all of that is gone um that's okay this is going to cause some issues in our run controller so I'm going to basically comment out everything for now but we still have a run repository so now what we want to do is we want to be able to talk to that database so how do we do that well we've already have a connection to the database we just need a way to programmatically access it um so there I mentioned there are different layers of abstraction in Spring if you see some older code online it's not that old I mean before 3.2 we still used the jdbc template but if you see some older code and you see something called the jdbc template this was really an abstraction on top of the jdbc API guys that made it easier to talk to a database in 3.2 we got something called the jdbc client this simplified that abstraction and really give us this nice fluent API for working with databases so what does that mean to us uh Actually I don't even need this for now um one thing I'm going to do is get a logger real quick so we talked about this earlier I just have a logger that I can use to log in my class here um I'm going to declare a a um jdbc client so jdbc client we'll get this through Constructor injection what this means is we saw this earlier right so this is dependency injection because we added that jdbc API dependency spring this is one of the powers of kind of spring boot looking at things that are on the class path and autoc configuring things so it knows hey we're we're going to be talking to a database I'm going to autoconfigure you a jdb DC client and now it's in the application context and if you ask for an instance of it here in the controller it will pass it to you you don't need to create one so we have an instance of a jdbc client what is a jdbc client let's take a look at it so I'm going to go and download sources um a fluent jdbc client with common jdbc query and update operations supporting all the jdbc style positional as well as spring style name parameters with a common unified unified facade for jdbc prepared statement execution so it gives some examples in here you can dig through here uh you can look at the structure of this and find out hey there's a a SQL a create create create um a very simple API from there we can do other things so let's use this to kind of replace the functionality that we had in our inmemory um repository so I want to be able to find all of the runs in the database so what we're going to do is say I want a list of runs and we'll call this find all and how are we going to get that we're going to use that jdbc client jdbc client Dot and now the first thing that we need to do is use some SQL so we're going to have some SQL and we're going to say select star from run right oops and once we do that I want to go ahead and map the results to something so run that query and map the results to a run and oh yeah go ahead and return a list of things back to me so I don't have an actual connection to the inmemory database here from my database tools so it's going to just give you an error here but that's okay we have a connection everything is going to be working so I have a way to find all this is good but I also don't have any runs in my database so how can I fix this so another thing you can do is you can come in here and say I want to go ahead and uh insert some data so you can use data. SQL now this is you're going to have to write SQL to insert data so I don't do this a lot but I'm going to do this just for this kind of demonstration later on we'll do this programmatically we can add some data through through through some code all right and I'm just going to p this in uh so we're inserting into run here are our columns here are our values let's go ahead and try and run our application and there we go now we have a single run in the system so with some data in the system and a schema in place now I should be able to come to my run controller uncomment that out we're using the same run repository we've just changed that code in the repository to actually pull from the database so now uh this is probably restarted by now we should be able to uh just go over to the browser and go to Local Host 88 so we can go to localhost 880 API runs and there's our single run in the system but now we're pulling from a database so this is exciting we've moved on from this inmemory representation to uh storing some things in the database now remember every time we change our code it's going to restart the application and uh the data is going to kind of reset itself but we're making some progress we're doing some some fun things here so now I want to go through and talk about uh some more methods that we can write in our repository so I'm going to go to our run repository and I'm just going to paste in some methods here because we can talk through them we don't need to watch me type all of them out but let's go ahead we have that find all what about an instance where we want to find a single run remember in our inmemory representation we returned an optional run we can do the same here we can say um okay here's the SQL I want you to find these columns from run where ID is equal to ID so we're using a named parameter here we can set that parameter by calling param the param name is ID here's what I want you to pass to it that is the ID that we got from the argument I want you to map this to a run so we have our run um and then I want you to return an optional so it's a good way to find by ID now you'll notice I'm naming these the same as I did in the inmemory representation so that these are in place our controller should just work exactly the same now again this is for demo purposes but I thought it was fun now to create update and delete uh we are using something called update in jdb update is basically hey I'm either inserting something I am updating something or I am deleting something and what happens from that is we here's the SQL that we're going to run here's the values I'm getting passed in I pass in a list of params I call update what is returned from update is how many rows were affected so in this case we actually want to make sure only one row was affected if it didn't here's the uh message that you could uh send back so again update we're just making sure one is updated delete we're just making sure one is deleted we're able to count we're able to um I would wrote like a save all method if we want to save a bunch of them and then just a custom query like hey find me all of the ones by the location so this is again if you've never done anything in in Spring and just worked with databases in Java this should look pleasantly familiar it's it's a little bit easier to read you get this nice fluent API and if you've not done a lot of work with Java in databases and you're coming from another language I think you should be able to get dropped into this and understand what's going on so what I want to do is go back to our run controller and uncomment all of these out great uh we'll restart our application and what I want to do now is take a look at our uh collection of things here and say um let's go ahead and run all of these I want to run all of these and make sure these are all working and of course they are still because again we've kind of named everything the same so I know that my API from my controller level is still working uh but now we're talking to a database so let's go back over to here and go to H2 counil and if we wanted to look at the database here we can click on run and run and we see our one run in the system so this is great we've gotten one run in there but I want to be able to get a little bit more data in there so one thing I'm going to do is actually just come in here and comment this out and now what I want to do is find a way to kind of batch load some data in Just For example purposes uh before we move on to having a little bit more fun with say like a a real database right all right so with this commented out uh we're no longer going to be inserting that one record so if we booted up our application there would be no records in our app so one thing I want to do is come back to this command line Runner this is very interesting right because the command line Runner is something and if we jump into it this is a functional interface uh that will be run after the application has started if you're a little bit new to Java a functional interface is an interface that has a single abstract method so in this case that method is run and because it's a functional interface it can be used as a Lambda expression a Lambda can Target this so you don't need to create a class that implements the command line Runner and then does overrides like the run method you can use a Lambda expression which we are doing here so I want to show you this example and then we'll move on to kind of doing some batch loading so I have this run here but I want to save this to the database this Bean annotation again is another way of creating a bean in the application context we looked at things like at component rest control at repository at service these are ways of telling spring hey this is a class that I manage go ahead and manage this in uh go ahead and manage this for me Bean is another way to create beans and put them into the application context we're not going to go too far into that in this course um but this is one example of cre creating a bean so what we're doing is we're creating a command line Runner and it will get run after the application starts but because this is a bean we can say hey part of this is in um I need a run repository go ahead and and pass that instance into this Bean for me so now I can say run repository Dot and there is a create method to pass in a run and create a run from that so let's say create uh whoops and then now we should be able to go ahead and run this and we have an issue here which is uh run controller so let's look at our run repository create so insert into failed to execute script uh this looks like it's complaining about this that's okay let's go ahead and delete that and let's run this again and there we go the application started up and if we remember let's take a look here we have this thing called first run so we should be able to go back to the database here and connect to this and if we go to run we have our first run so good so we know now that this is a programmatic way that we kind of bootstrap some data so we're going to use this as a way to insert some data that we can use in our application but I'm actually going to get rid of this because I'm going to go ahead and do it a different way so the first thing that I'm going to do is I'm going to create some a new folder here call this data and inside of here I'm going to say that this is a runs. Json and we have some Json data that we can paste in here you can grab this from the repository and we could say there we go so now we have 10 runs and the reason I did this is so we can basically bootstrap some data we have some data that we can work with right so now I want to talk about maybe how can we read this Json data and insert it into the database now we already have the mechanism for reading and persisting data right we have this create method we have a delete method I also have a save all method that can take a list of runs and insert that so what I'm going to do is create a new file here and I'm going to call this my run J whoops run Json data loader and in my run Json loader I'm going to implement that command liner because in this case I do want a separate class uh to do this in because I'm going to do a bunch of things all right first off I'm going to get a logger I have a logger to to log some information with I want to get that um log that run repository so I'm going to say run repository run repository and we'll get that through Constructor injection again this is dependency injection when it creates an instance of this class it will see that it's dependent on the Run repository spring knows about that class it'll inject that into this Constructor for us and now we have a run repository that we can use right so in this method now I can say hey um run repository. count so we know this is going to be zero all the time because we are basically resetting the database when we start and starting from zero so we know it's going to be zero but when we move on to a real database that's not the case right we don't reset a real database all the time but in this case it will be zero but that's okay we're saying if the count is zero I want to do some things I want to go ahead and try and load some data and wow uh copilot on its game today let's see if this works um so we need one more thing here which is an object map so we need um that that will get passed in for us this doob mapper is equal to object mapper right so um the reason we need that is we are basically reading in some Json and trying to map that Json deserialize that into objects and what are we trying to deserialize that into we're trying to deserialize that into a list of runs so just like I have run I'm going to create a quick record so I'm going to call this my runs and this will be a record which just basically just a list of run runs right so now I am I am deserializing that into a list of runs um run repository all runs oh do we call that something different all right so now again you don't really need to know this type of code I just thought I'd be nice to show an example of reading some data from a Json file and inserting it into a database you could certainly in the commandline runner that was in application. jaava insert 10 records on your own and and you'd be off and right I thought this would be a good example so basically we're going to read from that file which is runs. gson if we can we're going to try and map those to the runs record uh we do a little bit of logging here to say how many runs we are loading and then we save them all using that run repository we're going to Pur these off to the database so let's go ahead and one more thing this class will never run because we haven't told spring about it yet so we just need to mark it with at component to say hey this is something I want you to be aware of so let's go ahead and run this application uh we see reading 10 runs from Json data and saving it to an inmemory collection that is probably from some older code but just say saving it to a database right so um this will probably already restarted but let's do that and then we can go to um the browser we can reload our database here and we can say connect and now we can click run and now we have 10 runs in the database and we've loaded those through that Json file so cool we're doing some fun things here we've connected to a database that was pretty easy we're using an inmemory H2 database uh We've made some progress replacing our inmemory run repository with a repository that is actually talking to the database and then we just did some kind of batch operation where we can read from a file and insert into a database so this has been fun we're not done yet next what I want to do is kind of replace place this in memory database this was fun for getting up and running but let's talk a little bit more about how we can take this one step further all right so we've already looked at using an embedded H2 inmemory database now I want to talk about using something a little bit more production like and that is a postgress SQL database so from a coding perspective there's not much change now we we saw with H2 database we could simply fire up the application and we had an inmemory database up and running with H with something like postgress or MySQL there's a little bit more but not much so I'm going to go ahead and comment out this and all we would have to do is go ahead and set up a URL a username and a password now the URL looks something like jdbc colon um let's see colon postgress SQL something like that local 5432 Runners and then you have a username and a password if you have a postgress database up and running on your local machine right now you could do that set up a runner's database um and then now let's talk about a couple things now first off you need a postgress database up and running so how can we do that you can download you can install it or you can go the route which I'm going to go which is like the docker route second off in um this schema file this schema file only gets picked up by embedded databases by default we are not going to run this automatically when you're using something like postgress or MySQL so you have to tell us that hey I do want you to go ahead and run that and the way that you do that is by using the um spring. SQL doent mode and setting that to always so that would be good if we have a database up and running on our local machine which I do not so you could um go ahead and install Docker so Docker is a way to run a container um a container can be anything from like a database to another application to whatever whatever application we can containerize right in this case it's going to be a postgress SQL database this means that I can just run a Docker command and spin up a postgress database without having to like download and configure all you do all the things that we used to do so you could you have a couple options here you can come in here and there's a if you go to Docker Hub and look for a particular container in this case postgress you can go down how do you start a postris instance it has the actual Docker run command you could run this but then you need to like configure your properties and you need to do this every time you start your application up there's also something called Docker compose which is a file uh in this case docker-compose.yml that could sit in the root of your project and you can run Docker compose up it'll look at this find all the services that it needs to start up and start them up and and this is really handy because imagine a scenario where we had you know Docker or um postgress running Kafka rabbit mq um some other thing you know some other microservice so this is really nice to be able to like start up services and in Spring loot 3.1 we introduced the docker compos module which simplifies a lot of things and we'll we'll talk about those so when you're over at start. spring.io and you pick a dependency let's talk like postgress SQL right when you pick the docker compose module so we go in here Docker compose support it's now going to look at all the other services or dependencies that you've selected so you've selected postgress maybe you've selected Kafka and what it's going to do it's going to create a Docker compose file with those Services listed so one way we can look at this is by checking the explore and again I'm going to choose Maven I'm going to check the explore and there is a comp hose. yo file now so now this is listing the services based on the dependencies that we've had um so this is really good so that's the approach that we're going to take today so I'm going to show you this um from the pom.xml I'm going to copy this uh post SQL driver and the docker compos support so with that we can head back over to our IDE here and I'm going to go into my pom.xml I am going to just uh Delete the H2 database and now bring in the docker compos support with the postgress SQL driver I'm going to go back here and copy the composed. yo file so I just copy that and I'm going to create a new file in the root called composed. yo now if you have other conventions maybe you put this in a Docker folder and call it Docker compose or whatever you want to call it you can go ahead and uh set this up in your properties file you can change where we're looking for that by default we're looking for compose or I believe Docker Das compose in the root of the the application so I'm going to post that uh uh go ahead and set that in there now we I want to make a couple changes this because um the first thing is the image I'm going to leave this how it is but you may want to change it so the image is saying hey grab whatever the latest postgress image is great for whatever we're doing right here today but if you're on a team and other people are pulling this down we want to make sure everybody's on the same version so you may want to specify a version here in this case I'm going to set a um database of Runners we'll call this uh my username uh let's call this password for very secure password and then we'll go ahead and set this to um Dan so um that's the username password and the database name now the port uh interesting enough when you use a Docker compost file and you just specify one port what that's saying is on my local machine just use a dynamic Port I don't care which Port you're using but on the container side I want you to map it to 5432 because that's the port that postgress is running on in the container now this is fine but in the instance that I want to actually connect to the database I need to know the port number now you could do jump through some hoops and run some commands and find out at runtime what port this is using but I want to be very specific here so I'm going to say hey this is 5432 is going to map to 5432 on my local machine now when we use our database tools we can connect to the database using that Port so uh with all of this in place I think what I want to do is just restart the application see if we have any errors oh and we do because Docker desktop is not running so let's make sure Docker desktop is running on our local machine to make this work again if you don't have Docker desktop no big deal you can go ahead and set up an actual postgress database and uh connect to that that's fine U but now you can see it says using Docker composed file it sees some services and um it goes it went it went ahead and fired those up so um that's up and running now we have a database connection to a postgress SQL database and we've actually read uh 10 r from Json data and saved it to a database so let's test test that out before we had the H2 counil now how can we go ahead and look at our database if you're not using intellig ultimate don't worry there are plenty of free great tools out there to connect to a database and manage them uh on Mac on Windows Linux Etc so go ahead and find something like that if you're in intell Ultimate you can just click this database icon you can go here and say I want to add a new database and I'm going to say this is postgress and this is on Local Host again 5432 that's the important part the username was Dan the password was password the database was Runners right and that looks good so now that's the jdbc URL the connection string that we need to connect to the database let's see if this works uh we'll go ahead and say okay come in here we see that there is a table there is a run table and we see that we have our 10 runs in there so this is really great to see so we have our connection to our database now I want you to notice something here because we've declared some properties in here but I don't have any of those properties set up here in my application. properties that is because we don't want you to have to duplicate these properties right we have a database we have a username we have a password we have a port we don't need to duplicate these across both files what happens is uh spring uses something called The Connection details interface behind the scenes and there are some implementations of this one of which is being able to create a jdbc connection and it will read this at runtime and fill in those properties and put them into a property Source at runtime for you so it knows how to construct a jdbc URL it knows how to get the username and password Etc so that's really nice that we don't have to uh kind of duplicate those properties so that is Docker compose let's talk about one more kind of abstraction at the database level okay we're back over here at spring.io if we go to projects and you go down to Spring data this is a really cool project made up of and has many many modules underneath of it you see here it says spring data's mission is to provide a familiar and consistent spring-based programming model for data access while still retaining the special traits of the underlying data store so we know that different data stores different databases have special traits we kind of uh keep those uh underneath the hood and we're allowed to use some of those special things that different data stores can do you'll see that there are some features here so powerful repository and custom object mapping extractions uh this really allows us to Define an interface in Spring data and have it get turn into an implementation at runtime what this means for you is that you don't have to write all of these crud methods out we saw the jdbc client I really like the gdbc client it's nice it's fluent it's easy to read but I still got to write all that code to get just some simple crud things going on right maybe I want to MVP maybe I want to kick something up real fast I don't want to have to do that for every resource in my application so spring data allows us to kind of bypass some of that and do it for us then when you have special needs like hey I got to find all the runs by location then you can write these Dynamic query derivations from the repository's method name so you can just write return to me a list of runs and we're going to call this method find by run find by location and pass a location in right so this is really cool spring data has a lot of really powerful Concepts now two of the most popular spring data uh projects out there are spring data jpa which is an implementation of the jpa specification the Java persistence abstraction um and this underneath the Hood by default uses hibernate so you might have heard of an OM or hibernate before that's what spring spring data jpa is doing spring data jdbc uh actually simplifies a bunch of things by kind of getting rid of some of the things that hibernate does and really just allows you to like model your uh domain objects and use kind of straight SQL that we're used to writing and it still gives you the power of like repositories uh Dynamic query derivation and so on so we're not going to spend a lot of time on this today this is this we could really create a whole course on Spring data and some of the other implementations in fact you could create a whole course on just like spring data jdbc right so what I'm doing here today is I'm just showing you this as an option so that once you get past like the jdbc client and some of the basic stuffs you know that this is available to you and you'll probably come across code out there that's written using spring data and so I just want you to be aware of it as you're uh getting into it so from from start. spring.io you would pick something like spring data jdbc uh you would pick uh your database in this case postgress we would pick the docker compos support so if I go look at explore again I'll come back back and choose Maven if I look at explore here the starter for this is spring um boot starter data jdbc so I'm going to go ahead and copy that I'm going to head back to the IDE we're going to go over to our pom.xml and I am going to just put this right here and we're going to reload Maven and I'm going to actually stop this for now and so now we're going to talk about like what does this do for us so let's go ahead and look at run and look at our run repository so right now this run repository has like all this code in here that we wrote using the jdbc client so I'm going to actually rename this so let's say rename room jdb J DBC client sorry my my shift key has been sticking on me lately I got to fix that so J BC client run repository that's going to break some other things but that's okay we'll fix that now so what I'm going to do is create a new one we're going to call this run oops run repository but this is going to be an interface not a class an interface how is this going to work all right so let's go ahead we can extend some of the repositories that spring data gives us it gives it's a credit repository uh for J there's a jpa repository there's also a list cred repository now the arguments that it's taking here is the type and then the ID of that type so we're creating a repository around the Run type so we have a run already if we had like a user if we had um uh equipment right like we could create repositories around all these different types so the ID type of a run is the integer right so now that we have that uh that's one piece of the puzzle the other piece is we have to come into run and we have to mark the integer we have to say hey this particular thing uh is the ID of our uh type so we're saying this is the ID I'm going to do one more thing and this is kind of specific to Spring data jdbc and that is there is an at version column and we'll call this uh integer version and this is just a way to track whether this is a new type a new row or an existing row to to keep it simple right so with that I need to make one more change and that is to the schema and I gotta go ahead and say that I need a version and this is an INT uh it can be null so that's okay uh yeah so that looks good so now with all of those in place I haven't done anything let's look at this list credit repository ru real quick so first off there's a save all method that will return a list of of types right there's a find all which will return a list of those and then there's a find all by ID we can also see there's a crud repository so we can save save all find by ID exists find all find all count delete delete delete delete delete right so all of these methods are available to us out of the box based on that type and we don't have to write any of that code which is really nice so what this tells me now is if I look at my run controller I'm pulling in that uh okay so this refactored it let's go back to the Run repository and see if that breaks anything so yes so this needs to be a run repository um so that looks good so now our create method we may need to call Save instead of create um um this is save and this actually doesn't take in the right um and then the delete doesn't delete so now the the delete method doesn't take an ID it actually takes the run to delete so all I'm going to do is use the Run repositories do find by ID um and then pass the ID in there and mostly it uh we could do there's another one uh we could do this a little bit safer but this is okay for now so now my controller is basically um lined up with the new run repository that is using spring data again we haven't written any logic here let's go ahead and see if we can restart our application so again looking at that composed. yo file all right now something interesting happened here says not loading runs from Json data because the collection contains data already remember we had in our Json loader we had this hey if the run repository. count now the run repository. count method is using the new repository that uses spring data there's a count method in there so it'll count how many rows there is is there zero rows if there's zero rows go ahead and read from the Json and sa those um if not hey we've already got rows in there because remember now we're using postest this is not resetting every single time that we restart the application so if we were to go into our database again look at our table we'd still see our 10 runs right so uh that's interesting the other part is yeah if we go to the terminal and let's just clear this and HTTP IE so uh 8080 slash API runs uh oh we don't we got a little air [Music] um prepared statement has a bad squl grammar that's okay we like erors um let me look over here this is a little bit hard to read so let's find out what's going on [Music] here um okay so bad SQL grammar select run 9 title title miles version version with r cause column run. version does not exist okay so um what happened is probably this schema didn't get Rewritten that second time when we added version so let's just go ahead and come to this database and I'm going to drop this table right so now if we restart the application it should see that that table doesn't exist and go ahead and add it and now it added those 10 there so now let's go ahead and refresh this and make make sure that it has the version which is null okay right so now that looks like it's working let's go ahead and check our terminal again and go to 8080 there we go now we have our 10 runs in the system so cool uh I want to show you one more thing with spring data again I I just love geeking out over this stuff so one of the things that we've done is add all this like custom or uh crud functionality but what if we wanted to add some custom functionality what if we wanted to say hey give me a list of runs and I want you to find all by location and then um pass in the location that you want to find all by actually this is not find all by and then as you can see we also get intellisense this is based on the type that we're working with so you could find all by uh completed on complete it on after and you could start to chain these together you could say find me all by location and by miles greater than so I want to find all my outdoor runs greater than five miles you can do that you can start to chain all these together now I will say once you get into like if you start chaining three or four or five or six different things there's probably some better ways that we can do it but um that's okay so I'm going to say find all by location and I'm going to pass in these string location and then I could just go into my um controller and create a a custom method for this so I could say yeah that looks good get mapping and I can say list of run find by location path variable string location return find uh all by location that looks pretty good let's see if we can restart our application and do that so now what I would do is go to this slash location slash outdoor right and now it finds all the outdoor runs so is there no indoor runs let's see oh there's a few oh yeah okay so okay I was looking at something different I thought it was the 10 showing me the 10 of them but yeah so that was a quick way to write a custom query uh you can also come in here and add the at query annotation so if you wanted to write your own query here uh you could do that as well so there a whole bunch of ways that you can add functionality on top of this repository that gave you all this crud functionality out of the box so I think that's where we're going to wrap up our database section uh I hope you learned a lot in this section we started off by like kind of replacing our inmemory collection with an H2 embedded database uh we talked about you know connect ction strings and all those things we talked about how to use the jtbc client to get data in and out of uh our H2 database and then we moved on and we we replaced our it22 database with a postgress SQL database using Docker using a Docker compos support in Spring boot 3.1 and we finished it up by taking a look at Spring data so I hope you learned a lot in this section I had a lot of fun but with that it's time to move on to the next module in this module I want take a look at rest clients now we built out our rest API and we've talked to a database to get some data but what you'll find is often in organizations in applications they're not just Standalone applications huge monolithic applications sometimes we're dealing with microservices where this particular application is dealing with one thing and maybe to get data about say a user it has to reach out to another service in the organiz ganization the question is how do you talk to that other service one such way is by using a rest client so here we're in the spring documentation you can see the spring framework provides the following choices for making calls to rest end points now I'll give you just a really quick history lesson so you understand why there's uh some options here so when uh spring MVC first came about the rest template was born and the rest template was a way to make a client call to another service the rest template over time had um issues come up and hey I I need to be able to do this in this sort of way so over time that API grew uh into the API that it is today so there are a lot of overloaded methods in the rest template well when spring web flux came along which is the reactive stack for building web applications or web apis they decided to take a look at the client and kind of start from the ground up and so they built the web client so the web client is used strictly in the um uh the reactive world but you could use it in Spring and VC apps before because it had a blocking call so you could say hey do this but but this is going to be a blocking call so the web client was really great folks really loved it because it had this nice fluent API it was easy to understand there wasn't all these overloaded methods and so we found that a lot of developers were bringing in the web client into their spring MVC apps so from that uh the rest client was born and the rest client is a blocking synchronous client with this nice fluent API really easy to use and so that's what we're going to do today we're going to take a look at the rest client and then we're also going to take a look at HTTP interfaces this is a really nice feature that allows you to talk to another service by just defining an interface and not having to write the low-level uh implementation to talk to another service we saw an example of this in the last module right with spring data I need some CR crud functionality but I don't want to write all of it just to find an interface and let spring turn it into an implementation at runtime HTTP interfaces is analogous to that so let's have some fun here um now we don't need to do anything as far as adding more dependencies because with the spring web dependency that we chose at the beginning of this course that will bring in the rest client and so we have everything we need so now all we need is another service to talk to so I fumbled around with this and and thought about some different scenarios that we can go through we could have created another uh application to do something maybe to like bring in like a list of locations or something but I thought I'd just go off the a little bit off the path of the runner's application and just use kind of a public API that way you don't need another service this is a public API that anybody can talk to and you don't need to authenticate against it or anything so this service is called Json placeholder service and again you can go out and test this on your own uh you can see you can go try it hey I want to talk to uh to-dos I want to get a specific to-do you can get it and it will give you back a to-do now there are a bunch of different resources here so I've done stuff with all these different endpoints before but the one we're going to work with today is users so we're going to set up we already set up a user package earlier in the user package this is where we're going to Define all the code we need to talk to this service and bring us a list of users if you want to keep it in the realm of this runnner application let's just pretend that we have a bunch of users that need to log in and maybe we get those users from another service and this is that service so here is what a specific Runner looks like a single Runner looks like I'm going to copy this because what we want to do on the spring side is Model A type after this we're going to create a record based on a user and it's going to have a couple things right it's going to have some Fields but it also has other types like an address an address has a Geo we also have a company so we need to model this out on the spring side so that when we call this service we can say hey what I expect back is a user and all these fields will kind of line up so I'm going to copy that I'm going to go back to intellig in uh user package I'm going to create a new new Java class we're going to call this user and this is going to be a record and then let's just put this on different lines and now co-pilot again is on its game because I've done this one before so it's remembering this so let's just go ahead and paste I'm also going to paste this up here just so we can kind of see oh let's put that in a comment Dan and let's put that there so now we have ID name username email address is its own type which is going to contain Geo uh string phone website and then company so now what we need to do is create an address so let's create an address record so I'm going to go ahead and do that and let's put this on separate lines and it's going to figure that out as well so let's I don't know why I keep hitting the wrong button today uh create record Geo and then what is Gio going to have it is going to have a lat and a long all right I think there's one more we need to create um which is going to be the company and so let's create a company record and this has a few uh Fields name catchphrase and Bs and there we go so now we have something in our system that we can model after a user so when we call out to that system that public API we get say hey give me back a list of users or give me single user right so I'm going to create a new Java class here we're going to call this the user uh rest client we're going to call this the user rest client and this is going to be a class and we need to mark this with something so I'm going to mark this with act component uh just because if we want to go ahead and use this later we want to tell spring hey manage this class Force put an instance of this into the application context so what we need is a rest client so I'm going to say private final rest client and we'll call this rest client all right so we've declared this rest client but how can we get an instance of it let's take a look at rest client and we notice right away that it's an interface so we're not going to be creating a new instance of the rest client but if we drill down into this there are some static Factory methods which we can use so we can create a new rest client we can also create a new rest client with a base URL uh we can also create one from a rest template so if you have a rest template instance you can create a new rest client from that and then there these uh there are these Builder methods and Builder is actually an interface in here as well if if we look at Builder there is a default res client Builder that implements that res client. Builder and this is something that will get created by Spring boot so we'll have an instance of this default R client Builder if we just ask for an instance of the rest client. builder in here you'll see that it declares uh a bunch of things uh these private static final Boolean for like the JD key client The Jetty client the http compon component's client we'll talk more about that uh in a second so if you want you can dig into that and see what the default rest client Builder is this means that we can come down here and we can create a new Constructor so we can say public user rest client and we can get an instance of that Builder so we can say rest client. Builder and it will basically pass in that uh default rest client Builder so now we have a builder uh co-pilot yes thank you so we're using the Builder to set the base URL so the base URL is the Json placeholder service so if we go back to the browser you'll see this is going to be the base URL this slash users will be the the URI for all the users and then if you wanted to get like a specific user you could say slash users1 all right so now that we have uh kind of our rest client ready to go we can start to write some methods to interact with this service so I want a uh an instance where I can get a list of users so I want all the users uh I might call this find all and I'm going to return whatever the rest client Dot and now this is for me one of the big advantages of the rest client over something like the rest template that had all these overloaded methods when I hit rest client dot I'm given some options here it's not a whole lot of overloaded methods these are the request methods I know that hey I want to perform a git a put a delete a post Etc so I know I'm going to perform a g here the URI off the base URL is going to be that slash users that we saw before next I need I basically have two options here I can use retrieve or exchange now retrieve is kind of the simplified version of this where exchange allows you to get a little bit more control over the request and the response so I'm going to say retrieve and then finally hey what do you want us to do with the response in this case um the response body in this case he I want to just turn it into a parameterized typed reference and this is a way that we can get a list of things so that will give us a list of users how can we ask for a single user so I may just want to get a user I I may call this fine by ID uh I'll get an integer ID then I'm going to use the rest client doget um I'm going to use a URI of Slash users SL Dynamic ID and we're going to replace that with whatever uh we get as an argument to this method so now we have a URI there next we're going to retrieve and finally we're going to turn this into a body of what type we're going to model it after that user record that we created so great we have two methods here that allow us to basically find all the users and find a specific user when we're talking to that other service so uh normally I would write a test against this we're not going to get into tests until the next module so right now just find a quick way to test this out using the command line Runner so what I want to do is get an instance of that client uh let's just go double check that we marked it with that component and we did so now we know that we can get an instance of this here because it's in the application context and uh let's just make this simple let's call this client and in here I can say client. findall that is going to return a list of users we'll call that users and I'll just assis out users and we should be able to run this now and let's see and there are all the users that we pulled down from that Json placeholder service if we wanted to get a specific user we could say client. find by ID we know there's one in there with one so I could sayar uh we'll call this user and then I can just sis out a user and uh we can go ahead and run that and again because that's a record we get that two string component in there so we have that single user we're splitting out uh based on that two string we're able to uh view a representation of that user so good um that was uh pretty easy right I like the rest client I like this simple um fluent API that isn't complicated again I just I can read this I can look at this and like know what's going on um I want to look at a couple other options that you can talk about when you're using the rest client and then we'll move on to http interfaces so what is happening underneath the hood this is actually the API this isn't the low-level mechanism that is actually making that API call across HTTP right for that there are a bunch of different uh options that you have there is a default HTTP client underneath the hood but you can always swap that out for something else and you can do that using the request Factory so we'll look at the request Factory it takes in a client HTTP request Factory we'll see this is an interface if we look at the implementations of this there are a bunch of them so if we wanted to use something like the jdk client HTTP uh we could use that from jdk11 if we wanted to use something like Jetty or something from the Apache Commons we can swap these out so all we have to do is say new jdk HTTP request Factory and now I'm using a different HTTP client Library underneath the hood I could also uh extract this out to a variable so if I wanted to I can say new uh jdk uh HTTP request Factory let's set a VAR there and now what I could do is uh I can customize the underlying HTTP client so if I wanted to do something like set the the connection timeout uh I don't think that's actual call I think it's Set uh set read so we have set read timeout uh set read timeout with a duration so we can kind of change this if we wanted to we could say I want the timeout to be this instead so this is a way to get at the uh underlying HTTP request Factory and go ahead and customize it and then I would just pass in this uh variable here so that's one thing we can kind of customize uh another thing we can customize is if we go in here and say dot we see that we can do something like a default header maybe we wanted to pass a user agent and say what the value is we can set a default header here so any call that goes out to the Json placeholder service we'll go ahead and pass this uh header along with it some other things we can do is by setting a request Interceptor so Interceptor will allow you to intercept that request you can do it in line so we could see if we look at this this is uh based on the interface client HTTP request Interceptor this is a functional interface so you can pass a Lambda there if you just have something simple to do if not you can implement this uh uh Interceptor and it allows you to get access to the request and you can kind of handle do do some more things with that if you want a couple of examples of this and I've done some of these I think on the YouTube channel is uh what if you had to do like an ath two handshake and you wanted to go out and get a Json web to JWT and pass that in every request uh you can do that there maybe you wanted there's a really great project by a co-worker of mine uh for retries so if you wanted to uh call this service but whatever reason it failed once failed twice I want to retry this service three times these are all like custom things that you might want to do but you can do them in an Interceptor so that is uh some other things that you can do so we've looked at the user rest client uh this is really great but again I'm writing some code here uh what if I don't want to write code and we saw this already in the spring data example where we can declare an interface have spring turn this into uh an implementation at runtime and handle some of this for us so that's what we're going to take a look at now and we're going to do that by creating a new Java class and we'll call this the user HT GTP client and this is actually going to be an interface so let's say interface and then all we're going to do in here is write out the contracts for the methods that we want this is going to look pretty similar to this we want a list of users um find all we want a user find by ID so let's go ahead and put those in here so I'll say list of user and this is called find all and again all we're doing is creating the contract and in this case user find by ID and we'll actually get this through a path variable now we need to kind of hook these up and say these are going to be we have to give them an annotation to say hey like this is something I want you to uh make an exchange with another service for and the way that we do that is there's the HTTP exchange annotation but there are also specialized versions of this so this is an a git exchange so I'm going to use the git exchange annotation and then you're going to use the URI so remember with the rest client we'll set a base URL and this is the URI so for this one we'll say get exchange uh that almost looks good let's say users slid and now this is all we have to write in this class we don't have to write out all of this boilerplate now there is one boilerplate thing we'll have to do and this is basically um setting up that rest client and telling spring hey this is this is a um this is a user HTTP client and I need you to go ahead and create this for me so the way that we do this is user uh actually user HTTP client user HTTP client we're going to use that rest client to oh yes um Co pilots on its game so really what we're doing here is we're creating a rest client using one of those static Factory methods we're setting the base URL we're creating an HTTP service proxy Factory with that R client and then we're just creating a client and we're returning this user HTTP client now again this is a little bit of boiler plate I usually have like a um a live template here in intellig that creates these for me or co-pilot if you've done it enough it will go ahead and write it for you once this is in place this creates a bean this is now a bean in the application context so I now have access to that so really all I got to do here is switch this out for the user HTTP client because I've named those the same this should just work but again we haven't uh actually written any code to talk to that service uh this is being done for us by Spring at runtime so pretty cool stuff with HTTP interfaces now again this in spring boo in the latest version of spring boo 3.2 this is using the rest client underneath the hood we can see that here we're using rest client in previous versions if you're on something like 3.0 you would have to bring in the web client to make this work uh but now this just kind of all works seamlessly uh in the MVC stack so pretty cool stuff uh I hope you got something out of this we talked about a little bit of the origins of rest clients in in the spring world how we've gotten to the rest client in 3.2 HTTP interfaces uh to kind of simplify and and take away some of that mundane boilerplate code that we we have to write uh so with that I think we'll end this section and we'll get ready to start writing some tests uh we'll write some tests against this and and a whole bunch of other code that we've written here in this course uh so with that let's move on to the next module and talk about testing in this module I want to cover testing now I talked about this early on in this course this probably isn't the route that I would go as if I was building an application today I would write a class and I would write a test for it but I didn't want to B you down with the mechanics of writing a test so I went through and we built out an application we built the rest API we talked about talking to a database we talked about being able to communicate with other services via the rest client so now I want to kind of step back and talk about testing and specifically testing in Spring boot one of the things I love about testing in Spring is that there is no need for you to opt into testing we've already done it for you so we are giving you all the tools you need to write your test and there are a whole bunch of tools available to you write out of the box and I want to start there so if we're on the spring initializer and we don't pick any dependencies if we go ahead and uh check Maven and click this explore button you see down here we have this dependency for spring boot starter test now spring boot starter test is made up of a bunch of dependencies it gives you a bunch of tools out of the box the nice thing is this scope is in the test scope this means that these dependencies are loaded when we're using tests but when we build our artifact for production then all of this kind of gets stripped out so we're not asking you to bundle a whole bunch of libraries in there when you're not going to use it for production uh this is strictly for testing and there is a bunch of stuff that comes with it and we'll go through some of that so the first thing I want to look at is in your test package under Java there is a single test uh in this case it's called Runners applications test uh we could even rename this CU I renamed the application so I can rename this to application tests and refactor that and there's a single test in here called context loads there's no code in there just the context loads now we can run our uh tests via the IDE there's also um a maven plugin to do that uh so I'm going to do this right from the IDE you can say run application and this will run the application tests and if we look in here we see fail to load something has happened um and I think and this is because of some of the things that we're doing with the database connection I haven't refactored this to make this work yet but what this will do is will throw it will basically fail if some exception is thrown and something's happening now uh with that basically the database and the test environment isn't configure but if you download a project from start. spring.io you create this new project and you have this single test in there this will work right away and so this is a test that I would often keep in here I get a lot of questions like should I delete this no keep this test this is a good sanity check the context loads means does can I just get an application up and running and from this standpoint I can't because I have some things going on with the database connection but um most of the time this will just kind of give you a sanity check so this is a good place to start this is my um my main test and this is going to kind of stay there and give me that that sanity check now there's another annotation in here at Spring boot test I'm going to download the docs for that and this is one you're going to come across often this annotation that can be specified on a test class that runs spring boot based tests provides the following features over and above the regular spring test context framework so it does a whole bunch of other things it allows you to um set a context loader it allows for custom environment properties so you could pass in properties to like over something in this case like the data source right we could maybe switch back to an H2 for a test I wouldn't do that but just an example of something we could do there um Provide support for different web environment modes so you can basically uh start a fully running web server or or start some kind of Mack web server uh that could be on a defined port or a random Port doesn't matter so this is nice the spring boot test it's kind of like the kitchen sink for being able to test uh different things in Spring also does things like register a rest template a test rest template or a web test client Bean for web tests that are useful using a fully running web server so I need to talk to like some other service right so this is the um spring boot test annotation you'll come across this often next I want to go ahead and look at some documentation so I'm going to go over to spring.io we're going to go under project we're going to go to Spring Boot and under the learn section we'll go to the reference docs and in here this is kind of broken up into different sections if you look under core features we see profiles logging testing and more so this is where I want to be so I can go into core features and go down to testing and this is where I kind of want to start so spring boo provides a number of utilities and annotations to help when writing or testing your applications test support is provided by two modules the spring boot test contains core items the spring boot test autoconfigure supports autoconfiguration test um most developers just use that spring boot starter test that starter that we saw that got included which Imports both spring boot test modules as well as junit uh junit juper to be specific that's junit 5 assert J ham Crest and a number of of useful libraries um by default we're using junit 5 now not junit 4 um so if you need to use junit 4 there's a way but uh we're using J Note 5 so here's what I wanted to talk about these are the number of dependencies the tools that you have at your disposal so I think part of the key is you know we've talked about it Spring's been around 20 years spring boot's been around 10 years if you go search for something and you say how to write a controller test like you may get all these different examples and you're like what are all these things in this test I don't understand what these things are and part of that is understanding what things are available to you out of the box what libraries right so junit the deao standard for unit testing Java applications this is how we write our test how we there's a test Runner how we can run our tests um the at test annotation comes from junit junit also comes with some assertions so I want to do this thing and then assert that uh this particular thing equals some value that we expected to right so that's junit uh spring test is kind of the core testing utilities the integration test support for spring boot applications a search J is another way to uh use assertions it's just a different way of using them it has this nice fluent Library so you can use the ones that are in junit you can you switch over to assert J which I know is very popular I wouldn't recommend mixing and matching both because you kind of want to just stick with one style right ham Crest is another way to uh go ahead and match on things things um also known as constraints or predicates so those are the kind of core things then we get into makito so makito is hey we want to mock something out so in the example of our controller that uses that repository that talks to a database when I want to test the controller all I care about is the controller I don't really care about other dependencies I don't care about talking to a database talking to another service fetching data from some event driven architecture right like I don't care about those things I want to mock those out so that I'm only focused in on the controller and Mido is again the de facto standard when it comes to mocking in the Java Universe then we have a couple others uh for dealing with Json so we have Json assert and Json path whenever you're like trying to test um assert against like particular sets of Json data these two um libraries are very helpful and then we have a weight ability a library for testing asynchronous systems so it's good just to know what's in there these links in here are all links to the documentation on the various libraries you don't need to like study them and become experts on them but I would dig through there and just like get a really good like overview of what they are and what some of the code looks like that way again when you see a code example online or somebody shows you some test you can quickly scan it and understand what library Aries are being used to kind of build out those tests okay so that's enough of an overview let's go through and uh start writing some tests for some of the code that we've written so far all right so the first thing I want to look at is getting this context loads test to work again if you just download a project this is going to run right away but we're running into an issue here and I want to talk about that issue so we are using a database that database is because we are using this composed. emo right when a spring boot application starts it will see that file it will run Docker compose up and that is and that connection gets created and put into the environment at run time we're not running an application we're running a test so it's a little bit different of a workflow so we don't have a database up and running so in the test scenario I would have to come in here and actually run Docker compose up so that that database starts see it start in a second and that is up and running and now that that's up and running I have to come in here and actually set a data source because again it's not getting injected from the docker compos file because that's not getting run in a test scenario so now that I have this up and running I should be able to run my application tests and that should work now in a real world I would not do this this is not my workflow in the real world I would use something called test containers if you haven't heard about test containers yet uh it's a really great project go ahead and check out test containers. org uh you can go ahead and check out the docs to learn more there's different languages support um but the Java support is really great uh has a bunch of really great features and really it just allows you to say hey I want to the same way that we used a container for development we could use a container for testing and I like this approach much better we used to maybe use something like an inmemory database like an H2 database for testing but then we have an H2 database in testing a postgress database in production and we're really not aligned right like we want to be as close to production as we as we can get on our local development machines so um in that sense I like using test containers for tests um but to keep this short I think we'll just leave that at that for now I have some more um videos on my YouTube channel if you're interested in learning more about test containers but we'll just leave that as it is for now so I want to focus in on some other tests and to do that let's go ahead and close this out I have uh brought in our inmemory run repository I think we overrode that um here while we were going through stuff but if you want to grab it from the repository it's there we've we went through this right this is just using an inmemory collection so I want to talk about how to test this so the first thing I'm going to do is go ahead and generate a test for this I can say create test and this will actually create out the right package and the name of the test for us now junit is looking for tests that end in the word test or tests so that's why it gives us this nice class name it says in memory run repository test yes this is great so I'm going to click uh okay and now we're dropped into uh this test and you'll see this test is now in the right package down here cool so now we can begin to write our tests now we aren't going to use any annotations on this we aren't going to do any kind of special things with uh the spring environment because in this case we just have a class that holds some data in a data structure um a list to be specific and we don't need to involve spring in this this is for me a true unit test right because all we care about is the inmemory Repository we'll call this inmemory repository although that's kind of long let's make it easier so now I have a repository um now if that repository gets created um we can um let's do actually let's think about this for one second so I'm going to in junit there are some special uh methods that we can use so we can basically say hey before each I want you to go ahead and do some setup in my application so I'll call this setup um and oh that's pretty good let me just I think I need a n here and a null here right um oops that was right here right uh so that looks pretty good so all we're doing is creating an instance of this repository now the reason we are setting up two runs is if we go into the inmemory repository we have a create method and um this method is actually going to get called by the life cycle in spring so this at post construct gets called and these get created in this case we're not involving Springs so that that init method is never going to get called and we want to have a couple of uh runs in the collection to be able to test against so now we can write a simple test we can say at test and we can say uh void should find find all runs um and yeah that's a pretty good uh assertion there so all we're doing here is and actually let me let me let me let me get this out of here let's do this let's say hey repository find all oops find all and give me a variable for that and we'll call this runs and then let's just do this just so we we can be a little bit more clear what's going on here right so what we're doing is we have an instance of the repository we've created two new uh runs in there we're saying hey if we call the find all method basically we're expecting two runs to come back we know that there's two runs in there we know that there's two that are going to come back there is a third argument here and you could basically give a message on what should have happened so um in this case we could say should have returned to runs right so now we can go in and we can go ahead and run our meth our test here and we see that it's green and green is good now you also hear of like tdd Styles so I come in I would write this method first and then I would make it fail and then I would go into the inmemory repository and write this method so a lot of the questions that come up around testing are like what should I test well like what are you writing what what classes are you writing in this case we're writing this inmemory run repository this is our code that deals with a collection of state so yeah we should be writing tests against this in this case we don't need some um integration test we're just testing this class right so um that's one test uh we're gonna we're going to kind of copy paste a lot of this I don't want to walk through every single method and every single test and actually these are going to fail because we need nulls here and again this is just because I wrote These before the database stuff went in remember we added that null so we have some tests here should find runs with a valid ID should not find a run with an invalid ID so it should throw some exception um should create new run although I don't know if that's going to throw an exception yeah maybe um we'll circuit so I just have a bunch of tests in here and we can run each of them individually or you can run them as kind of a suite right here um and then we got greens for all of those so those are good okay so that's our first test our in inmemory run repository what should we test next all right the next test we're going to write has to do with the jdbc Run repository so I'm going to go ahead and create a test for that now this is going to be a little bit different we are not creating a unit test we have to deal with some of the infrastructure in Spring and we also have to like talk to a database right we're like we're testing out this run repository so to bring in the test support with spring we could use that at Spring boot test annotation that we saw before but one thing I want to kind of talk about with that is at first your test might be very fast but as your application uh grows in size that might tend to slow the test down and that is because that at Spring boot test annotation is basically going to load the entire application context that means all the classes in your system that you might need it's going to go ahead and load those but for this class this test the jdbc Run repository test I don't really care about all of the classes in the system really only the classes that that that pertain to a jdbc test and so there are these things called slice tests in Spring and that says hey this is the slice that we're testing now only load all of the things that are equivalent to that so there are a bunch of this uh one of these is at jdbc test so if we go into at jdbc test and look at the documentation we can see that hey this is an annotation for jdbc test that only focus on jdbc based components this means that it's going to disable full autoc configuration and instead only configuration relevant to jdb jdbc test um by default jdbc tests are um transactional and roll back at the end of each test that's good to know right like if you add a new one and then you move to the next test that new one is no longer there um this also gives us an embedded in-memory database replacing any explicit or usually autoconfigured data sources this is important um we're okay we could be okay with using an inmemory database um but what if you wanted to to say don't do that just use the one that I have um so we need to understand how to do that so this is the at gdbc test annotation now I want to use that repository I want to say at autowired give me an instance of the jdbc Run repository right so uh we'll see in a second I don't believe that'll work but we'll we'll check that in a second um and I know we talked about this earlier when it comes to dependency injection we want to favor constructor-based dependency injection that really is in our own code in a test I don't think that makes a big difference because we aren't trying to test a test so using reflection here is okay in my books so we have a jdbc test we're going to um I'm actually going to just paste some code in here so we can kind of take a look at this again we're going to use a setup method and this is going to we're going to have to fix these so null so I promise you all of these worked at once but that was before I introduced the spring data component so you know we're using spring data now um so the uh entity uses um an ID on there and actually I think I may get rid of that for these tests so let's do that so let's go back into run and say that we're not using this right now and then in my schema I'll kind of remove this again this isn't something you'll have to deal with this is just me having to like show a bunch of different layers of abstraction and you won't have to deal with that so okay so uh let's see we have a jdbc repository test no errors so all we're doing here is uh we're calling our repository and we're creating some um and then we want to be able to click find all find by ID the same things that we did in the inmemory one but this time we're doing against the database now again which database are we doing it against uh if we don't do anything we'll be doing it against an in-memory database so let's see let's just I'm curious if see if that works let's go ahead and run that yeah I didn't think so um these things are going to start to complain still and don't worry those ones will still work now so let's try and run that again oh we have more more more all right and we have some failures but that's okay um that's probably not test failure so let's dig into here and yeah so uh fail to replace data source with an embedded database for tests we already have a database up and running right so how can we fix that again we don't want to use use that inmemory database we want to say hey we already have one up and running and we have one configured so I can just say Auto configure test database and we're just going to say replace none we don't we don't want we don't want you to replace it with a embedded one so now if we go ahead and run this we should be using the regular database and we're still having an issue I suspect it has something to do with us flip-flopping back and forth between all of the different examples that we're using but nonetheless let's see if we can't debug this in real time um no qualifying mean of type jdbc run repository is available so this is a good thing uh this is uh basically telling us that hey this run repository that you've tried to autowire into this test doesn't exist why doesn't exist this at jtbc test only loads certain things in certain Auto configurations so if it's one of those classes that we want that we don't have available to us we need to just go ahead and import it and jdbc run repository let's see if that works all right still some red um yeah I believe this has to do with um that already exists so again we're getting into a scenario where we're just hitting this because of all the fun testing I'm doing so let's just do this uh drop table if exists run um and then let's try and run that again so this will just basically create every time and there we go so again I think in the real world we are I'm using something like test containers I'm trying to avoid that because I don't want to like throw something else at you um but the that we're running into are all because of the demo stuff that we're doing so that is our jtbc run repository test we've now been able to write tests against two of those classes that we wrote early on I think the next thing that we really want to test is the Run controller and we want to test this from two different angles we want to write more of a unit test that just tests the controller the inputs and the outputs and then we want to test an integration of this we want to say hey if I run a test against this run controller that calls the repository I want to make sure that works as well so I think those are really those are the two tests left there and then we'll write a test against the user client that we wrote earlier all right so we're going to write a couple tests here for a run controller we're going to create a new test we'll call this the Run controller test that looks good um this is also going to be a slice test we are just testing the web thing the web slice so I can say this is a web MVC test and we're specifically testing the Run controller so I'm going to set up a couple of things in here and then we'll go ahead and write a test so at autowired because this is a web MC test it will autoconfigure Mach MVC autoc configure MVC autoc configure cache always drill down into some of these annotations and you'll find out that they are really just annotations that are annotated with other annotations but you can Dr into these to kind of figure out what those are but one of the things that it does is it gives us a Mach MVC and this Mach MVC is uh the main entry point for serers side spring MVC test support so we can create a Mach MVC then we can perform actions against it in a mock environment we can say hey I want to perform a git to slash form and here's what I expect to happen so this is really helpful in testing the input and the output of a controller also I'm going to autowire in the object mapper we saw this earlier when we were dealing with Json this is from the Jackson library that comes in with the web support and it allows us to basically convert things from Json to a type or from a type to Json here's where the fun begins now remember the controller is dependent on this thing called The Run repository that run repository talks to a database in a unit controller style test we don't want to we don't care about outside dependencies whether talk to database talks to a service we don't care about that so this is where constructure Constructor injection comes into play is we can mock this dependency we can say hey provide me with a mock Bean which is not a real one it's just a an inplace one um so this is really nice so we're saying mock this particular thing when you're setting up this run controller finally because we're not talking to a database we don't have any um runs so we're going to set those up here so how how do we write a test that uses uh a mock so first we're going to start with at test we're going to say void should find if I could spell right find all runs right come on D all right so now what we want to do is we want to mock out this repository we want to say no I took that we want to say when so this is coming from makito so um why that did that so when the repositories find method is uh called find all method is called then return this list of runs that I've created right and so again we're going to import that from makido so now we're going to use the Mach MVC framework here to say perform a git uh request so where does this git request come from I don't know why I can't find this this should come from mock MVC request builders. yeah so you can import that as a static if you want you should add exception for that so we're we're performing a get request against slash API runs and then what we expect is the status to be okay and here's where we're using that Json path remember all those libraries I said that get kind of brought in for us so um we're we're saying hey um from a result mattress standpoint what is the Json path and so let's bring um and let's bring inside is so basically we're saying hey uh this is an expression you can say hey like from the root give me the size we know that it's going to be one and we want to make sure that it's equal to the size of the runs which in this case is one so with all that in place let's see if that works and it doesn't that's okay we like seeing red first then we can figure out what's going on so hey the Run repository is not available um yeah that would make sense so run controller we want to Mack out the um I guess we're mocking out the wrong thing here so let's mock out the Run repository and let's see if that works now Okay cool so we got one of our U methods running which is finding all the runs now again I'm just going to copy some copy and paste some code in here so we don't have to watch me write this but now what we can do is we can say hey I I should find one run here's the run I'm expecting when the find all meth find by ID is um find by ID method is called and you match any integer then go ahead and return this I want to return an optional of run uh optional. of and then here's the run so now try to go get one run and expect that the status is okay and expect the data that we're getting back is this again we're checking the put so we're passing some path in here and then we're checking what we get back part of what we're getting back in the response is hey is it a 200 is it a 400 is it a 404 if it is a 200 what is the data so those are the things that we're checking in more of a controller unit test we're not testing the whole flow yet um and then we're testing hey what happens if you return an invalid one what happens if you create a new run or deleted or an update so if we go ahead and test this out and I believe that this may fail because we've switched over to this run repository again too many moving Parts but let's see if we can't fix it it's fun fixing things so let's see um I believe this is saying delete uh API runs and expect status is no content what is it um no value present that's because I believe the delete uh should take the actual run uh so we say API run1 delete and. content type is application Json content type right and then the content is the actual run so sure that looks good and then um do we get one too many there all right so now let's see let's go ahead and run this one actually let's just run a moan h no value present okay I'm going to skip this for now I'll have this updated in the the final repository so these are our unit tests more uh because we're not we're not including the outside dependencies but what if we wanted to write more of an integration test he I want to see the flow when we go ahead and do something and it talks to the database talks to the repository which talks to the database how can we get that to work so I'm going to create another test here but this time I'm going to call this our run controller int test for integration because we're integrating um other uh Services other libraries and so this is more of a full endtoend test all right so now we're writing the integration test for the controller I'm actually probably just going to write one method here for this one um but I'll try and get the uh final repo updated with everything so we're going to use at Spring boot test annotation now we're also going to set up a web environment you see the code assistants already there kind of helping me out we're setting up a web environment to say I want to run a server but I want you to run it on a random Port because this is a test I really don't care what port it's on as a test but when we do that we will need to know what port it's running on and to do so we can use the at local server Port annotation and then just provide a uh very able for that so now we have the server Port now we can set up a before each and we can basically say let's go ahead and set up a rest client so we're going to use a rest client here we've seen the rest client already and we'll say rest client and we'll say rest client is equal to uh remember there are some of those static Factory methods one of which is create um oh that looks pretty good thank you and we're saying hey go ahead and set up the base URL as HTTP Local Host not 880 but whatever that random server Port is right so with that in place we should be able to say at test and I want to uh again should find all runs and what I want to do is I want to use the rest client to actually make a call so I want to say restclient doget uh to the URI of API runs um so now that that's there again we'll just retrieve that we'll turn that into a body of new parameterized typed reference um and then from that actually from that I'll get a list of whoops from that I'll get a list of runs now I don't know why it's saying object I don't want an object I want a list of runs right so now that I have a list of runs I can say um let's assert equals and we should have 10 runs because we know 10 runs are in the database uh let's see if that works so now we're actually performing an integration test where we make a call into the controller it talks to the repository that talks to the database finds all of our runs and then asserts that that's equals so again uh We've written um some other test similar to this again I would just do this for find by ID postp put delete and call it a day all right so one last test I want to write here is for the user rest client so let's go ahead and create a test for that now we are not going to write this I'm just going to kind of show you this one but let's talk through this so there is a uh annotation called the rest client test and what this does is um it's an annotation for spring rest client that focuses only on the beans that use the rest template Builder or the rest Client app builder so this is again going to disable full autoc configuration and really all we want is the relevant stuff to a rest client test like Jackson or gson or some Auto configuration for Json components but not regular component beans so not all the beans are going to get loaded uh so if you find something you need in there uh you'll have to import that so what we also get from that if you look at this there's a autoconfigure Mack Ser Mach rest service server so we get this Mack server so we can use a server to make a call out um then we get the r client we want Auto Weare it in and then the um object mapper which we've talked about before so now we have a test here and we're using the given when then kind of set up and we're saying given here's one particular user I have um and I don't know new go L long why is this complaining oh this wants a double huh oh we set these up as strings for some reason okay those should be doubles I think they're doubles in the final so we'll fix that um okay so we have our user and then we say here's our list of users it really is just one so now we can use the server to say I expect a request to and in this case the Json placeholder service sluser um so we're not actually calling out to the server uh this public URL but we're kind of mocking that out and we're saying Hey I want you to respond with a success and here's the media type so let's go ahead and actually perform that go ahead and call the client. findall and I expect the users to equal this so we're kind of mocking that out and this is a way that we can mock those rest client calls out so um and you if we're performing a full integration test we don't need to mock that but this is a nice infrastructure to kind of to kind of test those out so let's see if this works and it doesn't uh yeah this is because double can't be converted to a string um is this same thing was I running all of those again I think in the final code this is a double so let's just try and run this one and there we go and let's try and run them all if they pass we'll kind of look through them real quickly um that one doesn't uh yeah okay that's just the expectation so there was the one and then this is to find by single one so we do that same request but now we're doing it to SL users1 we're saying hey respond with a success and here's what should I basically wanted you to write this value as a string so write the Json now I can go ahead and do this I can do a bunch of assertions here I'm saying hey make sure the name is this the username is this and the email is this and then oh I can use this assert all to make sure everything in the address is um what it's supposed to be again double versus string so if we run this again it so pass then we're saying hey uh phone website and Company I want to assert all of those so let's go ahead and just run that again to make sure that works and it didn't [Music] uh maybe we had these backwards let's see lat is 37 huh okay we'll rerun these hopefully third time's a charm and it is great so those are the tests now I know we didn't kind of spend a whole ton of time on these but I just wanted to give you the infrastructure like what is included in writing tests and what are the pieces that I need to understand you can easily go back through the repository later and actually like dig through every line of code if you want to here but I think just getting an overview of kind of what tests you can write what is some of the annotations that you'll use what are some of the libraries included that I help give you but again I would try to stick to once you get the mechanics down I mean you're you're just learning now if you're just learning spring boot you know build stuff first but once you get the mechanics down try to make it a focus of okay I just wrote this controller what kind of test can I write for it or even better before you write the controller start writing the tests for it um and this will just through repetition and writing these different types of tests uh you'll be writing all kinds of tests in no time uh so with that I hope you learned something I hope you enjoyed this section on testing I think that is close to the end of this course I can't believe it uh let's say a few words and wrap this thing up wow congratulations for making it all the way through this course I I hope you had a lot of fun I hope you learned something new in this course uh I had a lot of fun putting this together so I hope that shows through the videos that we made here today um again I want to kind of double back and say thank you to free code cam for having me thank you to all of you for watching this uh I have the get up repository here this is going to be a kind of ever living document this is a way for us to stay in touch so I'll keep updating this as the needs come in as issues come in if you have issues with some of this code or questions I'll open up discussions on this uh GitHub repo I also have a list of resources I'm going to put some more resources in here I have things like like books and other courses you may want to take but for now the resources in there are me so I have a website a YouTube channel again if you want to keep diving into some of this spring stuff uh Twitter account also on the spring side spring Academy I just launched one of my first free courses my free guides on there um actually there's going to be two on there now so free guide on 3.2 like a lot of the stuff that we talked today when it comes to the jdbc client the rest client virtual threads uh that will be included on Spring Academy so that's a free resource go ahead and check that out the spring developer Channel this is uh a really great YouTube channel with a whole bunch of spring content uh check out the spring iio website the spring blog if you want to stay up to date with everything in the ecosystem and Spring Office hours that a podcast that I am a host of and part of that is keeping you up to date with everything that's going on in the ecosystem as well as answering your questions so if you have a question about something you went here through on this course join us every Monday 1 pm Eastern may change in the future who knows you can always check out Spring Office hours.i to find out more about that but please come there with your questions tell me you went through this course that'd be awesome to hear um and with that uh those are my resources I'll update that again I'm honored to have been your teacher in this course uh very thankful to free code camp for hosting me very thankful for to my employer broadcom and the spring team for letting me do this it was a lot of fun and I can't wait for you to get your hands on this course uh I know I'm saying that as you're probably watching this but I'm saying this after recording this and ready to get this into the hands of you guys this was a lot of fun I appreciate it and as always friends happy coding