Transcript for:
Spring Boot Crash Course Overview

Welcome back, friends. My name is Dan Vega, Spring Developer Advocate for VMware, and today is an exciting day. This is a video I've been wanting to put together for a long time now, and it's finally here. This is my Spring Boot Crash Course. So I get a lot of questions. How do I get started with Spring? Spring does so many things. So we're going to talk about that today. What is Spring? What can it do? What is Spring Boot that sits on top of spring? Why are there two different projects, if you will? So we're going to talk through that and then answer. the question, how do I get started with Spring? For one of the use cases, which is building web applications, that's what we're going to do here today, and you're going to learn what you need to learn to get up and running with that. So we'll talk through some prerequisites. We'll talk through what is Spring, what is Spring Blue. We'll talk through the application that we're going to build here today. And we'll go through what you're going to learn. And then we'll jump in and write some code. So there's a lot to do. What are we waiting for? Let's get started. All right, so here I am in one of my favorite tools, Excaladra. And this allows me to just provide some great. and talk through some of the things that I want to cover today. So let's start with the prerequisites. What do you need to take this Spring Boot Crash course? So you need some experience with Java. We're using the Java programming language. You should have a beginner slash intermediate experience with Java. Experience with Java build tools. Maven or Grado, we're going to be using Maven today, at least understanding what Maven is and what it provides. That would be a big help. Software. We're going to use Java 17 today. So you should have Java 17 installed. You need an IDEE or text editor for Java development. I'm going to be using Intelli Idea Ultimate Edition. This is a paid version. You can get a 30 -day free trial, or you can use the free version. Use Visual Studio Code, which is free. You can use the string tool suite, which is free. So any of those will work fine. You need an API testing tool, something to like test your APIs with. So Postman's a very popular tool that's free. You can use curl from the command line or a really nice utility called HTTP. HTTP. I never know how to say that correctly. Or in IntelliJ, what I'm using today, there is a built -in HTTP client, which is really nice. Docker desktop, not totally required. There are, we're going to use H2 for an embedded database. At times, we'll switch over to Postgres. And instead of installing a Postgres database locally, you can use Docker Compose to spin a container up really quickly. In effect, when we get to production, we'll have to kind of step back and use postgrass as well in our development environment. We'll see when we get to that. Those are kind of the prerequisite. So if you fit that mold and you want to learn about spring and spring boot, you're in the right place. So let's kind of slide over here, maybe zoom out a little and see if we can't get into spring and spring boot here. The first thing we start with is a spring framework. The spring framework is used. It's a pretty massive project that's used for a variety of of applications. So we can build web apps. We can build secure, responsive web applications connected to any data store. These are, which we're going to go through today, is traditionally an imperative style programming using something like Spring MVC. We also have a reactive stack. So if you want some asynchronous, non -blocking architecture, you can reach for something called Spring WebFlux. You can use Spring to build microservices, quickly deliver production grade features with independently evolvable microservices. So if you have these services that often change and you want to kind of split them out into their own service, you can do that with Spring. Spring Cloud is this really great project, your code, any cloud, we've got you covered. And there's a whole bunch of services within Spring Cloud that allow you to help, help allow you to build cloud native applications. Serverless. Surveus is a big thing these days. And if you want to build functions, we have something called Spring Cloud Function, which is really great. It allows you to kind of write these functions in a spring programming paradigm, but not for a specific platform. But if you want to plug in and use something like AWS Lambda or Azure, you can. But you get to keep that same code base no matter where you're going to move your serverless functions too. You can do things like event -driven architecture. integrate with Enterprise, React to business events, act on your streaming data in real time. You can use it for batching. So I want to have some automated tasks. I want to do some offline processing of data at a time to suit you. Spring batch is a really great project for that. And something I've been getting into lately is Spring Shell. So if you want to build some command line interface, CLI applications, using the tools that you're used to using like Spring, Spring, Spring, Shell is a really great project for building CLI applications. So Spring is this massive framework that allows you to build all these different types of applications. That's great. So what do we need Spring Boot for then? Well, Spring Boot kind of takes that a little bit further and says, okay, we're going to help you simplify your spring development. And it does it by a lot of different ways, but there are three kind of core principles in Spring Boot. Spring Boot starters, auto configuration, and production ready. So in Spring Boot starters, when you want to create a new project, you declare something in your palm .xm. So traditionally in the past, you would have to declare all of the kind of dependencies that your project needed. So you'd have to list them all out, list all the versions, and figure out which versions played right together. Now what you do is you list out a starter. So in this case, Spring Boot Starter Web. and Spring Boot Starter Web goes, oh, I know all of the things you need to build a web application. You need SpringC., you need some logging support. You need an embedded version of Tomcat and you need Jackson and whatever else you might need. So that's Spring Boot Starters, kind of bundling all the required dependencies together and using the correct versions. Auto configuration is a way for us to say, okay, in the example of a spring boot starter web, if you're building a web application and you're connecting to a database. So I'm going to connect to a database. You probably want something like a data source configuration configured for you. Why would you want to go in and create that yourself? We know that you put a database driver on the class path. Let's go ahead and configure a data source configuration for you so you don't have to. So we provide a bunch of sensible defaults, but we also based on the type of application. you're building, we auto -configured some things. Now, you can always change how that configuration looks, but we're going to provide to you what we can out of the box, and that gets you half the way there. So instead of having to create this data source configuration, it's already there. You're connected to a database. You get to worry about the things that you need to worry about to build out the requirements of your application. All right, the next is production ready. So we start with the actuator. The spring boot actuator module provides all the of Spring Boots production ready features. We get things like endpoints. So we have a bunch of endpoints that can give us some insight into our application. What are all of the beans in our application? We'll learn more about beans today. What is the health of the application? Is it up and running? Is the connection to the database healthy, et cetera? We can find out info, metrics, mappings, and so much more through Spring Boots actuator. In Spring Boot 3, there's a big theme of observability. which is the combination of logging, metrics, and distributed tracing. The spring boot actuator kickstarts all of that. And with some settings, you get a whole lot of metrics and tracing out of the box. Finally, the ability to build something for production. We have a bunch of different ways that you can build an artifact that you can use wherever you're going to host your application. So if you want to create an executable jar, great. Anywhere that has a JVM, this jar will go ahead and run now. What about where we don't have a JBM? We could build a container using Docker or something like the Cloud Native BuildPacks to build an OCI -compliant image. Finally, in Spring Boot 3, we have this idea of native executables, which is really, really exciting, some really cool new features in Spring Boot 3. So that's a little bit about Spring Boot. I don't want to go too much further. I want to talk about what we're building and what we're going to learn today. So we're going to build a traditional kind of web app where we have a client that makes a request to a Rest API. This is really what we're building here. We'll build a simple front end for one of the examples, but most of the time, we're just going to use a tool like some API testing tool to call out to the rest API. This RIST API that's built in spring, we'll talk to a couple different things. At first, we'll just start off with this kind of in -memory collection of things because we haven't talked to a database yet, so we're going to kind of gradually build on those concepts. Then we'll move to a database. We'll use some different approaches to querying data from a database. So we'll dive into things like the JDBC template and spring data, all of which are going to return JSON responses back to the caller. Of course, using Java. All of the project source code for this will be listed on GitHub. You can find out more about it in the description below. So we're building a content calendar. I had to pick a domain. I went with this. I have a lot of content that I'm building and I'm just kind of kind of create a calendar of things that I have built or that I am building. So we're building out this calendar. It's a very simple domain. It has a content domain, things like the title, description. What is the status? It could be an idea. It could be something that's in progress, completed, or already published. What is the type? It could be an article I'm working on, a video, a course, or a conference talk. When was it created? When was it updated? When was it updated? And what is the URL to it? So what we're going to do throughout this is it, it's not a seem pretty simplistic, but there's a lot that we're going to learn by just building this out. So we're going to start at start. Start .Spring .io, which is this really great website that you can go ahead and bootstrap a new Spring Boot application from. From there, we'll talk about dependencies, what are dependencies, how should we go about selecting them, what if we need to create some later? We'll examine the project that gets created for us, including talking about those Spring Boot starters that we mentioned earlier. and diving into how our dependency versions declared. We'll take a look at the main application class, look at the annotation within that class. We'll talk about how to start our application. How do we start it from the IDE? How do we start it from, say, a command line? Finally, we'll get into how do we structure our code. We can kind of, we're given free rein on how to structure our code. What are some different approaches and where should our code live? Once we've done that, we're going to go into a whole bunch of different topics talking about, you know, Spring Corps. What are the core kind of fundamental concepts that you need to learn when you're developing spring applications, things like inversion of control, the application context, beans, and dependency injection. These seem like terms when you first hear them, that might be a little scary. They're not at all. They're very approachable. We're going to talk about that year in this course. Spring NVC is how we build our MVC apps, our model view control. This is our web application. So we'll talk through a lot of the annotations that you see when you're building this out. We're going to build a out at CRUD Rest API. We're going to test it using our API testing tool. We're going to talk about cores. So when you're calling an API from a front -end application, there's something called cores that you need to think about. And we'll talk about validating that data that comes in. Next, we'll move over to the data world. So let's talk about JDBC and how traditionally we use JDBC to connect to a database and query or get data in and out of a database. We'll talk about how to configure a data source, how to populate data into a database. We'll talk about the JDBC templates, spring data, and repositories. Next, we'll talk about production ready. So we've built our application out. We've got to start getting this ready to move to production. We'll learn a few more kind of core concepts like how do we work with configuration, how do we inject values using the at value annotation, or more structured data using configuration properties, what do profiles do, and when when we need them, and what is that spring boot actuator that we just heard about a minute ago. Finally, we'll talk about moving this into production. We're not just going to talk about it. We're going to do it. Here's our options, but we're going to take this and actually move this to a host. This is a free host that you can sign up for an account for. It's going to be free. It's not one of the big cloud providers. It's a really nice app called Railway that allows us to just get our application out there into production. The most important part here is you're going to follow along, but after this crash course, I want you to take what you've learned today and apply it to another domain. So say that you're very interested in maybe starting your own blog. You know, that could be another domain. Or maybe you want to create a place where you can keep all of your recipes. Whatever things are interesting to you, go ahead and take these concepts, apply it to another domain, and this is where some of the the real learning will come in, not only following along here today, but building your own projects using the concepts that we talk about today. So just jumping out, I will try and include this in the resources for this project. We talked about prerequisites. What is the spring framework? What is spring boot? What are we building? And what are we going to learn today? So with that, what are we waiting for? Let's just jump in and get going. When you want to create a new spring boot project, you should head over to start .spring .io. This is the spring initializer. It's a way to bootstrap a new spring boot project. This is a website where anybody can use it. Now, this same spring initializer is built in to a lot of the IDs and the text editors that we use. So what we're using today is an IntelliJ. If you're on the community edition, it's not available, but if you're on the ultimate edition, it is. If you are in a clips, you can take advantage of this. If you're using something like Visual Studio code. It's built into there as well. But no matter what ID or text editor are using, you can always start here at start .Spring .io. So what this is, is, again, a way to bootstrap an application. And the way that we do that is by filling out some data about the application that we're going to build. So we've already gone over that. We know what we're going to build. We know what things that we might potentially need in this application. Once we have that, now we can come over here. So the first thing we have to select is what type of project is this going to be Grado or Maven? I'm going to go ahead and choose Maven. You have to pick your language. I'm selecting, keeping Java as the selected language. Then you have to pick your version of Spring Boot. As long as you are, so at the time of this recording, the latest version is 3 .0 .2. If you're watching this in the future, this could be a lot higher. That's okay. Just take the current version. You should be okay unless we get into a situation. where we're on fourth, then we might have some breaking changes. So let's talk about metadata. This is data that describes your project. So we're going to start with a group. This is kind of the default package, right? So this is usually your domain in reverse order. So for me, that is Dan dev .com. Danvega because my personal website is Danvega. So if you were ABCcompanney .com you could say com .abst company. The artifact is the thing that we're building. So the thing that we're building today is a content calendar. And then you can go ahead and describe the project if you want. So let's say content calendar application, let's say, REST API. And then we have our full package name here. The packaging is going to be JAR. The version of Java that we're going to use is Java 17. then what we can do is we can start to add our dependencies. Now the dependencies, the way that I like to think about this is before I go shopping at the supermarket, I have a pretty good idea of what I need to get, right? I know what meals I'm making tonight. I know based on those meals, I know kind of what ingredients I'm going to need. So I write them all down on a list. That way when I go to the supermarket, I know what I need to get. We've already. We've kind of done that with our application, right? We sketched out what we're going to build today. We kind of know what we're going to be building in the entire application, but for the foreseeable future, for right now, we know this is really just a Spring MVC app. This is going to be a Rest API. So what I'm going to do is go into my dependencies and I'm just going to choose Spring Web. Now, if you go in there and look, there are all kinds of things. So if you want to do things like graphs, FQL or Spring Data or Oath 2 or anything that you can really think of is in this list. This is really just a starting point. Remember that. Our application is going to use a lot more than Spring MVC, but that's okay. We can always add dependencies later. So I want to just start with this and then we'll go ahead and add some dependencies as we need them. From the Spring Initializer here, you can actually go in and explore. This is what your starting project is going to look like. You can also share this if you want to share a similar project with a friend, or you can go ahead and click generate. And what this is going to do is download a zip file with all of that code inside of it. Now what you can do is open this up in your favorite ID or text editor. So we know that we're using IntelJ Ultimate. So what I'm going to do is go ahead and say, show me this in Finder. And then I'll go ahead and unzip this. And that gives me a directory with all of those files in it. And then I'm going to go ahead and open this up in IntelliJ. So one way that I can do that is I'm just going to drag this onto my IDE. And there goes, it opens up and it's ready to go. All right. So before we do anything, I want to take a look at our palm .xml. If you're not familiar with what a palm is, this is, this is part of the maven build tool. When we picked our dependencies from start .Spring .I .O and filled in that metadata, it kind of builds this file out, right? So here it declares the version of Spring Boot, which is 3 .0 .2. Here's our group ID, our artifact, the version of this particular artifact, and then name and description. We're using Java 17. And then here in the dependencies, these are all of the dependent. that we are going to be using in this application. So right now, all we selected was web. So we got this dependency. And whenever we build a spring boot app, we get this spring boot starter test to give us testing support out of the box. Then there's the spring boot maven plugin, which allows us to run the application via maven, build it, compile, do a whole bunch of things. We'll take a look at that in a second. So I want to talk about this idea of spring boot. starters. So if you haven't done a ton of Java development or been around as long as I have, there was a time when you had to kind of figure out all the different packages or libraries or classes that you would need in an application. You would maybe stick them in a lib folder and hope to God everything worked. Those days are long gone. We now have this tool called Maven and it allows us to say, hey, go ahead and pull this particular project or library into this project that I'm using. And then you declare a version. You say, I want to use Jackson data binding version 2 .19 .2, right? Here we don't do that. We're just declaring this thing called a starter. And what a starter is is comprised of all of these other different things. So if you remember back from the beginning of this crash course, we talked about being able to say, hey, I want this one thing. Go ahead and pull all these other things in. That's what this starter is. We can command click into this here in IntelliJ and it will dive into what that starter is. And you'll see it's nothing more than in a bunch of dependencies that are included. So the Spring Web includes the Spring Boot starter. If we were to jump into there, you'd see some more dependencies. It also includes Jack JSON support. So that JSON support is including the dependencies like the Jackson data binding, the data types for JDK8, data types for JSR 310, and our Jackson module here. So as we dive into these, we're going to see, then there's the Spring Boot Starter Tomcat. So this is how we get our embedded Tomcat. There's Spring Web, so this is going to bring in the basic web support, and then the WebMVC stuff is going to allow us to create these Rest APIs that we want to work with today. So just by declaring that one thing, this is a set of dependencies and particular versions that all work well together and give us the ability, the functionality to build a web application. So these starters are really, really handy. The official Spring Boot starters start with Spring Boot Starter Dash and something else. So we'll see some more of those later. But as you can see here, Spring Boot Starter dash tests, we can tell that that that's an official starters. The other thing we want to talk about is dependency versions. So if we come back up here, there's a spring boot starter parent. If we click into that, there is a spring boot dependencies. If you look in here, there is a bunch of dependency versions declared. So when you go to use something like the DB2, JDBC version, we have a version declared. All these things have versions numbers associated with them. And this is so that you don't have to declare them when you go ahead and include them. We know that those particular versions work well with the things that are in this particular version of Spring Boot. Now again, that's just to get you started. If you need to override that and declare a specific version, you can. There's nothing stopping you from doing that. But this is just what we know is to be tried and tested. Again, just one less thing you have to worry about figuring out which versions of which software play nice together. So we're done with the palm. The next thing I want to look at is kind of the folder structure here and what is included. So if I go in here, we have this dot idea. This is for IntelliJ idea. There's a dot maven folder. This is for the maven wrapper. So you don't have to have maven installed to be able to run this application from the command line. That is because of the maven wrapper. There is a source folder. We'll get in of that in a second. There's a Gitignore file, which is pre -populated with some stuff already in it, which is really great. There's just a quick help file, and then the Maven stuff, the palm .xml. So if we look at source, this is a normal Java project setup. We have source main and source test. So main is where our main code is going to go. We have a source main Java. And then we have that main package generated for us based on the metadata. data that we filled in. So we have dev .ddenvega .com content calendar and we have this content calendar application. This name is a little long for me. I always like to come in here and just rename it. I'm just going to name this application. And we'll click okay and that works for me. So now I have just this main application class. This is the main class. Every Java application has to have a mean class with a public static void main. This is it. So we have public static void main takes in some arguments. And what it does is it calls this spring application. Run and passes in this class as the class to run. So we say if we look at Run, this is a public static, returns a configurable application context. Even though we aren't really returning anything in this instance, we'll talk more about this when we get into application context and beans and so forth. But this is the magic that makes it happen. And this is how we can run our application. Now, this main application is annotated with this at Spring Boot application annotation. I don't want to go too far into this, but as we start to build at our Spring Boot application or using Spring Framework, you're going to see a lot of annotations. And it may seem like a lot at first, but it is way better than the contrary, which is we used to define everything in XML. So you have these huge blocks of XML. defining how your application works, right? Now we just have these annotations. So we just annotate a particular class or a method or an argument and we can do some cool things. In this case, we are annotating this with at Spring Boot application. And what this does is it does a whole bunch of things here, a whole bunch of more annotations that are on top of that annotation. So this is just a way to go through and configure your application and do some other things that we're not going to get into right now. It doesn't really matter for this point. I just wanted to point that out that your main application class is going to have the main at Spring Boot application annotation on it. And then you can always come down here and write more code inside of here if you wanted to. And we will do that at some point. But right now, this is enough. So now that we know what the kind of structure of the application is, we probably want to know how to run it. So there are a few. ways that we can run our application. The most glaring one here is right within our ID. So within our IDE, we have these little play buttons here in IntelliJ. We can run the main application. We can run this main method. We can also come up here and click this play button to run it. We can also debug it. So there's a debug here. If you right click, you can go to debug or run application with code coverage or profile it with Intelog's profiler. So I'm going to go ahead and just click this play button here to run our application. And as it starts up, you'll see some information in the council. We got this awesome ask -y art here, Spring. So Spring Boot, and it displays the version of Spring Boot you're on. And then there'll just be some logging here. So this is logging by the system. You haven't done any logging yet. This is the system kind of logging some things out, letting you know what's happening in your application. So we see that we have. are starting our application using Java 17. We have no active profile set. So we're following back to a default profile. We'll talk about profiles at some point through here. And then we can see that Tomcat was initialized on port 8080. So that is the default port as you'll come to find out everything in Spring Boot is configurable. Well, not everything, mostly everything. But we provide sensible defaults. Like we have defaults so that you don't have to go in and configure everything to just get something started. We provide some defaults, and you can always come back and change this later. So if you wanted to change the default port, you can. So we start on 8080. That's using Tomcat. We are on the latest and greatest here, which is Tomcat 10 .1. This is as of Spring Boot 3. We have moved to Jakarta EE10. So again, we'll talk more about that as we go. So now that we could see the Apple, has started on 80 and this is how long it took to run. Now if I want to stop this, I'll just go up and click this big old stop button and our application is stopped. So how else can we run our application? If we go to a terminal, we can open up a terminal. Again, we are using this maven wrapper. So if we go maven wrapper, there are some commands that we can run in maven. So if we look at, In Intelli, there's this nice maven tool here that shows us what is available. So we have different profiles, we have different life cycles, plugins. So we have a spring boot plugin. And these are all the commands that we can run as a spring boot plugin. So we could do things like build an image, run, start, stop. So what I'm interested in is this spring boot colon run. So what I want to say is spring. boot colon run and it's going to do its thing and at the end of the day this is running. This is the same application that started up before. You can just see here in the terminal we're doing all the same things and it's exactly how it was. Now if I want to stop it on Mac here I'm just going to hit Control C and that kills that process. So I'm going to go ahead and close that and close that and close my window. And I'm going to start it up one more time here. And with it running, I'm going to head over to the browser and I'll go to Local Host 80. And this is the default page that you're going to get, this white label error page. This application has no explicit mapping for slash error. So you are seeing this as a fallback so you can define your own slash error page. We can see the error. There was an unexpected error type not found. status 404. So there is just nothing available at the resource that we're looking for. So at the root context, there's nothing available. And that's true. We have not done anything yet in our application. So there is nothing available. So I just wanted to point that out because if you see that, you might think, well, something's not working. It's just because we haven't done anything yet. And we can also do that via the command line. So we have different. So if you view it in a browser or you view it from a command line, we see that as a different context, right? So we have this idea of context and we know how to display information to you based on where you're coming from. So here I'm using a tool called HTTP. And so what I'm going to do here is just make a get request to local host 8080. And as you can see, we are getting some information back. So we see that it's a. a 404 error. So we're in the context of a command line, we're just going to send you back JSON. We're not going to send you to a page, right? So we send you this. Here is the content type application JSON. Here's the response. And then here's the actual response. You're getting an error. The path is this and that is not found. Okay. So one final thing in this section. I just want to talk about structuring your code. So now at some point, you're going to start writing your own code. So remember, we have this source main Java, and then this main package. The first kind of advice that I will give you is that you want to place all of your code within this particular package. You don't want to start creating code outside of here. So if you create something in the Java folder, it will basically be a default package, which means no package. And you don't want that. It's not going to find it. It's going to be. really hard to use here inside of our application. And it's just going to make things a bit messy. So kind of tip number one is whenever you create something new, try and make sure you create it underneath this package. You can create sub packages. So I can come in here and create a new package called controller. And you can create classes inside of that package and so on. But this is the root package. Try and keep all of your classes inside of here. Now the next thing I want to talk about is kind of how you would structure your application. The nice thing here is that spring doesn't really care. This is up to you and your team. So you could put everything inside of this main package and not, you know, create sub packages. You can just stick a whole bunch of classes in there if you wanted to. Probably not the easiest thing to maintain that way, but it's it's going to be just the same. It'll work. So there are a bunch of different approaches to how you could structure your application. So you could structure them. You'll see me do a lot of this in my kind of demos where I'm structuring them by the type. So in this case, I have a package for my controller. I might have a package for model. I might have a package for service and then config and repository and all that. And then no matter all the different types in my system. So if I have like a content. So when we get into this, we'll have like a content type, a status type, a tag type, type. Those will all go in the model folder. And then I have a content controller and a status controller, et cetera. So that's how I'm organizing my content in this particular course. But you could come in here and say, I want to kind of pack, you know, I want to separate these by the different resources in my system. So I may say, you know, I may say, like, I'm going to have a content and I'm going to have another package called user. And inside a user, all of the things are going to be there. The model, the controller, the service, the repository, all of the things that deal with a user are going to be in that particular package. So again, there are some pros and cons to you each. I don't think, you know, somebody can come along and tell me otherwise. I don't think it's, at least for what we're building here, it doesn't really matter. So I think the thing to just take away from this is that it's really up to you how to structure your project, but the one thing you want to do is try to keep everything under that main package. Okay, so with that, we know how to run our application. We know where code's going to go. Let's go ahead and talk about some of the fundamental core concepts of spring. Before we dive in and start writing some code. I think there's, we need to take the opportunity to talk about a few core concepts in spring. Now, we could talk about a lot of the core concepts in spring and a lot of the fundamentals of Spring Boot, but I just want to cover a couple and then we'll start writing some code. I don't want this to be too much theory. I want us to learn a little bit theory and then apply that in code. So I'm over at spring .io. If you go under projects and go to Spring Framework and you go to learn, there is the reference stock. So let's go ahead and click on the reference stock. And just so we're clear, 6 .0 .4 is the latest. That is GA. When you select Spring Boot 3 .0 .2, this is what you're pulling in. You are pulling in whatever the current is, most of the time when you're on the latest version of Spring Boot 3. So we go over to the documentation and I want to take a look at the core section. So we're going to talk about the Spring IOC container, the application context, and beans. And again, we're going to cover this at a very high level. We could spend a long time doing this, but I want to be more practical with this and kind of apply this stuff in code. So you can take the chance to go through this documentation, but what we're going to talk about here is mainly the IOC container and what that means. And when it comes to kind of the application context and beans in spring. And so these are two terms that you're going to hear that you may hear and they may kind of start to scare you off because you're like, what the heck is that? What is an application context? What is a bean? And I want to take the chance to kind of go through there. So let's start with the IOC container and the application context. To do so, I'm going to head back over to IntelliJ. I'm going to go ahead and on the Mac option command O. There's a way to get up here and go to, I'm going to type Command O here. I'm going to type Command O here. I'm going to look for something called the application context. And we're looking for the one here in Spring Framework. So if I go ahead and click on that and pull down the sources, we can see that this is a interface and it extends a whole bunch of other interfaces. So let's kind of scroll up here and take a look at the definition here. And this is a central interface to provide configuration for an application. This is a read only. while the application is running, but may be reloaded if the implementation supports this. And then here are the different things that the application context provides, one of which is a bean factory. So we can think of kind of the application context, the container of the application. I like to think of it as this bin. Let's say I had a bin in my house here and I had a bunch of books in the bin. Each of the books have titles on the side, but the bin is really just a place to store all of these books, right? So I have a bunch of books in a bin or on a bookshelf. And when I want to get a particular book, I ask for it by title. So give me that new book on Spring Boot 3 in action, right? Give me that book by that title. So the container or the IOC container or the application context is a way for us to get classes when we need them. And we can get them by name, we can get them by type, we can do a whole bunch of things. But at the end of the day, the container is just this bin that holds all of the classes in our application. And at any time, we can go ahead and ask that bin for a particular class. So I want to see this in action. This application context extends a whole bunch of other things. And that's what gives us some of the functionality that the application context has. So if we look at the packet structure here, we can see that in this application context, we can do things like get the name, get the display name, not a whole lot here at this level. But then if we go into something like the listable bean factory, we can do things like find out all the beans in my application or get all of the names of all the beans in my application. So there's some more functionality here. And then as you go on into some of these different interfaces, there's a whole bunch of functionality that we can get out of this. So that's where I want to start. What is this kind of application context? The reason I bring that up, if we go back to this, remember that this static method, this run method, actually returns something called a configurable application context.! Configurable application context extends that application context that we were just looking at. So what that tells me is if I come back here and I a variable. So I could say here, here's our context. Now I have an instance, right? I have this context that I could probably do some work with. So one of the things I can do is remember the context has that Git bean definition names. So what is this? This is going to return a an array of strings and this is all the beans defined in the factory. So hey, this is great. I can get all the beans that are in my application, right? And one thing that I might want to do with this is turn this into, let's say, a stream. So we're going to use arrays dot stream. We're going to have all of the beans, at least all of the bean names. And then all we're going to do is say, for each. I want you to go ahead and print them all out. So let's go ahead and print them. And again, this isn't something you'll have to do in your application. I just want to kind of show this off so we can see what's going on here. So if I go ahead and run this application, you see a whole bunch of things were printed to the council here. And again, these are all the beans in our application. I say, Dan, I didn't, I didn't write anything yet. What are all these things going on in the background here? And that's exactly what they are. They're happening. in the background. These are beans that the framework has created for us based on the type of application that we are building. With one exception, there is one here called application, and that is our application. So that is also a bean. So these are all the things that are going on in the application right now. Again, you won't need to do this. This is just a little handy trick. And I wanted to point that out because I want to talk about beans. So we keep hearing the word being. What is a being, Dan? So I want you to go ahead and virtually, I know you can't see you, but go ahead and raise your hand if you've ever created an instance of a class. Okay. I'm looking out virtually over the entire audience right now, and I see a lot of you raising your hands. That's great. That most of us have done that, right? Well, at the end of the day, that's all we're doing. We're creating instances of classes. A spring bean is nothing more than an instance of your class with some configuration metadata around it. Things like what is the name? What is the scope? There's a whole bunch of things. And if you want to go back through the spring documentation, you will see that. So now the question becomes, okay, this application class was created. How do we create our own beans then? How do we do this? So let's go ahead and. take this for a test run. Let's create a new Java class. And we're just going to call this message. So if I go ahead and create this class and I save it and let's say maybe we have a method in here. Maybe we have just a public string get message or actually let's say get get. Yeah, that's fine. And then we're going to return hello. So this class does nothing more than have a method called get message, which returns hello world. So now if I go ahead and restart my application here and I look for something called message. I see a bunch of things called message in here, but that's not the bean that I just created. So what happened? I created this class. Why isn't Spring adding this to this big container we keep hearing about the application context? And that's because Spring needs to be told about the application context. And that's because Spring needs to be told about the classes that you want it to manage for you. There are a couple different ways to do this. There is at a class level, we can use annotations. So the generic annotation that you'll see all the time is at component. And if we go ahead and dig into this, you'll see that this indicates that an annotated class is a component in such classes are considered as candidates for auto detection when using annotation -based configuration and class path scanning, which we are using. If you do some searching for spring out in the wild, you may see a bunch of old examples where there's all this XML defined, and we just don't do that anymore. We use annotations and Java -based configuration so much easier. So that's what this is saying. This is saying, okay, if you add this annotation to your class, we are now going to know about it. The application will know about it, the application context, and it will add it to a its container. So let's go ahead and run this again and now look for message. And you see there is a bean called message. Now the way that the bean name works is it just takes this class and uses camel casing. So it'll start with lowercase M. If this was like message source, it would be lowercase M capital S, right? So that added it to it. Now, there are, again, I don't want to get too far under the weeds. There are ways to configure like, what is the being named? By default, this is a singleton. There'll only be one in existence in the application. There are ways to kind of customize that. Again, look through the documentation. I think it's a good just to kind of get this over review and then you can dig deeper if you want. So that's a component. There are specialized versions of this, which we're going to see throughout this crash course. There is one called a service. There is one for a rest controller, which we're going to be building on. on today, which is nothing more than a controller. And as you'll see with all of these specialized annotations, they are just made up of other annotations. But at the end of the day, they're all components. So if you wanted to just use component, you can. If you wanted to use the specialized versions of these, there's repository. And yeah, so there's a handful of them. So that's it. So now I'm going to go ahead and delete this message. I'm going to revert this because we aren't going to, like I said, need this anymore. And I just want to show you one other trick. So if you don't want to have to output all the bean names, which you probably don't want to, you can just run this application. If you're in IntelliJidea Ultimate Edition, you can come down to our spring tab here. And you'll see there's a beans tab. So we can click on content calendar. We can click on the application, on the application, and these are all the beans in this app. We can see application. We can see kind of how it was configured. So if we go down to something like the cash manager, we can see that there is a simple cache configuration. And then the bean is coming from that cash manager. So real nice way to kind of dig into kind of the internals of what's happening here. But instead of having to just kind of print these out to a council, which you won't want to do, there is this nice UI in IntelliJ to print out all of these beans. Okay, so now there's one more instance. So we saw all of the annotations, component, controller, service, repository. Those will all work at a class level. But what happens if you don't have a class? What if you are creating an instance of a class, maybe that you don't have the control over? Maybe you can't just slap an annotation on it. Let's look at an example. So I'm going to create a new package, and we're going to call this config. And inside this config, I'm just going to call this my web config. So in here, in my web config, I may create something of a type called Rest Templet. So Rest Templet is something that the Spring Framework provides, and it's a client that you can used to say call out to a public API or another service within your organization. And so what I want to do is create an instance of this rest rest template. So I would say return new rest template builder. Builder. That build and that will return a new instance of that. Now the name of the method is the name at the end of the day will be the name of the bean that we use. But how do we create a beam? So we can't use that component. Like I said, this is a class level annotation. So it's going to tell us that that we can't use it here. So we have a method level annotation and that is bean. So the bean annotation, if we go ahead and look at that, indicates that a method produces a bean to be managed by the spring container. Again, there's some really good information here in the documentation. You may want to dig into that. But that is the bean. The name of the bean is going to be the method name. So this name of this bean will be rest template. And if we go ahead and were to run this now, nothing would work. Why is that then? When you want to define a bean, you need to do so inside of a configuration class. So you need to mark this class with at configuration. And now it will go ahead and say, okay, I'm going to look for bean definitions. And in fact, I found one. I'm going to to go ahead and use that and put that in the application context. So if you were to run this again, look at the bean definitions. You would now see an instance of rest template. And again, why this is important is anywhere that we want to use an instance of a rest template before we had our message class, now the application context is handling it for us. So we can just get an instance of it. And to show that off, let's go back to our class here. And let's say that we want to create a bar. Let's do this again. Context. And what I could say is context. Get bean and get it by the name. So I might say arrest. Oh, whoops. I'm sorry. Rest template. And that is going to be, so it's going to be an object. We can go ahead and cast it to that. If we wanted to, say rest template. because we know that's what it is. And let's just go ahead and do that. And we'll run this. And you see that we just get that signature there. But then we can go ahead and use this if we wanted to. So one of the methods in a rest template is to go ahead and get for an entity. So we could call a URL and get a. response type of type, whatever. So yeah, just an example of using bean. So at the at bean annotation is used when you need to define a bean on a method that returns some class. So again, I think you can take some time to go through the documentation after we go through some of this stuff. I wanted you to kind of get this high level overview. We'll write some code that will help kind of reinforce. it and then, you know, after this crash course, come back and dive through the documentation and really go through and take a look at what the container is, what these beans are. There's some really, really great information in here. It can just be a little inundated if you haven't done anything with it yet. All right, so let's start writing some code. The first thing that we're going to focus on here is the domain in which this application is kind of built around. As we talked about, this, the idea here as we're building out like a content calendar. So I'm going to start with content. And to do so, again, you can kind of split this up however you want to divide your application. I'm creating a model package here. I'm going to create a class inside of here. Not just a class, I'm going to create a record. So we're going to create a record around the idea of content. So that is going to be our main type. Now when you define a record, you don't define properties, you define these components of a record. And as you can see, I'm getting really good at this. Let's go ahead and turn GitHub Copilot off just for now so we can work through this. So I'm going to start with an ID. We are going to have a title. So what is the title of this piece of content that I'm working on? We're going to have a description to describe that content. I want to have a status for the content. So this is going to be an enum. We'll go ahead and create this in a second. I also want a type. We'll call this content type. This is like, is this an article or a video or anything else? We'll create that in a second as well. That should just be an enum as well. And then I have a local date time for when this piece of content was created and a local dates time for when this piece of content was updated. So this could be null to begin with. Then we'll have a URL where this content is located. So cool, that is pretty good. Then what we're going to need is a status. So in IntelliJ, I'm control clicking, control enter. We're going to create an enum for this right inside our model package. So this is going to be, let's talk about it. So status, I want to start with an idea. So I have an idea. Then after it's an idea and maybe a work in progress. Then when it's done, I'll say it's completed. And then after it's completed, it's now published. So those are some good statuses to start with. Next, I'll go ahead and create a type. This is also going to be an enum. And we will go ahead from here. And these could be, we could have a whole bunch of types here. I'm going to start with article, video, video. course and then maybe a conference talk. Those are some good ones. We could expand on this later, but that's a pretty good start, I think. So there it is. That's our record. We have an ID title, description status, type, date created, date updated, and a URL. We may add the something in the future for like tags. So if we wanted to like tag this particular thing with like spring boot and graph QL or whatever we're the topic. or categories that we're kind of talking about. But we'll revisit that later. So I think this is a good start. With our model in place, we can now start to write some code around this idea of a piece of piece of content in our system. All right. So with our content model in place, we can begin writing some controller code. So I'm going to, in a package called controller, I'm going to create a new Java class. Now, the convention for this is the resource that we're working on. So that is content and the suffix of controller. This is not a hard role. You do not have to follow this role. You will just see this in a lot of spring applications. So in this case, it's going to be content controller. And this is a class. That's what I'm going to stick with here. So as we've created this class, we've done nothing special. It's just a class in the system right now. What we're going to do now is mark this with the at -rest controller annotation. So we've already kind of gone through this. You understand that this is a specialized stereotype, which is really just annotated with that controller. So this is saying, hey, I want to go ahead and I want you to pick this up and create an instance of this controller for me and stick it in the application context. The next annotation we're going to mark this with is request mapping. So request mapping is, hey, What is the path to this controller? How do I go ahead and get to this? And in this case, we'll just be API slash content. So now, what is a controller? A controller is really just a class that is going to accept requests. So I'm accepting a request and I'm going to return a response. You'll find a lot of the CRUD methods in here. So, hey, I want to list all the pieces of the content in the A application, whether it's stored in memory or in a data. base. Hey, I want to find one particular piece of content. I need to create, read, update, delete, filter, sort, page, you know, all of the things you might do around a particular domain like content that we're working with. So that's the first two kind of annotations that you need to understand as we're building out an NBC application. Now, before we go further in here, I want to create another class. So we're going to create a new pack. in here. I'm going to call this repository. And inside a repository, I'm going to create one called, let's create a Java class called Content Collection Repository. So I'm not just going to call this content repository because we're going to call that one later when we create a Spring Data repository. So this is not a Spring Data repository. We are not talking to a database. But I am going to mark with that repository because again, that is a specialized stereotype marked with that component. So now our spring application context will pick this up. And what we're using this for because we're not talking to a database yet is to just keep a collection of pieces of content in memory. So that we can work with them in our application. So to do so, I'm going to create a private final list of content and we'll call this. content and this is just going to be a new array list. So we're going to initialize this array list here. We're going to have a constructor and then we're going to have a couple methods. Let's just start with one to list all of our content. We'll call this find all. And that's just going to return content. Then we need a way to get a single piece of content. And I'm going to have this return an optional. So if you're not familiar with optionals in Java, this is basically a way that a value may or may not contain a non -nall value. So it's just a way to kind of not have to deal with nulls and get those like null pointer exceptions. So there are methods around this to say like, is this thing present? If so, then I can go ahead and get the actual value out of there. And so the reason I'm doing this is this. is this is what ultimately the spring data repositories contract looks like, and I want to keep this kind of similar. So we're just going to say fine by ID, and we're going to take in an ID. Now, why is this an integer? Because our content has an integer ID. So when we're looking for a particular piece of content, we're asking for it by its ID. So I'm going to get that array list. So I'm going to get that list of content. I'll just turn that into a stream real quick. I'll filter on that. And now I can say, hey, go ahead and give me the ID of the content. And I want you to see if it equals the ID that was just passed in. If so, go ahead and find the first. And that returns an optional. So if we look at that, that will return an optional of type T. Okay. So with that in place, now we can come back to the content controller and talk about dependency injection. So we've learned a lot of the concepts of this already. And I'm going to leave a link to a video that I've done on an in -depth tutorial on dependency injection in spring. I don't want to go too far in this because I don't want to make this video too long. So we'll just cover this very quickly. But let's say that we had a, actually, let's go ahead and generate this. Let's say we had a constructor here. And we need an instance of this content collection. repository, right? We need that because we are going to use it here. We're going to use it in our controller. When someone asks for all the pieces of content, I'm going to delegate to that content collection repository to say, hey, go ahead and find me all the pieces of content in our system. So one way you might do that is you might create, let's get rid of that, you might create private content content. repository and call this repository. And then here in your constructor, you may say repository is equal to new content collection repository. So this might be your first kind of take on how to accomplish this. But anytime you see the new keyword in spring, it kind of should raise your eyebrows, right? Because we've talked about this thing called the application context, which is responsible for managing all of the instances of our classes in our application. That is why it's also called inversion of control. We are no longer responsible for creating new instances of our classes. We are putting that onus on the framework. The framework is going to handle it for us. So we no longer should be doing this. And we know, based on what we've learned already, that marking it with an component, there should be an instance of this in the application context. So ultimately what I'm doing now is creating two instances of this in my application when I only need one. So we want to get this from the application context. We want to inject any dependencies that this controller has into the constructor as one form of dependency injection. So we are dependent on this class for our controller to work. So that is a dependency. So there are ways to get this dependency into this controller class. I'm only going to mention the one because it's the preferred one. Again, go back to the video that I'm going to link to if you want to kind of learn about all of them. So what we're going to do is make this an argument to our constructor. We'll call this content collect. repository and now we can say this dot repository is equal to content collection repository. Now an easier way that I like to do this, especially if you're here in Intel .J, we are going to make this final because we don't once it's created, we don't want to have to change that. We don't want to recreate it. This is a final variable. Once it's created, it's done. When you do that, IntelJ will put this little squiggly here and say, hey, oh, do you want me to add a constructor perimeter for you? Yes, I do. Now I automatically get that created for me. So now I have that constructor. This little icon over here in the gutter says, is telling me that we have a auto -wired bean being injected into this constructor for me. This is also the same as saying at auto -wired on the constructor. At auto -wired is basically saying, hey, this is a This is something I want injected. So this is an alternative to this annotation. But when you only have one public constructor in your class, this is implicit. So you actually don't need it on here. It's the same thing. The framework will kind of add it for you, but that's what's happening. So now I have an instance of the content collection repository. So now, now I have an instance of the content collection repository. So now I want to create something that allows someone to make a request and find all the pieces of content in the system, right? So how do I do that? Well, first, we write a method. We're going to write a method, right? This is going to look eerily similar to that one we created before. We want a list of content where you're at. where you're at. There you are. And we're going to call this one find all. Again, you can name this whatever you want. But how am I going to get all of the pieces of content? I'm going to use that repository that we had injected into this controller for us. And there's a method called find all. And I know because we just wrote it. That also returns a list of content. So I'm going to do that. So now I have my method. Now I need to make this available. to the outside somehow. So there is an annotation called request mapping, which we already saw up here. But there are also specialized versions of that request mapping annotation. One of which is Git mapping. So Git mapping says, I want to go ahead and handle Git requests. And what is the path? I'm going to leave this as an empty path. Because we've got a request mapping on the, class itself. So the path for this is going to just be slash API slash content. That means once we start up the application, if we go ahead and visit Local Host 80 slash API slash content, we should get all of the pieces of content in the system. So if we do that and we go to generate a request, so here is that request. If we look at that, everything is fine. we got a 200. We just got an empty array because we don't have anything in the system yet, which is fine. We can go ahead and create some if we wanted to. So we could do this a couple different ways. We could go ahead and do this in the constructor if we wanted to. You can also use something called a post construct. So this is, hey, I'm going to have some method that is not going to return anything. I'm going to call this a knit. And now this post construct will get called after this, let's just double check with the documentation says. I believe it's like after the post -construct annotation is used on our method that needs to be executed after dependency injection is done to perform any initialization. So again, all we're doing here is we're saying, let's create a piece of content. So content C is equal to new content. So now we have to provide. all of the information for this. So I may have one. What is the title? Let's just call this my first blog post. And I'm going to see if I could get this on separate lines because this is going to get pretty long. So I have a title. I now have a description. So that is going to be same thing. My first blog post. Then I'm going to have a status. So let's just say that this is an idea. The type is an article. The day created is right now. Has not been updated yet. And the URL is just an empty string for now. So there is my first piece of content. So now what I can do is say on the content. This is the list of content. I could say content. Add. And then I'll just add that particular piece of content. So now if I go back to this and I actually restart the application. We can see that in there. And again, I don't think we've gone over this yet. I just assumed that we did. So let me go back to the browser. And remember, local host 80 is going to be, have that error because we haven't created anything there, but we did at API slash content. So this is one way that you could test it. I'll show you the, , the HTTP client in Intel .J and in a little bit. So before we would have, we would have gotten this empty array. Now we have a single piece of content in our system. So with that in place, we have a way to kind of list all of the piece of the piece of. of content in the system. We really want to build out the rest of CRUD, which is create, read, update, delete. And we won't get to them here today, but this could also be any other methods that need to be in this controller. So if you wanted to like filter by something or do some like paging and sorting or whatever else you needed to do. So let's go ahead and build out the rest of that in the controller now. All right. So next we need to provide a method to go ahead and get a particular piece of content by its ID. So we're going to use get mapping again, but this time we're going to want to use an ID. So I might do something like this, right? I might say, okay, at slash one, go ahead and get me the content for, , that has an idea of one. But this doesn't scale very well, right? Like we would have to create this and do this. Oops. And we'd have to do this like 27 ,000 times if that's how many pieces of content we had. So what Spring does is gives us the ability to use a dynamic placeholder here. And we could say, okay, ID is there. I want to look for something, , for some ID. This is going to be dynamic. And then we can reference this in our methods. So I want to go ahead and return an optional piece of content. And we'll call this fine by ID. And now the ID is going to be of type integer. And how are we going to map this thing to this thing? And that's what the path variable annotation is used for. So it's going to assign whatever's in the path to this particular argument name. All right. So now that we have that, we can go in our method and we can say, I want to return. Let's think about this. So if we just return, return whatever the repository. Find by ID and pass the ID. That may work. Let's see if that'll work. So we're going to restart our application. We're going to go over to the browser. And we're going to get all of them. And now we're going to say, give me one by its ID. So if I do slash one, great. We get that one particular piece of content. This is great. So at this point, you'd also want to probably handle for what is going to go wrong. So like if I ask for something that is at 99, I'm basically going to get knoll back. So what we could do is say, we're not actually getting that. We're saying, , we're not actually getting that. or else throw. Let's throw a new response. So response status, response, status exception. So we're going to throw a response status exception. We basically want to say that the status is not found. So that's like a good 404. And then I provide a message and say content not found. Okay. Um, this is complaining why. Uh, this required type is optional, but what we provided was content. So I think this is because of our fine by. Find first. Right. So we're actually returning the content here and not the optional. Okay. That makes sense. So let's go ahead and restart that and check this out as well. And so now if we throw this, we are getting a 404. We can't find that one. And if we ask for one, we are getting that particular one. So so far, so good. This is looking good. Now we need the ability to create a new one. So let's go ahead and say public void. We'll call this create. And we need to take in some content. Right. Then what we can do is we can use our repository. We can call something, let's just call this save and we'll pass in our content. Now save does not exist over here. So we need to go ahead and create this. So here all we're going to do is we're actually going to say content. Oops. So we don't want to call this content. Because our collection here, we should probably rename this. This is a terrible name, Dan. Let's call this content list, right? So now I can say content here. Call this content if I wanted to. And I like this to be last. Okay, so content list. Add this piece of content, right? So this is almost going to work, but we will have to like provide the ID for this, which is okay. We can create like an atomic integer here and maybe we'll do that in a minute, but for now this should work okay. So now the question becomes, okay, well, I need to handle this in a post request, right? When we're creating a new resource and a rest application, we're using a post request. So the way that we handle this is by, so again, we have specialized mappings for Git. So as you can imagine, we have a specialized mapping for posts. So we call this post mapping. Now this can take in whatever the path is, so like API slash content. But again, we've already set that at the class level. So we can just do the same thing we did with the Git mapping and have, have an empty mapping here. So now this post mapping is going to respond to a post request at slash API slash content. Now, the only other thing here is we have this content, but we need to somehow tell Spring that this is going to be sent as part of a request body in a request, right? So the way that we do that is by using the request body annotation. And so if we dig into this and download the sources, it'll tell us that, hey, this annotation is going to indicate that a method parameter should be bound to the body of the web request. And so we'll see what that looks like in a second. So now we can't really use the browser anymore. So we've done some initial testing. I'm using testing lightly and in air quotes. The testing is just, hey, let's make a request and see if it works. But we've done that in a browser because the browser can handle a great request. We can't do a post request just by putting a URL in a browser. We need a tool for this. So there are some great ways to do this. You can do this from the command line using something like curl or one of my favorite, HTTPIE, which is just a better version of curl that adds in a lot more support for doing things like this. There's a tool called Postman, which if you've been in this world, I'm sure you've seen or used. I like that one as well. The one I kind of showed you already was the HTTP client here in IntelliJ. And I really like that because I don't have to leave the tool that I'm in to do something. So I'm going to do that. So I'm going to go to, well, you could just say generate this request in an HTTP client, but I'm also going to show you a trick here, which is you can create a new file in your project. And I'm going to just call this content. Content dot HTTP. So anything that ends in dot HTTP will be one of these files that the HTTP client can use. So we've already seen we can do something like, where is this one? Let's just show what this one looked like. So let's copy these back to our one. So the triple pound sign here is like a comment. So I can say, find all content. I can say get content by ID. And now what we can do is say create a new, create new content. And so what we want to do is we want to do a post, right? So we want to do a post, right? So we want to do a post to this particular URL. Oops, to this URL. So how do we add the body for that now? Well, the first thing that we need to do is we need to set the content type to application slash JSON. And then down here, we can just give it a body. So here is what the body is going to look like. So one trick I have here is let's just run this one where we get a particular piece of content. And all I'm going to do is copy that now. And this is what the request body is going to look like. So I'm going to say this is my second blog post. My second blog post. This is an idea. This is also an article. We'll just keep that same day created, date updated, and our URL, which is going to be blank. So if I do this, I'm going to go ahead and restart my application. So this should take into account the new mapping that we have. I'm going to try and post this particular request body to slash API slash content that would create a new post. Now, the response says it was a 200. I have no response body because in fact, if you look at my controller, I've basically said, I'm just going to return nothing for this. So the only way to kind of check this now is if we go ahead and list out all of our content, we should see that we have two in there. And we do. So we have my first and then my second. So this is great. But one thing I want to add to this is whenever we create a new resource in a system, the caller who's making this request should have a better indication that something was actually created. And to do so, we can use the response status annotation and say that we want to return an HTT. status HTTP status. Dot created. And that will create a 201. So now when we restart our application, we only have one in our system because that's all that loaded up. I'm going to go ahead and create that second one. And now you see we get a 201. So at least we have some indication that a new item was created in the system. All right. So we have our lists. We have our get. We have our create. We need a update and a delete. So let's work on the update now. So the update is going to look pretty similar here. We're going to have a public void. We'll call this update. We are going to take in the request body of content, content. We are also need to figure out exactly what piece of content we're trying to update. So we may say integer ID. Let's just return null for a second. So actually, we don't even need to do that because we don't return anything from here. So this should be an integer, Dan. And now we're going to use, so whenever we create, whenever we update something, we are not performing a post. We're performing a put. And so we also have a mapping for that called put mapping. And again, this is going to be similar to the read. We are going to be working on a, dynamic ID. So we're going to say slash ID. And then we can go ahead and use the path variable to get that idea out of the path. So now that we've done that, the first thing I want to do is make sure that that ID exists. So let's write something to say if the repository, let's create a method called exists by ID. And we'll pass in the ID. So if it doesn't exist by ID, then we're going to do something similar to this. We're just going to say, row, new response status exception, content not found. And then we're not going to do this in this crash course. We'll probably jump to this in more of a full course, but I would probably create a custom exception for this. Like my content not found exception. You can go ahead and do a search for that. And it's fairly, fairly trivial to do. So if you want to replace this later, you can. If we don't throw that exception, no, I'm going to use the repository. That save method and pass in that content. So we've already created the save method. So I just want to create a method called exists by D. And this is going to return a Boolean. So this is going to look. pretty similar to this, except we're not going to find first, right? We are going to say, we can go ahead and call count on this. And we can say, does that equal one? So if it does, it's going to return true. If it doesn't, it should return false. So let's go back here. That looks good. Sure. Let's go ahead and test this out. So I'm going to do something similar to this. And I'm going to say update existing content. So I'll pass in a one. We'll say that we are calling slash one. We'll just say my, let's just do this all caps, my first post. We'll do the same. This is how we know it'll be kind of updated. And then what I want is, oh yeah, that is the, and then what I'll do is I'll just create like an updated timestamp as well. I'll just pass this in here. This is all the same. And then maybe we have a URL now. We'll host 8080 slash some or my first blog post. Okay, so let's see. We are going to create a put. So we are sending a put request to Locos 80 -E80 slash API slash content and then the ID of the one we are trying to update. So we'll test this out first and then we'll test one with like 99 to see if it throws that 404. We are sending some JSON. Here's the payload. This is the request body. The ID is one title description. Yep. Okay. This looks good. Let's go ahead and try this. Let me just restart this. I don't think I did yet. And then I'll go ahead and make this. And I have a 200. So I think that is good. Let's go ahead and just list out all of our content. We should only have one. And there we go. So we have, oh, nope, we've created a second one. Oh, and I know why that is. Okay. So we've created a second one, but the right one that we're, you know, it actually created one, which is good. The update part worked in our controller, but in our save method here, we didn't write the logic to say, hey, if this particular post or content already exists in there, go ahead and just replace that one. If it doesn't, then go ahead. and add it. So we can go ahead and do that. So let's get the ID basically out of the content. If it, yeah, so let's say, oh, actually, it'll be there no matter what. All right. Yeah, so I probably would have created an update and a create, but to handle both, let's just go ahead and do something. So there is a, if we look at content list, there is a remove if that takes a predicate. And so So basically we could just say, hey, if that piece of contents ID is equal to content. Dot ID, then go ahead and, oops, content. That ID, then go ahead and remove it. So we're just removing it and then we're adding it back in. Again, this is kind of arbitrary because we aren't going to use this in -memory collection in a real world application. We're going to move to a repository that talks to a database. But I just want to. wanted to put this in place so we can understand how this works before we move on to the database stuff. So let's go ahead and try that now. I'm going to go ahead and restart the application. I'm going to go ahead and put. So we're going to call put. We get a 200. If we look at find all content, we see there's only one in there now and it's been updated to use the new information. So conversely, if we will go ahead and do this and we say update existing content with invalid ID. Let's just go ahead and do this at 99 and try to run that. And we do get a 404. All right. So we're getting there. Create, read, update. We just need a delete. Actually, I'm going to do one more thing here. We, I forgot about this. On the create, we use the response status. to say, hey, basically this is being created. I like the idea I'm going to put sending back no content. Like, yes, you got a 200, but I want to change that status to say, like, everything's okay. You just didn't get back anything because we're not sending back the newly updated one. We don't need to. You already have all that info. So I'm going to use the at response status and say HTTP status. content. So that will just give us back a different status code. And actually, I'm going to do the same for deleted. So let's do that. And then we are going to public void delete. So delete is just going to take in the idea of the piece of content that we want to delete. And then we will say repository delete by ID. Or we can just call it. delete for now. So we'll pass in the ID. Now we're going to get this from the path variable. And again, if you've been following along, you can kind of guess what this mapping is going to be. Yes, it is a delete mapping. And so again, we will pass in a dynamic ID, assign it to this argument, and then we will call delete on here. Now we do not have this delete method in here. So we will need to go ahead and delete it. So we'll just say our content list. That remove if. And again, we just did this up here. So this should look pretty similar to this. So c .d .0 .0 equals. And then we'll just say ID. Okay. So let's go ahead and restart application. And let's go back to our HTTP client. And all I'm going to do is copy this and we'll say this is a delete delete by ID and we'll give it an ID of two. Let's create that second one and then we'll go ahead and delete it. So we'll need one in there now. Let's create that second one. Where's our post? So let's create that. Now we should have two. So we have two in here. So now let's delete the second one. And remember, this should return no content. So, , did we?! 204? Good. Now if we go back to find all, we only have our one blog post in there. So this is great. Um, that is all of our crud operations. We kind of know. knock those out. And again, what I really love about this HTTP client is now this file in here is in the repository. This is something you could pull down with the final code. You can take a look at it. And you can run your test straight, right from the IDE instead of having to go out to a separate application. So I'm a big fan of this. I'm a big fan of what we've done here. Again, we're just kind of using an in -memory representation of all the pieces of content in here. We're going to move this over to a database soon. But before we do, I want to touch on just one or two other things here in the NBC world. All right. So I want to talk about something called cores, but to do so, I have to create a little bit of a front end, and that's okay. I've created a very simple one we can take a look at. I'm using Vite. VET is this really great kind of framework agnostic tool that I can create a bunch of different front ends in, whether it's vanilla JavaScript or Vue or Svelte or React, whatever you're using. you can use VET4. So check out ViteJS .dev. I've created something very simple. This is a vanilla JS project. All it has is an index .html. It points to a main .js. In main .j .js, I am fetching. I'm using the fetch API to say, go ahead and call local host 80 slash API slash content. That is that URL that's going to give me a list of all the pieces of content in the system. When you get that back, turn it into JSON. We know, we are returning JSON from our application and then just log that out to the council. Pretty simple. In here I can, I have a live server that I can use. It's an extension to basically run this application. Again, this is our front -on app. It opens up in the browser. It goes to 5500 and I don't see anything. If I look in the council, here is our problem. This is a problem you're going to run into if you're kind of building clients that talk to this rest API on the back So it says access to fetch at local host 80 slash API slash content from the origin. So origin is local, basically local host 550. So it's a different port. Has been blocked by Corps policy. The no access control allow origin header as president on the requested resource. So ultimately what this is saying is this is a feature of the browser that is helping us security saying you have two different apps trying to talk to each other on different ports or domains or both. I'm not going to allow you to do that. So what we can do is in our server side code, so in our spring boot application, we can set up cores to basically say, this is the, these are the resources that I'm going to allow to talk to this API. So how do we do that? So let's go back to IntelJ, we're going to do this at the controller level. So I have a video on this as well that goes in depth into this on how you can do this at the controller level and the method level and hey, what happens when spring security gets involved. So go ahead and check out my YouTube channel for that. If I haven't mentioned that already, there's a lot of really great resources there. YouTube .com slash at Dan Vega. So what I can do, though, is come over here and say cores. And so this is the cross origin annotation. And then you can start to define some different parameters in here. So let's look at the cross origin and we could say, okay, we can have different origins. So a list of all the origins for which cross origin requests are allowed. So this could be like a specific domain and port. So in our case, that's like local host 5505 .05, I think it was. You can get very specific on what headers are allowed. So possibly star to allow all headers. Methods. So maybe I only want to allow get requests to this. Maybe I don't want to allow anyone to do like posts or puts or deletes. And then you can have credentials and then a max age. To keep this very simple, I'm just going to add the cross origin. annotation here, which by defaults, so if you look up here, permitting cross origin requests on specific handler classes, , it says the default values are applied via course configuration. apply permit default values. Um, so let's go ahead and do that. So I'm going to do that. Restart our application, go back to the browser and visit my front end application. And now you can see that the blog post, that the blog post, the one blog post that we have in our system was now returned to the application. So that is now something that we could do, we could use in our application. We could turn that into, like, say, an array of pieces of content. And then just write a normal front end client to kind of iterate over those pieces of content and display them or display a single one. And this is, I do a lot of this in my blog. Actually, I do it via GraphQL, but that's neither here to note there. So just a simple front end example. talking to our API to bring up this idea of cores. If you're getting this error, that error that we saw in your council, that is a cores error. That is something that you need to handle on the spring boot side. Okay. One final thing that I want to talk about here in this spring MVC section is data validation. So we talked about building out our controller to kind of have our cred methods in here, right? Two of which are the ability to, , create a new resource, so create a new piece of content and update a new piece of content. But what we haven't talked about is the content that we are accepting from someone, so whoever's calling our API, this content needs to be in a particular format. If it's not, then our save method may not work. So at some point, we need to do some validation on the data that is coming in to us, right? We don't want to just blindly accept anything that. comes into us. So I'm going to go back to my palm, and this is our first kind of introduction to adding a new dependency that we haven't thought about. That's okay. As you start to build out your application, you're going to realize, oh, I need this particular dependency or that one. How can I go ahead and add it? So right here in IntelliJ, I'm going to go ahead and say dependency. And the dependency that we need is the spring boot starter. validation. So as we type validation, it'll now give us a list. We, of course, want that from org, springframework. boot. And then we don't need to provide the version, because again, this is a spring boot starter. All of that's kind of been figured out for us. After you add a dependency, you've got to go ahead and reload those changes here in Maven. If you didn't do that when you came over here into content and tried to use something from that validation dependency, it would not work. So what I want to do on this record now is start to define what is considered a valid piece of content. Okay, so the first thing is I don't want someone to be able to pass in an empty title. Like, why would you give me an empty title as a new piece of content? You must have a title if we want to move forward. So what we can do is use these validation constraints. So, this is coming from Jakarta. dot validation. dot constraints. And you'll see we have one called not empty. So if we look at not empty, we can basically see that this must not be null nor empty. So you can use not empty on say a string, a collection, a map, or an array if you wanted to. So this is really nice. So you can say not empty. You can also use blank. So hey, I'd, Not only do I want this to be empty, but I don't want this to be blank. It must have at least one non -white space character. So I like that. Now again, here are the constraints. If we go ahead and look at them. And if we dig down into constraints, we can see that there are a bunch of them. Hey, I want to make sure that this is an email or the date is in the future. Or there is a min or a max or a null or pass. or present. You know, there are a whole bunch of constraints that you can use kind of right out of the box if you want. So for me, not blank is good. I like that one. I may put that on description as well. I may put the date created or the date updated as, you know, future or present dates. Like I wouldn't create this in the past or update this in the past. So those are some other constraints that you can put on as well. You can also create customs constraints if you need to. There are a whole bunch of things you can do in the validation world. I just want to show you this tiny one just so you have an idea of what to do. So once you have that constraint in place, if we just did nothing else, that wouldn't work. What you need to do is when we have a create here, we need to mark this with the at valid annotation. So the at valid annotation now says, okay, we see that we're taking in this content via the request body, but hey, that content needs to be valid. If it's not, we won't even go into this section of trying to save this piece of content. It will automatically kick back and say, hey, this is a bad request. What you're sending me is not something that I want to work with. All right, so this is a really nice feature. So let's go back to our dot HTTP. Actually, I'm going to restart the application so those changes take effect. And in here, in my post, I'm going to go ahead and try to send a title with a blank title. And if we go ahead and submit this request, you'll see that we get a 400 bad request. So now our validation is work. You could start to stack validation. So if one particular class, like our content, had another class and say like a list of tags, for instance, that we were talking about earlier, you can go ahead and validate that on the content class to make sure that you don't get an empty list of tags. or that inside of that tag, you know, all those validation constraints are passing as well. So you can do a lot with validation. It is that extra dependency. So just don't forget that you need to add the Spring Boot starter validation to go ahead and bring in those constraints. At the heart of any application is the data that drives it. Traditionally, Java has made connecting to a data source, reading and persisting data, a little bit verbose and complex. While on the other hand, Spring Boot and Spring Data in particular, take this process and simplifies each step of it so you can focus on building your applications. Spring Boot integrates with a number of data technologies, both SQL and non -SQL. I want to start this discussion by taking a trip down memory lane. What I want to look at is an example application on how we used to use JDBC, that stands for Java database, connect, activity to connect to a database in Java and execute queries. So here we are in an example application. I don't have this up for you. Just kind of follow along and we'll talk through it. So in here, I have a Docker file to go ahead and use a Docker Compose to kick up a Postgres database. And it also has some volumes here so it will initiate some schema. So once it does this, now we can get into our job application. Our Java application is just a single public static void main, and we need to talk about how we can connect to a database. So first, we need a JDBC URL. This is a convention. This is a string that looks like, has some different parts to it, right? It starts with JDBC, colon, and then the database type, which in this case is Postgres, and then the URL that we're connecting to the port, and then the database name. So all of these things together comprise a JDBC URL. Then there are different ways that we can create a connection to our database, right? One of the easier ones is to use a driver manager to get the connection. So that driver manager takes in the JDB URL that we just talked about, the username and password for the database, and it will return a connection. And when you're doing this in Java, we're using a try with resources block here to basically say, if anything happens, go ahead and throw an exception and get out of here, right? So if we do have a connection, then we can come in here and we can check to make sure that that connection is valid. We can make sure that we connected to the database. So we say if the connection is valid or if it's not valid, go ahead and print this out and exit. Now that we have to be able to the database. a connection to a database, we need a way to select some data from the database. And we use this class called the prepared statement. If we look at prepared statement, this is an interface that extends statement. This has been around since Java 1 .1, since the beginning of time, time, time. And you could see if you look at this, you could see the different implementations of prepared statement. In Postgres we have this PG callable statement. and PG prepared statement. So once you have that prepared statement, you can pass in something, you can pass in some SQL. So I'm saying, hey, go ahead and select star from run. And then what happens is you need to use the prepared statement to execute a query and get back a result set. So again, the result set is an interface that's been around since the beginning of time, time, time. And as you can see, we have some implementations of this. So if you go down, we have things like in Postgres, we have a PG results set. And there are some other implementations of it. So once you have a result set, now you can say, all right, while there's a next value, while there's a next row, let's go ahead and extract some data out of that row, right? Out of that result set. So I'm going to, for each row, say, give me the next row. title, the way that you do that is you use the result set and whatever type you're working with, you say, okay, get me a string, get me an integer. These are pretty basic, but can get a little bit quirky when you start working with different types and e -nums and local date times, you know, the things that are kind of out of the norm of just like string and buoyant, buoyant, float, et cetera. Once you do that, I just print this out and everything works. So I'm not going to run this, but there are a lot of things that you need to think. of when you're working with databases. Now, this is just one particular connection in more of a traditional web application like the one we're working with, you wouldn't want to create a connection for every request that comes through. You can use something like a connection pool. We have these different pool of connections and as someone comes in and makes a request, we just kind of use that connection and then return it back to this pool. And so that type of connection is set up a little bit differently. What I'm trying to to get out here is, again, this is a little bit verbose. All we're doing is making a simple select statement here. You can imagine as we're starting to do a lot of crud operations from a database, this is going to get a lot more complex. So Spring Boot is going to simplify our lives when it comes to not only connecting to a database, figuring out these URLs and how to make that connection and how to get a connection pool and handle all of that for us behind the scenes. And then it's also going to help us with kind of giving us some abstractions on top of this stuff, where we're kind of doing this low level database work to get values in and out of the database. So that's what we're going to look at in this section. We're going to take a look at a couple things and talk about some different abstraction layers that spring gives us. And we'll go from there. And again, we're going to replace our in -memory representation of our collection of content. with something that is now stored in the database. So let's go ahead and do that. Okay, so the first thing I want to talk about is the Spring JDBC API. So Spring provides a starter that gives us database connectivity API that defines how a client may connect and query a database. To get started, we would head over to start .spring .io, and from the dependencies, you can select JDBC API. Now, it's important to understand that if you're you've heard the word spring data before. This is not spring data. We are going to cover that a little bit later. I'm giving you these abstraction layers and it's kind of be your choice to kind of choose which one fits into your application. So the JDBC API will define some things and kind of give us that spring's JDBC core functionality out of the box. We'll also need a database. One option is to use something called the H2 database. And this is a fast in -memory database that supports the JDBC API and R2DBC access. What's nice is it's very small, it's very fast, it has a built -in browser -based council application that you can kind of look at the contents of your database. I'm a big fan of it. So we wouldn't generate a new application here, but I'm just kind of showing you that if you're starting a new one, that's what you would do. We can also explore this. Oh, and we didn't choose maven let's choose maven we can also explore this and say okay what are the dependencies that I need. So I'm going to go ahead and grab this dependency and this dependency, copy those and head back to our application, our content calendar application. And here I'm going to just copy these dependencies in. So we have spring boot starter jdbc and our h2 database. So I'm going to go ahead and refresh maven to get all of those. dependencies back. All right. So I'm going to go over to source main resources and open up application properties. Remember, this is where we can start to kind of configure our application. I want to enable one thing. There is the H2 counsel. By default, it's disabled because we don't, we don't want to just expose this view into your database on all of your applications. You need to specifically enable this. So we're going to go ahead and enable us. All I've done was add one property here to enable a database council. With that, I'm going to go ahead and run my application and we're going to take a look at what's going on here. So there's a lot more logging happening. Our application has started on 8080. And now you can see down here, Hikari pool. So this is that connection pool we were talking about before. We've added a connection pool for Jdbc H2. That's the database type. So now that we know what this this J2 URL looks like. It's an H2 and it's in memory because you can use H2 as a file -based database as well. And then the name of the database is this weird long UID and the user is S -A. So it says it's completed starting up and oh, the H2 Council is available at slash H2 Council. And this is the particular database that you can check out there. So let's actually try this. Let's go back to the browser. Go to local host 80. Again, we're going to have our error page. But now if we go to slash H2 counsel, we get this little login screen that has some settings. So what are we logging into? This is the H2 database login. So if we paste in that JDBC URL that we saw before, the username is SA password is blank. We can test our connection and we can go ahead and connect to it. Here on the left is our database with our tables. Now, we don't have any tables because we haven't set this up yet. From here, you can run select, you know, you can run queries. So if I want to like select star from content, I could do that if I had something set up. What I want to point out here is that we have done nothing to connect to this database. You saw how much trouble that we had to go through in just a normal job application to connect to a Well, we don't have to do that. This goes back to some of the things we talked about when we started this crash course, which was, what does spring boot provide us? One of the things it does is auto configuration. It saw in our palm that we are using spring boot starter, Jdbc, and oh, we have an H2 database. So it put these two together. There's some configuration class, auto configuration class behind the scene that goes, well, if you have this JDBC stuff and you have this database, you probably want a data source connection created for you. Of course, if you need to somehow get at that and customize it, you can or override it, sure. But out of the box, we're just going to give you one. So you've done nothing and you have this connection to a database, which is great, because these are the trivial things that you as a developer don't want to really deal with. You want to work on the actual. requirements of your application, and this is what allows you to do that. So with the database in place, I am going to change a couple properties. We are generating this weird unique name, and that's okay for a test, but I don't want to do that every time. So I'm going to say generate unique name equals false, and I'm actually going to set a data source name. So I'm going to call this content. So now if I go ahead and restart this application. You can see that we are started on 8080, but now content is starting. So JDBC H2M, the database name is now content. So if I go over to my H2 counsel and reload this, instead of all of this, it's just going to be content. And if I test that, I can connect to it. Same thing. No actual tables yet because we haven't. gotten to that yet. Now, at this point, I know exactly what you're thinking. I've said it before. I hear it in the comments all the time. Dan, this is great, but this is an H2 database. This isn't a real database. I'm using quotations in the air. It must be way harder to connect to a real database. So I'm going to show you quickly that that is not the case. And then I'll kind of revert back to the H2 because it's great for prototyping and you don't have to rely on things like Docker. to stand up like this new Postgres database. You can just use H2 in the code that you bring down. So I like it for kind of portability and especially for these demos and tutorials that works out great. But what if I want to connect to a real database, Dan? So I'm going to use Docker here. Again, I don't want to go through the tutorial of how to set up Postgres on my local machine and connect to it and make sure everything works. I'm going to use Docker to basically spin up a Postgres container. So let's say 3 .8 and then we want to create a service. So services DB, we'll call this DB. This DB is going to have an image of Postgres, Postgres. Postgres is called Alpine. Yeah. So we're going to use like a lightweight version of Postgres. We'll set the ports. So we're going to map ports, which is going to be. 5, 4, 3, 2, 254, 3, 2. That looks good. Environment. Oops, environment. We will set Postgres username. And again, I'm just pulling this from the docs. So you can find those in there. Postgres password is password. And what are we complaining about here?! Sorry. Okay. So that's it. That's my Docker Compose file. If I go ahead and start this up and run this, let's see if it starts. It looks like it's done. Database is up and ready for connections. So in my application dot properties now, I'm going to comment this out. Oh, actually, we're going to need a database driver. So I'm going to comment out the H2 for now. So let's say that. We're going to need a Postgres database driver. Again, you can grab this. If you select it from start .spring .aO, this would come over the same, but this is what I'm going to use. So let's reload this and go back to our properties and just see how not hard this is to do. So I'm going to set a data source URL. So again, the URL is going to need to be that JDBC URL format. So I'm going to say Jdbc, Postgres, SQL. And this is going to be Local Host, 5 ,4, 3 ,2. And the name of the database, since we didn't supply one, is by default, going to be Postgres. So we're going to set a username. This was Postgres and a password of password. So let's go ahead and restart application. And that's all there is to it. You know, if we have, we're going to get in and, like, create some data. And once you have some data, then you can kind of validate that this is working correctly. But for now, just kind of take it out my word that we are connected to our Postgres database. And if we had some data in there, we can go ahead and select it. So again, you can use this going forward if you have something like Docker installed and you want to run a real database. For prototyping, though, this H2 database is really great. I really like it. So if you want to stick with me, go ahead and just use that for now and move to your quote -unquote real database later. So I'm going to go ahead and refresh this, stop the application. And now we can move on to how do we populate this database? Now that we have a connection to our database, we need a way to populate it. We need to populate it. We need to create some tap. We can insert some data. And there are a few ways that we can go about doing this. We could use a ddl script. So a schema file to go ahead and create our table structure and a SQL script to insert the various rows into our database. So that's number one. Number two, programmatically, we could use some Java code to insert some data into our database. And number three, a database migration tool. So I as we are creating databases and making changes to them and then adding or deleting rows, we can use something like a flyway, which is a database migration tool to make the changes to a database scriptable. So we can kind of commit those to get, if you will. So we're not going to look at the third one, but I will talk about the DDL script and programmatically as we start to move throughout this tutorial here. So let's talk about the. first one, which is that DDL script. Let me close all this up. Let's go back to source, main resources, and application dot properties. So we have our database stuff in there. Now what I want to do is talk about two other properties that we're not going to change, but I just want you to know that they are available. So if you go into spring .S .SQL, there's an init mode. So a nip mode by default, when we're using an H2 database, an embedded one, in memory one, is going to be set to always. This means that it's going to look for a specific file in a specific place to go ahead and execute so that we have this schema that can get created or rows that can get inserted. If you are not using H2, if you're using Postgres and wanted to stay on that, you would need to set this to always because if not, if it's not an embedded database, this is not going to act in this mode. So let me keep that up for a second. The other is spring .seql .net schema locations. So by default, we are going to look in source main resources for a file called schema. SQL. If you wanted to change that, you could. So we can come in here and set a bunch of different places where this could get populated from. So I just wanted to point those out. We're not actually going to set those because by default, We're using an embedded database and we're going to use the default location here. And this is going to be schema .seq. All right. So I'm going to pace in some SQL. I don't think we need to watch me type this out. This is basically the structure of the database. So we have an ID that's going to be an auto incrementing ID. We have a title, description, status, content type, date created, date updated, URL, the primary key is going to be the ID. So, That is our table structure. So all that we've done there is added that schema. SQL. We've added the structure for our table. If we go ahead and run our main application now, we don't see anything else here in the council. So we're not quite sure if anything really happened, right? We don't know did anything like take place. So for that, I'm going to go over to my application that properties once again. And I'm going to set logger. level for a specific logger. So I'm going to say org. That spring framework .jdbc. And we're going to set this to debug. So we haven't really talked about logging yet. I'm not sure how far we're going to go into this, but this property is just setting this specific logger to this specific log level. There are different levels of logging, and the default is not to output this debug info. So you have to have to. to be specific on what you want to output here. So we're just changing it for everything inside the JDBC package. So if we go ahead and run this again, I'm going to see a little bit more in here, and it's going to tell us some things that happened. So we see we have a JDBC connection, and we can see that it executed a SQL script from, we see that schema .seql, zero returned as the update. So I went ahead and created that table. and we see the executed SQL script from file and 5 milliseconds. So now if we go back to the browser and refresh our H2 console here, test and log in, now we see our table. So our table was created. There were no actual rows in here, so let's go ahead and do that. So back in our schema file, I'm going to do that. So back in our schema file, I can just do an insert. So I'm basically going to say insert into, and we are going to insert into, and we're going to have title, description, oops, sorry, content, title, description, title, description, status, content type, and date created, and then I'm not going to insert anything. into data updated or URL. So what we're going to insert into there is values. And this is is The content type is going to be article and then the date created is going to be current timestamp. So let's see if that works. Let's go ahead and refresh this. So restart our application. Look in our council. We did do an insert. So let's go back to this council. And connect. And now if we look at content. select all we see our row in here. So cool. So that is one way that we can go ahead and manipulate the data in the database that we are connected to. In this case, we need some schema to be run. So if it does not exist, I'm creating a new table called content. Again, the H2 is going to get wiped the in -memory database is going to get wiped out every time. So every time I start this application up, this is getting run, and then this is getting run. And then, yeah, it's not just for schema. We can go ahead and insert some rows here as well. Or we could just do this here and then programmatically we could insert some data if we wanted to. We're going to have to come back to the programmatic stuff though because we don't have a way to talk to the database. We've looked at how to connect to the database, but how can we use some code to insert, to read, to delete? How can we use some code? code, some Java code in our Spring application to manipulate the database. And that's what we'll take a look at now. All right. So when we're at start .Spring .i .O and we include this J2C API and this H2 database that we ultimately ended up putting into our application by copying those dependencies in, what we get are Springs JDBC template and named parameter J2C template. These classes are auto -configured for us. So they're automatically in that application context we talked about, which means we can ask for them as dependencies in our own beings. So what are the JDBC template and named parameter JDBC template? So if we look at here and we go down, we have a JDBC template here. So we have a JDBC template here. This is the central class in the JDBC core package. It simplifies as a use. of JDBC and helps you to avoid common errors. So this is our first level of abstraction on top of the APIs that we may be used to working with in, say, Java to get information in and out of the database, right? If you look through here, there are a ton of methods and a ton of overloaded methods, meaning they have different parameters but the same name. Because there are a ton of different parameters. things you may want to do with the JDBC template. But this is essentially one class that you can use to say query a database and get a list of things back. And so this makes it much easier to do all of the things that we need to do with the database. Now there is a difference. If you looked, there's a named parameter and I named parameter JDBC template. This is a This is the same thing, but when you're using dynamic parameters, using the JDBC template, you use these placeholders, these question marks as placed holders. As this says, instead of using question marks as placeholders, you get to use named parameters. So you could say instead of question mark, you could say like colon name and then provide a name later on. So you can use either. them. The API is identical. Again, it's just when it comes to dealing with parameters, whether you want to use a question mark or a named parameter. So that's what we're working with today. That's the first level of abstraction. Let's talk about that and create a new class in here. So in my repository, we have this content collection. We're going to replace this with a new Java class. And let's call this Content, Jdbc, repository. And actually, let's be specific, JDBC template repository. It's a long name, but again, we're not going to be using these. I'm just kind of using these as examples to show off kind of the different levels of abstraction. If you're going to go with the JDBC template, I would just call this content repository and be done with it. So what I wanted to talk about before is because we have those things on the class path, we're automatically getting that JDBC template. So we don't need to like figure out how to. construct one. It's already been created for us. We could say private final JDBC template, JDBC template. And now IntelliJ is going to say, oh, you want to construct your perimeter for this. So we now know after going through this ourselves that this is dependency injection. This template repository is dependent on the JDBC template to work. I need this. I can't do my job without this. So Spring is going to automatically auto -wire one in for us. So now we have a JDBC template that we can use to talk to the database. Okay. So now we need a bunch of methods to kind of deal with all the things that we would need to do for our crud operations of, you know, being able to get things from the database and persist them. I'm going to paste some things in here because I don't want to make this entire, we could talk to this code for probably 30 to 40 minutes and I don't want to make it about that. So I just want to talk about what you can do here. So we have this method called get all content. So I create a SQL string that says, hey, select star from that content table. From the JDBC template now, we can now use a method called query. And we could say, go ahead and query the SQL I just gave you. And then we're going to change this to content JDBC Reply. repository. Map row. And is that right? List of object, list of content. This is a list of content. So now we can just say, here's the query. This query method takes a string and then a, , let's look, a row mapper of type T. And the row mapper is really, and the row mapper is really, just how do I translate that particular row or rows that I'm going to get back for each row? How do I translate that into an object that you care about? In this case, a content object. So this row mapper will go through and do kind of the same thing that we saw on the Java side when we're getting that result set and saying getting string, here's the title description status, and we do all the things that we need to do with all of our properties. So this is going to be pretty much the same. you know, for creating, for updating, for deleting, for getting, this is, and this is, we've got to change this one to content, GdbC template repository. But again, if you like to write SQL and you want full control over the SQL that's being written, this is a great start. This is the abstraction on top of the built -in Java SQL stuff. So now what you can do. is if you wanted to use this, and I think we're still getting some errors in here. What is this one? Status string, content type string. Oh yeah, it's probably because those are enums, get timestamp. Okay, but I'll go through and fix this for the final source code. This is the JDBC template. So now what you want to do is if you wanted to use this, you can go on your controller. and say instead of using that in -memory repository, I would change this to something like private, final, content, JDBC template repository, and call this repository. Right? And now you just have to adjust these methods to kind of match what your JDBC template code looks like. Again, not going to do that here. We're going to focus in on the spring data stuff. I just wanted to show this as an option that, hey, when you pick that JDBC API, you get an instance of this JDBC template that you can work with. And now if you just want to start off by writing SQL and kind of controlling everything and not having some of the things go on behind the scenes that you don't have control over or that you don't understand, I guess is a better way to put it, this is a great start. Again, this is kind of level one abstraction. So I'll leave this code in here. I'll fix it up. But what I want to do is take a look at Spring Data. Okay, so the JDBC template was really nice. It's a nice abstraction, but there's still a lot of SQL that we got to write there. So we're going to talk about Spring Data. 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. Here we are on spring .io. If we head over to projects and we go to Spring Data, you will see that same thing that I just read to you right here under overview. And it lists out a lot of the powerful features. Things like a powerful repository and custom object mapping abstractions. We'll see that in action. You get some awesome dynamic query derivation from repository method names. Being able to have the. the implementation for the domain -based classes, providing basic properties, things like auditing, custom repository code, and more. So again, we get some out -of -the -box SQL and no -SQL support. So if you're using MySQL, Postgres, Oracle, SQL, SQL server, et cetera, you're good. If you're using Redis or MongoDB or Patchy Casandra, those will work as well. So Spring Data is broken down into different modules. So we have these main modules, like the commons, this is kind of core to every underlying spring data module. There are things like Spring Data, JDBC, and Spring Data JPA, which are two of my favorite, which will talk about one of these today. There are things for working with like MongoDB and Reddest or Spring Data Rest. And then there are a whole bunch of ones provided from the community. So if you're working with, say, Couchbase or Azure CosmosDB, or, or YugabyteDB. So all of these are community modules that are really great as well. So then you really have to ask yourself, what type of data store are you working with? What are you trying to do? And then kind of go from there. So I think by far the most popular one is Spring Data JPA. JPA is the Java persistence API. And underneath the hood, by default, we're using hibernate in this. So this is an ORM. or an object relational mapper. And this is really great if you have worked with ORMs before. If you knew ORMs, there's a little bit of an overhead here. You got to kind of learn how to map entities to each other, how hibernate works underneath the hood, because that's important when you're trying to debug those types of issues. So JPA is great, but there's a little bit of overhead. Another one I really love is Spring Data at GDBC. You get a lot of the benefits of using SPP. spring data without the overhead of, say, an ORM. So I'm a big fan of that. So I think we're going to use this today, but just know that JPAs are really big and popular one out there. So go ahead and check that out if you want. If you're over at Spring Initializer and you go to Added Dependencies, we already saw the JDBC API. But if you type Spring Data, you'll see all the different Spring Data modules that are available. So things like Spring Data JPA, R2DBC, if you're working with React, React, of relational databases. And then my favorite spring data, JDBC. So we're going to go ahead and choose that. And then you're going to pick a database, which is H2. Again, we're not going to generate a project here. I'm just going to go ahead and look at Explore. And we're in Grado again. And if we dive into here, we can see that the only dependency we need here is this spring boot starter data JDBC. So I'm going to head back to my Intelli, I'm going to open up my palm .xml. I'm going to keep my H2 database. I'm going to get rid of this and now just add this new one and refresh my Maven Palm. And now I should get everything that I need. So I talked about Spring Data JDBC being my favorite one. Well, why is that? What is it? So if we dive into that, you can learn more about the kind of overview of this project. if you want. You can go into the Learn documentation to check out the reference docs or the API docs, the reference docs, do a really good job of kind of giving you an overview of the things we're going to go through here today. Also, like a couple of the things we talked about, I could probably spend an hour or two just on this alone. So I'm not going to. I'm going to. I'm going to try and keep this concise. I do have another video on getting started with just Spring Data, JDBC, and a little bit more in depth into some of the things we're going to talk about today. So Spring Data JDBC aims at being conceptually easy. In order to achieve this, it doesn't do a lot of the things that's something like JPA does, like caching, lazy loading, right behind, or many other features that you get with JPA. This makes Spring Data JDBC simple, limited, and opinionated. All right? And it all starts with this idea of an aggregate root. So I'm not going to go into this. Again, watch the other video, go through the docs, learn a little bit more about that, and we should be okay. So back in our application, I want to take a look at our model because it kind of all starts with the model, this idea of domain -driven design. Before we jump in here, I want to talk about a couple terms too. You'll hear different terms like DTO, entity, and POGO, and what are these? And I want to give a very very terms. a big shout out to Greg Turnquist, who I think described these very well in his new book Learning Spring Boot 3. So if you haven't had a chance to check that out, go check that out. I'll leave a link in the description for that as well. A DTO is really a class whose purpose it is to transfer data, usually from the server to the client or vice versa. An entity, on the other hand, is a class whose purpose is to store and retrieve data from a data store. A pojo is a class that doesn't extend any of the framework code and doesn't have any restrictions baked into it. So if we're looking at this content record here, this whole purpose of this content record now is going to be to store and retrieve data from our database. So this is an entity. And as such, there are some things we kind of need to tell this record about. We need to like say, hey, this is an entity. These are some things you may want to know about. what is it what's the difference between an entity and a DTO? Well, in the case of this particular thing, not a whole lot because the same properties that we're working with here in the entity are something that we would kind of deal with on the client server handshake, right? Like when I create a new piece of content, I want all of these things. If I wanted to create a DTO that just accepted a title and then if I, if It was, you know, blank content was the type of DTO that it was. You know, I could maybe make the assumption that I could fill in the rest of the data for that request. So I'd create a new DTO based on this to kind of a subset of the data that I'm worried about. I hope that makes sense. If it doesn't, please let me know in the comments below, and I'll be sure to go ahead and answer that for you. So this is an entity. We need to tell Spring Data. at JDBC that this ID right here is an ID that we are going to be working with. And the way that we do that and we say at ID, this comes from springfirmert data. Datatation .ID. And if we look at the sources, not much here. This is an identifier, right? So that's all we need to do there. Now, we could do some other things. We could come up here. mark this with at table and we could say that we wanted to specify the table name. So we could say that the value is my, what if we had like a prefix called TBL and the table name was content, right? We could do that if we wanted to. I'm not going to. You can also come in here and say this is a column and inside of column. And inside of column. you could say that the particular column is called STR title. I don't know. Whatever you want to customize this column to be, right? So that is the at column annotation. Those are really the only three I'm working with here right now in this particular project. But right now, all I need is this ID saying this is something you're going to manage. And I want you to go ahead and manage. that manages for me. And this is the identifier of this. So with that in place, we can create some repositories now. We've created these repositories before, but we've also like these, these were very, these were classes that we had to implement. We had to make all of the code to create a collection of content and add to them and save and update and delete and list. find one. We had to do that for all of those. In this case, we're not going to have to do that anymore thanks to spring data. So what I'm going to do is come in here. I'm going to create a new Java class. I'm going to call this one just content repository. But in this case, it's going to be an interface. Say, what, an interface? How are we going to get some code out of that? Well, the way that we're going to do that is we're going to extend one of the spring data repositories. So there are a few. There is, one called a repository. And if we look at repository, there's actually nothing in here. So this just says, hey, this is a repository. Then we could go ahead and add our own methods in here. There is one called a crud repository. This gives us a lot of the crud functionality out of the box. In the latest version of Spring Data 2022, there's also a list credit repository. And this is the one we're going to use. Once you have a list credit repository, you need to give it a type. What type am I managing? This is content. What is this type's ID? That is an integer. Right? So once you have this in place, that's it. That's all the code you need to write. If we look at this list, cred repository, it has methods for returning lists because the credit repository returns iterables. And we're not used to working with intervals. I want to work with the list. So when I call find all, give me a list of content, right? But the CRUD repository contains the rest of the operations for doing things like saving, deleting, delete by ID, find by ID, etc. So just by extending this, what happens is we don't, and also we don't add the at repository marker here because this is an interface. And what happens is at runtime, Spring will see that you've extended one of the base repositories and basically turn. this into an implementation. So now you have an actual concrete class that you're working with called content repository that has all of these methods in it. Right? So how can we use this? So let's go back to our content controller. And instead of this content collection repository, let's replace this with just the content repository. And we'll keep this called repository. Now we're going to have to change this up a little. Let's say content repository. And then that looks good. This looks okay. This looks okay. This probably is going to work. And the only change we may have here is delete by ID. Okay. So now I did this because I specifically wanted my collection repository to look similar to this. So that we can just flip over. But again, we have not written any methods in this content repository. So when you start, you could just say, hey, repository, find all. That's going to get all of the methods, right? So this is pretty fairly simple to go through and get your crud operations up running. Now let's see if this actually works. Let's restart our application. And I'm going to go over to now we don't have any, we're not going to have any, we're not going to have any, we're not going to have any content in there because, remember when we added one, we were doing this here in this content collection repository. So let's back up a second. Let's go to our application. I want to talk about programmatically inserting data. Oh, no, we should actually have one, right? We do this schema. It does have one. Let's scratch that and go over to our HTTP test and see if we can list out content. And we do. So that is in the database. That's what we're born from the database. And most of our content controller should work. I do want to talk about programmatically inserting data now, though. Let's go ahead and take this out. Actually, I'll leave it. in, but just comment out in case you want to use it. But now if we were to rerun this, we'd have no rows in the database. So how can we do that? Well, we can come in here into our main application class or really any configuration class. Let's talk about this. Let's do it the long way so it makes sense and then we'll do it the shorthand way. So I'm going to create a new, and actually this really isn't a config, but that's okay. Let's create a new Java class and we'll call this a data loader, right? So there is a interface in spring called the command line runner. And if we look at the command line runner, this is an interface used to indicate that a bean should be run when it's contained within a spring application. You can have multiple command line runners. The important part to note is that this will run after dependency injection happens as the application has started up. So this is a really good spot to do some type of, you know, bootstrapping or data loading. So there's a single method in there, so we're going to implement that. And if you're paying attention, there's a single abstract method. Also, this is marked with that functional interface. So we'll talk about that in a second. But I could create a class and hello and wave. So that's all I'm going to do here. I'm going to run my application, rerun my application, and actually this isn't going to work yet. So this isn't going to work because we haven't marked this with at controller. So spring doesn't know that this is a class that it should care about. Once you mark it with that controller, now it's going to pick this up and then run the run method. And there we go. We see our hello output it after everything is kind of warmed up, started, and ready to go. So this is one way to do it. Again, I'll leave this in here. I'll just kind of take that off so it won't get run. Another way to do it is it's a functional interface. So it is a target for a Lambda. So what we could do, remember if you want to create something, so instead of using at component on a class. If you want to create an instance of a class using a method, you can mark it with at bean. So I'm going to mark this as at bean. It's going to return a command line runner. The name of this method is called command line runner. And this is going to return a lambda expression. Now this particular run method takes a vargs of strings called args. So I can say return and here's our lambda expression or in this case I don't even need that if I just wanted to say hello Dan right so let's go ahead and run that and there's hello Dan. And there's hello Dan. So this is a great place to do some bootstrapping is what I am trying to get to. So we can go ahead and insert some data into the database. Now, what we need to insert some data into the database is our repository. We need this content repository because this has all the methods to be able to do things like save a new piece of content. So how can we get this here in our command line runner? Well, this is just an argument, right? So we can say content repository. We'll call this repository. We'll call this repository and because spring is managing this as a kind of instance in the application context, it will see that when we create an instance of this thing, this is dependent on this and it will wire this in for us. So now what we can do is let's go grab this code so we don't have to kind of replicate that. We can say content is equal to that. Let's just write something else so we know it's something different. I wrote a new thing on chat GPT earlier. Let's say all about chat GPT. And maybe this was a video. So now what we can do is we can use that repository and we can save that entity, that content, and we can save it to the database. So the only difference here is that we are not going to supply the ID. So we are not supplying that ID. This is actually going to be null, right? So with that, let's go ahead and try and rerun our application. And there we go. So if we run back to this and say lists all, of our content, we can see that we get that new piece of content. So now we have the ability to programmatically insert data using one of the really nice interfaces that Spring provides us with the command line runner. So again, just a really nice way to kind of programmatically insert some data. All right, so there's one more thing I want to show you when it comes to data and then we'll kind of move on from this section. But what we've looked at. looked at so far with the content repository is we get all these really great methods out of the box. We get these list methods. We get all these crud methods. You can see in here. We got a whole bunch of stuff out of the box, which is great. I don't like writing boilerplate, dumb, boring, crud sequel. So awesome. Don't have to do that anymore. But what if we have something that we need specific? So let's say that we had a request from the client. Hey, I want you to write a method that will return to me all of the pieces of content that contain some keyword in their title. So find by title, right? And it's going to take in a keyword. So how are we going to do this? So first off, this is going to be a Git mapping, right? So we're going to respond to a Git request. So it's going to be at at Slip. slash API slash content slash maybe filter and then whatever the keyword is. So that's the keyword. We're going to accept that as the path variable. So how can we add something to the repository that will satisfy this requirement? So if we go back to the content repository, any methods that we add in here, we can go ahead. Well, let's back up. There are kind of two ways that we can add some store specific queries. We can do it from the query name. So we can do it by query derivation, which is off the method name itself, or by using a manually defined query. So let's talk about query derivation first. Let's say that I wanted to get a list of content. So what I want to do is I want to get all of the content by some column, by some kind of criteria, right? I'm going to start typing here. And as I start typing, you can see that I get find all by, find first by, find content by, find by, find distinct by, all of these really great query derivation helpers. So what we're going to do is we're going to type out a query name here. And then when this thing gets. implemented at runtime, it will turn what you're looking for into an actual query that will get sent to the database and we can get what we need back. I want to find all by title. And now we can start to like figure out what do we want to do with that title. We could say like the title is this or contains that or starts with. I want to say where find all where the title. the title contains, and then you can start to chain this. So if I wanted to find all by title contains and date created was, it happened this year, and the status was not an idea, maybe it was published, right? You can start to chain all of these finders together. I'm going to keep this simple and just say, find all by title that contains whatever this keyword is. So again, this is not. an actual implementation. This is just an abstract method here. We're defining the signature. It will get turned into the bits that needs to be turned into for us to actually work at runtime. So let's go ahead and go back to our content controller and say return repository. Findall by Title contains and then our keyword. So let's see if that works. Let's go to run our application and let's go to the browser and if we go to content and just list out all the content we have one in here we have a keyword of gpt so let's say filter by keyword let's say gpt and you can see that's found now let's find one by one that is not found so like data and as you can see we get an empty collection so this is a really great way to quickly add some new queries to your repository. Now this is one way. Okay, so I want to get a list of content and I will say that I want to list by status. And so we'll take in an argument of status and we'll just call this status. And instead of doing the query derivation and having that implemented for us, I'm going to use the at query annotation. Because I'm on Java 17, I can now use this nice triple code. text blocks and I'm going to say select select star from content where and then if we go back to our schema I just want to remember this where status so come back to that in a second where status is equal to And then we need a way to say the status that is being passed in. So we can use a name parameter here and we say where status is equal to status. And then we go ahead and use the app param annotation to bind to that. So now we're actually writing out our own query, right? So let's go back to the content controller and let's write a new method. We'll call this a get mapping. We'll say filter by status and then the status. and then we will get a list of content pack. We'll say find by status. And then we'll use a path variable to pull out that status. Right. And then what I want to do is use the repository to list by status and and pass in the status. Okay, so we're passing that. Let's go ahead and run this and see if that works. So again, I have just that works. So I'm going to say a status of idea. So I'm going to say filter by status and then idea and we see that we get that. Um, another status is in our completed and we see that we don't get any. So just a couple of different ways you can start to write your own custom queries here in a repository. You can use query derivation. There's a whole lot to learn about query derivation and the different ways that you can construct these queries. So check out the documentation. for that. And then you can use the query annotation and you can write your own queries here if you want a little bit more control over the SQL that's getting sent to the database. All right. You've learned a lot so far. I know this is a little bit overwhelming. There's a lot to learn here, but you've learned a lot. And I'm very proud of you. I'm glad you're sticking with me through this. But the ultimate goal is not to have an application that we can run on our local laptop, right? We want to get this out to the great world of production. We want to to be able to show our moms and friends and say, hey, look at this thing that I built, even though it's just returning JSON. So what we're going to do in this section is get prepared for the promised land of production, and we're going to do that by covering a few more fundamental concepts. So what are we waiting for? Let's do it. Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources, including Java properties files, YAML files, environment, variables and command line arguments. So we'll look at a list of all of the property sources here in a second, but I just want to talk through this. So we've already kind of seen this in action. If you open up source main resources and application dot properties, you see that we've got to configure some things in here already, right? Like we configured the H2 council, the data source name, and the logging level. So this is where we can configure all of the properties in our application. These are all the things that are built into whatever components we're kind of using in our application. So for web example, there's a bunch of configuration that you can do to configure how the web application acts. Remember, this is, you know, Spring is configuring some sensible defaults for you, but always giving you the ability to override those defaults if you need to. So one of those that we've already seen is the port, the default port that's that Spring Boot starts on. And that is a setting. So if you go in here to server. .port, you can see that its default is 8080. We can always change that. So if we want to change it to 8085, let's do that. Let's rerun our application. And if we look in the council down here, we'll see that now we have started on port 8085. So now what I want to do is go over to the browser. And if you look in the spring boot docs, there's a section for externalized configuration. And this is kind of the stuff that we just went through. We're going to get into this. Properties can, property values can be injected directly into your classes by using the at value annotation. So we'll talk about that. Or we can use structured objects using the at configuration properties annotation, which we'll talk to as well. But this is what I want you to pay attention to here. Spring Boot uses a very particular property source order that is designed to allow sensible overriding of values. Later properties in this list can override the the values defined in earlier ones. So this is something I never remember. I always come back to the docs because there's so many different types of property sources. One can override the other. And so if you ever have a question, always come back to the documents and take a look. But what this is saying is anything later will override the one that is earlier. So if we had a config data such as application. Dot properties files, and then we go ahead and set an operating system environment variable, that is going to override our application. Properties. And this becomes very important when you want to move to different environments. So I may not want to, you know, expose a secret key in a production environment. That's where I can expose a secret key as maybe an environment variable in my production environment. So there are a bunch of different ways. Again, the application not properties, whether it's dot properties or dot yamil, those are used in a specific order. And then we also have variants of that. We'll talk about this in a minute when we talk about profiles, but you can have different property files for different profiles. So we'll talk about that. So just understand that there's a pecking order to this, right? So here's our properties file. We've set 8085. So what I'm going to do is just doing a little experiment here and go into, my run and go to edit configurations. So we're going to go to edit configurations. And in my application, I am going to set a environment variable. So let's say environment variable here. And I'm going to set server. That port equal to 8081. So this is different than the default 8080. This is different than the 8085 that is in our properties file. So if we go ahead and run this now, we can see that we are started on 8081. Because, again, that property source overrides the dot properties file, and therefore, that takes precedent. So that's just a little bit on configuration and different property sources. These, again, are important to note as you're moving through environments. So I'm going to go ahead and remove this, and we're going to talk about injecting values. using your code using add value and configuration property. All right. So to demonstrate this, I'm going to create a new controller. We're going to call this our home controller. So let's say home controller. This is a class. We're going to mark this as a rest controller. And we're going to have a single method in here that is going to return a string for now. We'll call this home. We'll return hello world. And actually, let's just return hello hand wave because any chance we get to use an emoji in some code. Let's take it. So this is going to be a get mapping for that. So our root endpoint, that should call this. And if we go ahead and rerun our application and head back to the browser. And we get local host 8080 and we get our nice hello hand wave emoji. So so far, so good. Now what if we wanted to get a value from the application dot properties? into this controller. Um, well, first off, we might set up a variable here. We can call this string. We can call this welcome message. And then we might want to return that here instead of this hard -coded hello message. So we'll say welcome message and great. If we do this, we have a null value right now. So we're not going to display anything. So what we can do is we can use the at value annotation to say, let's go ahead and grab something from, that application dot properties or really any configuration source, right? Now that we understand kind of property sources and how they're overwritten. So we're going to use something called spell, spring expression language to get that value. So we're going to, we can name this value, whatever we want. So I'm going to start this with CC for content calendar. And we're going to say welcome message. Now we have not defined this yet. So what do you think is going to happen if we try to run this application. You're right, it's going to blow up. Could not resolve placeholder CC welcome message. So we could go to find that, but we also want to be able to handle this case where maybe somebody didn't define this in their app. So we can actually set a default value here. So I'm going to say default welcome message. And now if we go ahead and restart this, it doesn't blow up. And if you went over here and refresh this, we get our default welcome message. So so far, so good. Now, what if I do want to define this? If I go back to application. Properties and I say cc. whoops, welcome message is equal to, hello, what are we, let's say, welcome to Dan's content calendar. Okay, so let's go ahead and use that. and refresh and there is our new message. So so far, so good. But what happens if we wanted to add some more data that we wanted to display? So let's come back here and what if we had a an about? Like what is this, what is this application all about or what is this API all about? So maybe we had a string about. We could do something similar here. We could say, , c dot about and then we can pull that in. Now how do we display two things here? Well, at this point, we're not displaying a string anymore. Maybe we want to display some JSON data. So what I could say is I'm going to display a map of string of string. Okay, that's what I'm going to return. So how do I do that? I'm going to return map. Dot of and I'll say my first key is welcome message. And that's welcome message. And that's welcome message. and then my second key is about and that is about. So that looks good. We need an about in here. So let's go ahead and do this. Okay, so let's go ahead and refresh. Now, if I go back over here, now I'm getting my JSON, my welcome message, and my welcome message, my about. Okay, so this works, but there's a couple problems with this. One, we, you notice that when we start typing this here, we don't really get any assistance. CC dot, why can't I see what those properties are? I want, I want to be able to help whatever user is using my feature here and to be able to get some intelligence here. Two, if we come back to this, we can kind of plug whatever we want in here. So a welcome message, I'm going to say 99. And what is this about? I'm going to say that this is a list of things, right? And it doesn't really care. So it's going to go ahead and run this and it's going to go ahead and refresh and, okay, we have those things. It didn't really do any kind of type checking, right? Like these are strings. I would want the user to input some strings. So how can we get around this? So let's go ahead and delete this. Let's go in here and and delete this. Let's say string for now. And I'm going to remove these. So anytime you have a single value, this is great. But when I start having a collection of values that are kind of related to each other and you maybe want some types around it, this is a really good opportunity to use configuration properties. So I'm going to go into config here. I'm going to create a new Java class. And I'm going to call this content calendar properties. And this is just going to be a, actually this is not going to be a class. We should probably make this a record just to simplify things. Let's say record. And then the components of this record are simply going to be that welcome message string and the about. So all we're going to do to turn this into some kind of properties that we can use is we're going to mark this with at configuration properties. And we're going to give it a prefix. So what is the prefix that someone types in for each of these? So cc .welcome message, cc .combeau This is going to pop up in IntelliJ right away saying, hey, this spring boot configuration annotation processor is not configured. What are you talking about? So if you look at the documentation, it'll tell you, hey, generating your own metadata used by the annotation processor, all you need to do is include this dependency, whether you're using maybe, or Gradle. So to do that, I'm going to come back to my palm .xml. I'm going to include that dependency, reload Maven, and then this should be okay. But we have one more thing that we need to worry about here. And that is in our application, we need to say, we need to enable that. So we need to say, actually I'll put it up here, we just need to say enable configuration properties. Which one, which classes do you want to enable that for? Why only have one? I'm going to point to it, content, calendar properties, that class. Okay, so at this point, we should be getting no more errors. Everything looks good. Now, once you do this, you got to run a build. So I'm going to run a build. Let's go ahead and build our project, and we're going to get this target folder. And if we look under classes and under meta -imph, we now see the spring configuration metadata. And as you'll see in here, we have some metadata for the CC. So we have some metadata. have. This is the kind of type where it's coming from. These are the two properties, the welcome message and the about. So once this files in place, now I know if I go into my application dot properties and I type CC, I'm going to get some more help about this. So you could see that this is a string. This is a string. So now if I go ahead and type, and now I can say this is Dan's content, or actually we said, welcome. Welcome to Dan's content calendar. And then we say cc. About. This is a collection of my content. Okay. So now we have that in place. Now we can come back over to the home controller. And this is just a bean, right? Now the spring application context is managing for this. So, as you can guess, we are going to say private final content calendar properties. We'll call this properties. And Intel J is going to say, hey, you probably want to construct our parameter for that. I do, I do. We can change the type of this because, in fact, at home, we just want to kind of send this info back. So we can say that this is a configuration properties. And let's go ahead and return properties. Right. All right. So now, if we go ahead and restart application. Okay, everything's working still. Let's go back to Local Host 8080. And there we go.! We have our welcome message and our about. But now we have them nicely packaged in this content calendar properties record. And again, if we think of other things that we think of other things that we're going to be. We want to add to this later. We can just add that here and everything is going to be set up for us. So that's a little bit about injecting values into your beans using both at value annotation and the configuration properties. All right. So we've talked about configuration. I want to move on to profiles. Spring profiles provide a way to segregate parts of your application configuration and make it available only in certain environments. This is going to be really important again as we're moving to different environments. like production. So any component configuration or configuration properties can be marked with app profile to limit when it's loaded. So let's take a look at an example of this. And to do so, I want to first start our application and talk about something we may have seen in our council, but haven't really understood what it is. So here we get this nice askie art. This first line up here says we are using Java 17. The second line says no act. profile set falling back to one default profile default. So by default, if you don't set an active profile, the active profile is something called default. If you want to set an active profile, you can come in here and say spring dot profiles. And if you saw it real quick in the hint there, you can provide a single active profile or a list of them. So I can either say devs, or local or maybe this is local and dev. We're just going to start with say dev. So now if we restart this, that is the active profile. If we look up here, we can see that our active profile is now dev. So we have this app profile annotation. Let's look at an example of where we might use this. So I have this data loader class. And again, we made a mistake on this earlier. We used that controller. We should have used ad component. I just got excited. So we have that component here. And if we run this, it will go ahead and run because we are telling it to run. And there's our hello output. But what if we only wanted this to run in, I don't know, say production, right? Let's say we did not want this to run in dev. What we could do is add an app profile. And we could say what profile we want this to run in. We could do, we could say, hey, I want this to run. in production. Or I don't want this to run in dev. So you could do like matches or negative matches or against the list. You can do a whole bunch of things when you're kind of trying to figure out what profile this should be used for. So here I'm saying don't run this in dev. So now if I run this again, we should not see this in the council and we don't. So that's cool. That allows us to kind of limit where this profile is being shown. So that's one example. I'm going to remove that. And let's take this off so this doesn't get run anymore. So we're still using profile as dev. The next thing I want to look at is profile -specific configuration. So we have this application dot properties, and this is going to be loaded no matter what environment we are in. But what if we had environment or what if we had different settings based on the environment we're in? This is very possible. This is something that we're in. happen a lot, right? So I'm going to create a new file here and I'm going to say application dash and now you can use whatever profile you are going to be in. So let's say we had a profile called production. So I'm going to say application dash production dot properties. Now these will always get loaded into whatever environment you're in, but then the profile specific properties will only get loaded when you are in. that particular profile. So let's take these two properties that we just looked at before and set these in the production. And let's just say this is production. And we'll say production about message. All right. So now we're still in dev. If we go ahead and run this, we should be able to go to go to local. state 80 and see our original ones. So let's refresh and there we go. But now let's go ahead and change this active profile. And again, we could do this here if we wanted to. Spring. Dot profiles .active or let's override that in an environment variable because we know how these things work now. So spring. Dot profiles. .active is going to be equal to production. So let's hit apply. Okay. Rerun this. And if we go back over here, we refresh this, we see that we are now picking up properties from our production configuration. So this is really cool. I like the slot. Profiles allow us to do some really cool things. One of which I could see an example of, you know, that I've done before, is we have this data source for, for our our local development, right? Maybe when we go to production, we are going to use that Postgres, that real database, right? So we could come into our application, not production properties and define our Postgres JDBC connection in here. And so that only get loaded when we go to production. And in fact, that is what we are going to do today as we move to production. I'm not going to do that yet because we're going to have to set that production database up in that production environment, get those properties, and then we'll come back to here and load this. So that is a little bit about properties. I also just want to point out that we've talked a lot about dot properties files. They are interchangeable with something called YAML files. So you can go ahead and create YAML files in here as well. So let's say application. YAML. And some people like YAML better, because if you have like lots of different so so like spring datasource that name dot username that password right this can be a little bit more verbose in a properties file in a yamel file you can see we can start we can type spring dot data source dot username and this could be dan and now we can say password Oops, password. And this could be password. And then we can do driver, class name, whatever. So you could see that we get a little bit cleaner. We have some kind of cleaner structure to our properties and a little bit less verbose because we're not repeating spring. Datasource every single time. So you could use YAML, you could use properties. If you use them both, they'll actually get merged. and there is an order to like which one wins. But I just wanted to point that out in case you do see YAMO files. They are kind of the same thing as Top Properties files when we're talking about creating our, configuring our application. All right. So we're getting ready to push our application into production. I want to talk a little bit more about production ready features. So Spring Boot includes a number of additional features to help you monitor and manager your application when you push it to production. It's not just a number. to push your application into production, cross your fingers, and hope everything's working. You don't want to rely on your users telling you something's wrong. You need to be able to monitor this and see what's going on. So you can choose to manage it and monitor your application using HTTP endpoints or with JMX if you want. You get auditing health and metrics gathering that can also be automatically applied in your application. So what we want to first do is enable these production ready features by using the spring boot actuators. So like with a lot of things in Spring Boot, there is a Spring Boot starter actuator that we want to go ahead and add to our application. So if we go ahead and do this, I'm going to copy this dependency. I'm going to go back to my palm. And in here, I'm going to add this dependency. And let's tell Maven to reload. And we should be okay. So now when I go back to my application and start, everything looks like it's working okay. All right. So the first production feature, really the one that we're going to talk about today is endpoints. So actuator endpoints let you monitor and interact with your application. Spring Boot includes a number of built -in endpoints. And you can always define your own. For example, the health endpoint provides basic health application information. Here's the important part. You can enable or disable each individual endpoint or you can, expose, you know, a whole bunch of them or all of them over HTTP or JMX. The way that you get to them, most application choose to expose over HTTP, where the ID of the endpoint starts with slash actuator and then the name of the endpoint. And here's a list of all the different endpoints that you get out of the box and a description of what it gets. So we know what beans are, right? There's actually an endpoint that displays a complete list of the spring beans in your application. So this is really nice to be able to see what is happening in your live application as it's being used in production. What are all the beans that are available there? So let's go ahead and take a look at making these available. So we can enable one, we can enable all of them. I'm going to enable all of them. I'm going to say management. endpoints. That web. Exposure. Exposure. dot include and I want to include star. I want to include all of them. I also want to set one other property. I'm going to say management. Dot endpoint. So end point. Endpoint. Dot health. That show details. I'm just going to turn this on to always. So I want to go ahead and restart this application. And let's go back to. the browser. I'm going to go to local host 80 and actuator. And now you can see I get a whole bunch of endpoints in here. So we can see that we are basically given all the endpoints. So like beans, caches, health. And if we go ahead and dive into here, we can see beans. These are all the beans in the application context. So we know that we created that content, , was it content, calendar properties. So if we search for that, we should see that. Here it is. There's no alaces. The scope is singleton. Here's the type. Here's the dependencies. So pretty cool stuff. You can kind of see all of the different beans that are in your application. Another one that I really like is the config props. So I can go into config props and see where everything is. more importantly where it's coming from. So here's an example of that properties, that about, and that welcome message. And we could see where it's coming from. So if we look at the input, it's coming from application. Properties. So if we had a bunch of different property sources and we weren't quite sure which one was overriding the other one, hey, this is going to tell us exactly where that particular configuration is coming from. So I really like that as well. We can go into the health and we get some details about this, we can see that the status is up. Here's the components. Hey, we do have a DB. In this case, it's an H2. That is up and ready to go. What is our disk space? And we can even configure this to show a little bit more information. Say in the info, we can get some JBM info, the operating system info, et cetera. There's an environment that shows us all the environments that is happening. We can get a list of loggers. And these loggers are all the loggers that are currently configured in our application. And you can even make post request to this if it's enabled to change the logging level. So if I wanted to change a logging level at runtime and I had the actuator enabled, I can do that. Metrics are very important as we start to try to figure out what is going on in our system. So if I want to see, let's see from a JVM standpoint, let's just figure out what is the max memory of our JVM. So I can say, I can grab this key and then say from metrics, what is this, and here's some information about that particular metrics. So just with the actuator on, we are now collecting a bunch of metrics in our application. Let's take a look at some mappings. So we have some mappings in our application. These are all the mappings that are set up for our application. So again, just the, just wanted to show the actuator. It's important. You get a lot of information out of it. And this is the start. You need to include this to do some other things. So there's a big theme in Spring Boot 3 around observability. So if we include this, we can now do some things with metrics. So observability really is kind of the idea of logging metrics and distributed tracing. just by including that actuator in Spring Boot 3 and setting a couple properties, we can start to collect a lot of metrics about what's going on in our application. So that's pretty cool as well. So that is the actuator. Again, just by including this single little dependency starter in here. So we have this spring boot starter actuator and then defining which endpoints we want to expose or how we want to expose them. We get some more information there. So that is the spring boot actuator. All right. And I want to just do one more thing as we wrap this up and get ready to move to production. I want to get rid of this being here, but I do need a way to kind of load some sample data so that we have something to work with, right? Whoops, did I delete too much there? Nope. Let's go here. And so I'm going to get rid of that. And then we're going to revisit this data loader here, which we're going to use to load some sample data. So let's talk about that. What I first want to do is you can grab this from the GitHub repository. I'm going to create a data directory here under source main resources. And I'm going to create something called content .json. And this is just a JSON file of data. It has three articles and three videos that I've worked on. And this will allow us to load some data into the application. I thought this would be a really fun little exercise just to say, hey, I have some JSON data. How could I use this command line runner and load that data? Right? So we're going to need a couple things. We're going to need that content repository to persist it off to the database. So I'm going to say repository. And we're going to need that through a constructor injection. I'm also going to need an object mapper. So an object mapper is something that comes from Jackson. Jackson is, let's make this final. Jackson is the way that we can kind of create objects out of JSON and deserialize them to, you know, JSON from an object. So that is the just this has already been created in the application context. So we're just asking for that instance. Now that we have the object mapper and the repository, we have everything we need. So let's go ahead and say in here, I want to go ahead and read from that content .json. This is going to be fairly easy to do. So I want to do a try with resources because I'm going to read from something and I want to make sure that it's closed. So what I'm reading from is an input stream. So I'm going to say input stream is equal to. And then I'm let me use something here called a type reference. And then we're going to get a resource as a stream. So what does get resource as a stream do? says, hey, I want to find a resource with the given name. So that seems pretty, pretty useful here. So what I'm going to do is say data content. jason. All right. So now we are in here. And this is not liking us try to resolve. I don't know why it's not finding type reference from. We want it from core. Yes. So, okay. Resolve. So now, once we have that, I can use the repository to save all. So I'm going to save a bunch of list here. And we're going to use that object mapper to read the values. So it's basically reading the JSON. And for each one of those, it's creating a type out of it. What type is it? For this one, so actually we need to read the input stream. What type is it? In this case, we're going to use this type reference. to get a list of content. So content. And that looks good. Let's go ahead and try that. So I'm going to rerun this application again. In application, we've taken that out. So the only data loading should come from there. We should have six values. We should have six values. looks like no airs. Let's go back to our Locust 80 and go to our H2 Council. We'll go ahead and connect. We'll go ahead and run Select Star from Content. And there is our six values. So cool. So we were able to just provide a little more kind of dummy data for this application that we're going to spin up. That way we can go ahead and make sure that this gets loaded when we move to production and we have some starting data. All right. In the report, for this particular project that we're working on. There's a docs folder. I'm going to include this production markdown folder because there's a lot of good info in here. And I thought we just walked through this. We're going to talk about how to build an artifact for production. And then we're actually going to go in and publish this to a host so that we could see it live and out on the web. So production, it's the greatest place on the web. We should all want to go there. But it can be a very scary place. So I picture, I always use this picture because I always picture my friend Josh and my colleague Josh Long as Buzz Light Year saying production. It's the greatest place on earth. So here's Josh just telling us, reminding us that we need to get to production, get there as soon and as often as possible. So there are a few ways that you can build an artifact that is ready to go to production. We're going to talk through just kind of really quickly all three of these and I'll actually build one or two of them. But I wanted to leave this information here for you if you want to kind of explore all of your options. So the first is an Uber jar. So the spring boot loader modules let spring boot support executable jar and war files. We're using the maven plugins. We can get this executable jar automatically generated. To do so, you can create an executable jar running the following command. So remember, you don't have to have Maven installed because we have this Maven wrapper. So this means that we can go down to terminal. And if we see the command here, we can say Maven wrapper. Oops. And we want to type Clean and Package. So Clean deletes the target folder. Package will invoke Maven's package phase, which will cause the verify, compile, and test phases to be invoked in the correct order. So let's go ahead. and run that. And you see it runs some tests. It's doing some things. Build success. So you see it build a jar in the target folder called content calendar and then the version as defined in the palms. If we look under target and we see this content calendar, snapshot. That jar. So to run that, you can use Java. So now this is a executable jar that will run wherever there's a JBM. So we could say, Java dash, Target, content calendar. And if we go ahead and run that, it starts up our application as normal. Cool. So just seeing that as we're preparing to go to production, we should probably fix one thing. We have some logging in there that we probably don't want, right? So let's say application dot properties. Let's just go ahead and remove that. Okay. So that is an Uberjar. This is a really, what I love about the Uber jar is going to be run anywhere that is JBM. So as we're moving to production, a lot of hosts will be able to just take that jar and use it. So that's really great. So the other thing is, okay, this is great in an environment where there is a JVM. But what about an environment where there is no JDK, right? This is where container. and specifically Docker containers in this instance can help us out. You've already seen some examples of running things like Docker Compose to generate that data that run that Postgres database locally. But what you can do is you can create a production version of your Spring Boot application using Docker files or by using cloud native build packs. So I would encourage you to go into the documentation, read a little bit more about this. We'll talk about. resources to kind of follow up this crash course with. One of them is going to be spring office hours. Deshaun and I always talk, you know, one of our sayings is friends don't let friends write Docker files. And you really shouldn't be writing these Docker files from scratch. And that's why we're going to use this cloud native build pack. So to do so, I want to make sure Docker is running. Let's make sure Docker is running on my machine. I believe it is. All right. And we're started.! Let's go back here. And, Now what we can do is go back to the terminal. Let's clear this out. And now we can run, let's get rid of that, Maven wrapper, Spring Boots, and Build Image. So if we run Build Image, this is going to build us a container. So we're going to have a container file or a container that we can now run. So this is really great. So, as we run this, it's building this OCI compatible image. And it does some really interesting things in this image. So we're using Piquetto build packs underneath the hood. Again, read more about it in the documentation, but it does this really nice way of building this out, using different layers. And again, this is not something you want to build by yourself. Leave this up to the people who are doing some amazing things here with Kitaters. I don't do this every day. So I don't want to have to manage this. That's why I kind of lean on the cloud native build packs to create this for me. So once this is done, all we're going to do is say Docker Image LS dash a. We want to see that we have that particular Docker file created. So we see saving Docker I .O. Library, content calendar, snapshot, and the build was a success. So if we say Docker image, LS, oops, alice dash a. We can see a bunch in there, one of which is our, did I miss it, content calendar snapshot. So now what I should be able to do is use Docker and run it. We need to map port 80 to 80 to 8080. We're going to call this content calendar. Oh, oh. dot one, or 0 .0 .0 .1 dash snapshot. snapshot Dan. And as you can see, it's starting up our spring boot application. So this is really great for any host that doesn't have a JVM environment. Anywhere that can run a container image, boom, you're ready to go. You can just pass this container to them and you are ready to go. So I'm going to go.! up that. That's our container image. And then there's native images. If you're using Spring Boot 3, there is a way to compile down to a native image. So this is, this works really great for different workloads. Some of the things that kind of stand out for me are like serverless functions or even serverless environments. You know, building your own like CLIs. I did a video lately on my channel about building a CLI using, actually I've used one using Java and then built one using Spring Shell. So then you can turn those types of applications into a native image and it just runs on your fast. And the benefit to a native image is you get that smaller memory footprint and faster startup. So that's really cool. So we're not going to run that here. This takes a little while to run. So I'm not going to do that here, but that's an option. So all of this is leading up to how can I get my application into production? So I've compiled a little bit of a list here. Here are some places that you can host your spring applications. There are more, but this is just a short list of places that I really enjoy. And actually on my channel, I'm doing a bunch of different videos on deploying to these different environments. We've done, I think, three of these so far, and I'll continue to work on these throughout the year. So there are some resources for this. Again, we talk about this a lot on spring office hours. And here are the three that I've already done for Azure Spring Apps, Heroku. and so what we're going to do today is focus on railway. And I like railway because there's a free option. So if you don't want to spend any money and you just want to kind of see how you can get this particular application into production, I think railway is a great way to do that. So what are we doing? Let's take what we've learned today and get this application into production. All right. So before we head over to railway, I want to talk a little bit about our project. So we've been using the H2 database in our project. And again, this is great for prototyping and developing and the things that we were doing. As we're getting ready to go to production, we want to think about this because currently we're using H2 in our development. And then we would be using something like Postgres in production. And typically you don't want to do this, right? You want to stay consistent with whatever database you are using in production, should be in your dev environment, should be in your tech environment, should be in your test environment. If you haven't had a chance to check out something like test containers, that will allow you to spin up a Postgres container in your tests. So that's really great. So I think what we should do is make a change here and make sure that we're using Postgres in our local environment. And to do so, we need to do a couple of things. First, I'm going to go over to my palm. I'm going to get rid of my H2 database driver. And I'm going to include the Postgres driver. So I'm going to go ahead and grab that off screen. It will look something like this. We did this earlier, so it should look pretty familiar. So with that in place, now in my application of properties, I need to set some Postgres properties, right? Now, what are the properties? So I have a Docker composed file that we used earlier. So you will need Docker to do this. locally, if you haven't already set that up. If not, you can go ahead and set up Postgres as a local instance. I'm just not going to walk through that here, take a little bit too much time. So if you have a local Postgres instance running, no need for doctor, you can just input your parameters. So I have this running on port 5432. Postgres is the username, password is the password. So spring. datasource. JDB, Postgres, SQL, Local host, 5432, and then the database name is Postgres. We need a username of Postgres and a password of password and then we're also going to need that SQL init mode to be always. Cool. So let's, with that in place, let's see if we can run this application. And we have an error. Oh, yeah, so syntax near or at auto increment. So again, this is kind of why you want to use the same database in dev and production and test, right? This schema file is using something kind of specific to H2, right? That's an auto increment. In the world of Postgres, we're just going to say that this is a serial and we'll say this is this is primary key. So now with that in place, let's go ahead and try and run our application. And air syntax at our near descript. Oh, I wonder if that is a keyword. I think that is. should be description. So now we don't have to change any of our code. We're just changing where that gets stored. So I'm going to change this to description. And let's go ahead and rerun that. And cool, no errors. So I think I think we're good there. So again, just being consistent there will help us kind of catch some of those errors on a local machine instead of as we deploy them to production. So with that, now I think we can go over to Railway. You can find Railway at Railway. Dot app. If you want to go over to pricing, you can check out what pricing there is. I think I'm logged in. That's why it's not allowing me to see the pricing. Let's go here. So if you get a pricing trial, you get a pretty generous free tier, 512 megawatts of RAM, a gigabod on disk, $5 or 500 hours of usage. So again, this is really great for your. kind of side projects or something you want to just test out. Really awesome to use. Now, there's a developer tier as well. Ditch the limits still free under $5. So if you stay under free, it's still $5, but none of the limits. As soon as you exceed these limits, you know, you'll have to pay a little bit more. So pretty nice, though. And you get a lot if you head to like a team for $20 a seat. So I'm a big fan of Railway. I'm going to go ahead and log in. And what we need to do is create a new project. So when you create a new project, you can come in here and you can say, you can deploy a project from GitHub, from a template. They have a ton of templates. You can provision a database. What I want to do is actually create an empty project because I'm going to create a couple services in here. One is going to be that Postgres database. One is going to be my project from GitHub. So let's create a new service. I'm going to create a database. I'm going to add Postgres. And it's going to come in here and provision it. And once it's ready, I can go in here. So from the data tab, I can go ahead and create some tables if I want to. Again, we're going to kind of let Spring Boot do that for us. You can come in here at query tables, which is really nice. There's some connection info. So if you wanted to connect straight from, say, a terminal you could. Here's the URL connection. We have logs in here. These are our variables. So these are the different variables that we're going to use. And I think this one, yeah, I'm going to go ahead and copy this one because we'll use this. You have metrics and then settings for your database. So once this is up, now we can go ahead and create our application. So I'm going to go up here and say new from our GitHub repo. If you don't see this in here, you need to configure your GitHub app to allow either access to this specific GitHub repo. or to all of your repos. I only give it access to specific repos. So it has access to these two. I'm going to go ahead and select this one. And then as this goes, it's going to start trying to build, but we don't want it to build yet. We can just abort this if we want. Oh, no, we'll just leave it. It's probably going to not work. So we need to set some. environment variables, but we need to figure out how we're going to connect to this Postgres database that we just created before. So I'm going to head back over and we're going to go to source main resources. We're going to create a new file. We're going to call this application dash production that properties. Right. So in here, I'm going to copy this thing that I copied from there. And I want to copy these because these are going to be specific to production. So what we need is we need the host. So the host is PG host. So let's go ahead and do this. PG host. The port is going to be PG port. And the database is going to be PG database. Cool. The username is going to be PG user. And the password is going to be. P password. So the reason we're doing this is you could go in there and get the actual values for this, but this isn't something you want to stick in a plain text file and commit to get because then somebody can grab your Pg username and your PG password and use your database. So this is why we're using these property placeholders that will get replaced by an environment variable later. So with that in place, before I commit this, I'm going to add a new variable here. And so we want to set the end. active profiles. So we're going to say spring profiles active and we want to set this to production so that it uses our production settings. So with that in place, I'm going to go ahead and commit this and say updating for railway. And let's commit, push. And let's commit. And then as we go back to our deployments here, we should see updating for railway. So this one started. This is the one we care about. And it is going to go through and build. So it's doing its first thing, downloading everything from Maven. It's actually going to use another way to build a container called Nix packs. You, as you'll see in the settings, you can kind of change how it builds. But I'm going to use. fine leaving it at the default. So it's going to build a container and then deploy it for us. So you can see US West 1, Docker PG, there's railway, build time, 26 .62 seconds. Now it's going to publish that image and then try and run our spring boot application. All right. So we have a success. If you drill into there, you can see the spring boot application starting. our Hikarii people. Tomcat started on 5970 and our application started. So if there was an issue and you didn't do something correctly, you would have some output here that could kind of point you in the right direction. You see that we are following, the following profiles active, production. That's a good sign. So if we go into here, we can go over to settings. We can actually generate a domain name. So let's generate a domain name. And this is a going to give us this content calendar production. So let's go ahead and click on this. And it's going to open up in a new tab. And here it says one moment, your deployment should be live soon. So let's go ahead and just wait a second for this to be live. Cool. So it's live now. We remember our home endpoint is displaying our configuration properties. So if we want to go over to API slash content, there is a list of all of our content in the database. So this is pulling from the database. And it looks like we may have run this twice. So that's a good thing to note. If this got deployed once and then deployed a second time, we are running that command line runner every single time. Because remember, we only ran this in development mode. And in development mode, we had the H2. And every time. that restarted, we had a fresh database to work with. So now every time this starts up, it's going to insert that data. So you may just want to add a quick check in there. So we'll come back here. I'm not going to run this again, but in your config and data loader, you could do something like if repository dot count is equal to zero, then go ahead and do this. If not, we don't want to go ahead and insert this every single time. Okay. So cool. So if we go back over to railway and we jump into Postgres, we can see that we have this table. We can see all of the rows in there. We can also query from here. So we can say select star from content, run our query. And cool, we get all our rows in here. So really, just that easy to get something up and running on Railway. The biggest thing you have to worry about here is make sure you set the profile, the active profile, and then make sure you're using these particular environment variables that Railway has set up for the database. If not, you would have to set up new variables for that with specific values. So cool. Again, just a nice a really nice, easy way to get an app out into production, especially when you're, you know, just kind of playing around or tinkering. There's that free tier. There's also a generous developer tier. Big fan of Railway. But there are other options. So make sure you look in the documentation for this repo under Docs, under Production. There is a bunch of hosts that I can recommend. Again, some I've done videos on, some I haven't, but a big fan of all the ones on. this list. So go ahead and check those out. Wow. First off, I just want to say thank you for sticking around through this entire crash course. You made it through it. I hope you learned a lot. Now, this was a crash course. This was not a full masterclass on how to learn everything there is to need to know in spring. So I know I'm going to get a lot of comments like, why didn't you cover this or why didn't you cover that? We had to draw the line somewhere. There are a lot more things that we could go into that we just couldn't do today. So that's that. This is a crash course. I said this at the beginning. Please take what you've learned today and apply it to a different domain. I think that's where a lot of the real learning comes into play. So kind of what's next? First off, spring office hours. If you guys aren't aware of it, it's this really great show that Deshaun and I do over on Tanzu TV. Go ahead and check that out. I will leave a link in the description below as well as the resources in the docks folder for the GitHub repo for this project today. there is a resources. This file contains a whole bunch of resources. So all the documentation to a lot of the things that we covered today, those links are in there. There's links to books I suggest, podcasts, YouTube channels, yours truly, of course, and then everything that you need to do to find me. So, again, there is so much more to learn. This is really just the beginning, friends. I hope you will follow me on YouTube, Twitter, and link in for more content. I really, really hope you got something out of this today. This was a lot of fun to put together. I hope you had fun going through it. If you did, help me out, friends. Give me a thumbs up on this video. Subscribe to the channel. And as always, happy coding.