The Spring-Boot Crash Course | Cosmin Ionita | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

The Spring-Boot Crash Course

teacher avatar Cosmin Ionita, Senior Software Engineer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Intro

      1:03

    • 2.

      Why SpringBoot?

      2:17

    • 3.

      Create your first Spring-Boot App

      10:38

    • 4.

      How can we use POST requests?

      10:55

    • 5.

      Implementing standard responses

      6:18

    • 6.

      Creating Services in Spring-Boot

      14:08

    • 7.

      Adding configs in application.yaml

      6:01

    • 8.

      Calling external services via HTTP

      9:09

    • 9.

      Configuring MySQL with Docker

      9:33

    • 10.

      Configuring our Spring-Boot app to work with MySQL

      15:19

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

254

Students

1

Projects

About This Class

Intro

This course is everything you need to get started with Spring-Boot framework in Java, which is the most popular JVM-based web framework for building microservices and backend systems, used by many big-tech companies.

Java is a really great language and provides a number of features out of the box, but if you want to build a REST API in pure Java, it might not be so straight-forward.

For this reason, developers have created frameworks that allows you to build APIs fast, with best-practices in terms of code design and performance/efficiency, and Spring-Boot is such a framework.

Why do you need to learn Spring-Boot Framework?

Spring-Boot is so popular because of the following:

  • It allows you to create create production-grade applications very fast
  • It promotes a well designed code-base
  • It integrates with external systems seamlessly 
  • It has a big open source community that constantly improves it
  • And many other reasons

Having Spring-Boot in your skillset as a Java developer, will allow you to:

  • Be more competitive in the job market
  • Be more productive because you'll read and write code faster (and better) by recognising and applying well-established design patterns embedded into Spring-Boot 
  • Be able to tackle more technical opportunities since many open source projects use Spring-Boot  

Overall, this framework will take you a step further in your Software Engineering career and learning it as soon as possible is probably one of the best strategic moves that you can do for developing your technical expertise.

What you will learn in this course

This course is about 1 hour long, but be aware that it is jam-packed with information. In a nutshell, in this course we're going to create a plain REST API that interacts with a MySQL database to store user data, and also with an external HTTP API, to grab some external data.

A non-exhaustive list of things you're going to learn in this course is the following:

  • What is Spring-Boot and how it compares to a traditional command-line Java application
  • How can you import Spring-Boot framework in an empty IntelliJ Idea project
  • How can you find the right Spring dependencies on the web
  • How can you create a REST Controller and receive some data via HTTP
  • How can you configure your REST Controller to send data back and follow best practices
  • How can you create Services in Spring-Boot
  • How to use Spring-Configuration mechanism
  • What is Dependency Injection and how does it work
  • How can you call an external API via HTTP from your application, using a HTTP Client
  • How can you configure the Jackson deserialization to extract only the data you need
  • How can you create and configure a MySQL database using Docker 
  • How can you configure a Spring-Boot application to connect and interact with the MySQL database
  • How can you use Transactions in Spring-Boot to ensure atomic operations on the database

This course is meant to guide you through this framework by showcasing how can you build a simple application that connects to other 2 systems, from an end-to-end perspective. It's highly practical, because this is the best way to learn any new technology, by playing with it as much as possible

To set the right expectations: this is not a complete Spring-Boot course, it doesn't cover all possible configurations and dependencies that Spring-Boot provides. Instead, it's a course highly focused on building an application similar to a microservice, and the main goal is to give you a taste on how Spring-Boot looks as a web framework and what is the developer experience for using it.

Prerequisites for this course

This course is addressed to beginner Java Developers, Computer Science/Engineering students, existing developers that want to learn something new and of course, to anyone who wants to learn Spring-Boot.

The only prerequisites for this course are the following:

  • IntellIJ IDEA community (free) edition
  • Basic Java knowledge (classes, interfaces, generics)
  • Willingness to learn :-)

In the last 2 lectures I'm going to use a terminal and Docker, so if you are familiar with those it will be easier to follow along, but they're not required as I'm explaining any command that I run step-by step.

Thank you for being here and let's jump in the first lecture!

Meet Your Teacher

Teacher Profile Image

Cosmin Ionita

Senior Software Engineer

Teacher

I'm Cosmin, a Software Engineer with over 10 years of experience in developing enterprise-grade applications, based in Bucharest, Romania.

I am a self-learner, truly passioned about the technology, focused on gaining new skills, building great professional relationships and deeply understanding the underlying concepts behind the technologies I interact with.

 

My expertise revolves around JVM-based applications and surrounding systems/techniques for container management, deployment workflows, monitoring and alerting, performance optimization, code quality, resource efficiency, and many others.

 

I strongly believe that continuous learning is the only way to stay relevant in the Software Engineering industry, and to me, teaching is a... See full profile

Level: Beginner

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Intro: Hey everyone and welcome to the Spring Boot crash course. The best online resource you need to learn Spring Boot from scratch and become a better software engineer. Springboard framework is used by many big tech companies to build their microservices architectures, and large-scale back-end systems, because it helps you to build highly performant production rate applications while keeping your code base scalable. Having sprinkled in our skill set will allow you to become more competitive in the job market and is definitely a required technology to master on your way to becoming a senior back-end software engineer. In this one, our course, we're going to build from scratch a rest API using Spring Boot that communicates with an external API via HTTP, but also with a local MySQL database to store some user data. The goal of this course is to show you how Spring Boot works in an end-to-end application with the functionality similar to a microservice. And hopefully this will give you that powerful starting your journey of becoming a spring with master. The only requirements for this course is to have intelligent idea installed basic Java knowledge, and of course, a strong desire to learn new technologies. So with that, let's jump into the first lecture of this course. 2. Why SpringBoot?: Hi everyone, Welcome back. So before we dive into the actual code, let's take a moment and understand why do we need to learn Spring Boot framework. Right here we are on the official website of spring width. And if we click on the Overview, we can see a number of advantages of this framework which are actually validated by the industry. I mean, they are added right here on the website. But the popularity of this framework actually says something about whether those advantages that are actually true or not, right? So first of all, about the popularity, right? But the reason it's so popular is because it's very flexible and allows you to build production rate apps really fast. We're going to see further in this course that spring with is really easy to configure, whether using annotations or configuration files. And it's also important to mention the landscape of applications where Spring Boot can be used. We can use it to build microservices, which is kinda like the, the new trend nowadays. Pretty much any big company has this microservice architecture in some part of their infrastructure. And Spring Boot has actually full support for this Mosley. If you use the Spring Cloud and the Cloud capabilities that Spring Cloud actually offers, um, but apart from that, you can also build reactive applications and event-driven applications. So it integrates with pretty much all the new stuff that's going on out there. So in other words, if you know how Spring works, you have an, a, an advantage in this software engineering world as of today. So there are a number of clips and documentation on the internet that you can actually follow if you want to see an overview, or Palm Springs actually works, a lot of people are actually using it. So There's plenty of documentation on the Internet. And the main role of this course is to enable you to use springboard really fast. So we're not going to dive into all the small details of springboard. We're just going to start right away and get going with the main capabilities of Springfield, right? I'm going to assume that you can have no object-oriented programming and how things work in that space. I'm in classes, interfaces, methods and things like that. So basic Java knowledge. And then we're going to build on top of that with the capabilities of Spring Boot framework. 3. Create your first Spring-Boot App: So enough talking. Let's see some code, right? If you want to build your first Spring Boot application, we got two options. The first one is to use this spring initializer website, which you can access at startup Spring dot io. And this website allows you to create a pre-configured Spring Boot application. You just have to click around, select your project, your language, your Spring Boot version, and complete your project name artifact group and things like that, including the Java version. And when you click on Generate, you're going to see that the browser will download an archive with the project in an intelligent idea project that contains a simple Hello World application with springboard preconfigured. This is of course the easy path, but we're not going to go on that route. Instead, we're going to start from a clean intelligent idea project and we're going to add what's required in terms of spring dependencies to see how it actually works. So right here I have the intelligent idea, Community Edition. I'm going to click on New Project. I'm going to say Spring Boot course. I'm going to select Java as a language greater as-built system. I'm going to use Java 17. And right here I'm going to say Java dot, spring, spring dot course. I want to hit Create and we're going to wait for Gradle to get refreshed, to download all the initial dependencies. And this is our first project. Now we're going to go back on the web and search for Spring Boot starter web. Maven, Central. Central is of course the main repository for JVM based dependencies we're going to search for this dependence is called Spring Boot starter web. This one is kind of a slim dependency which includes pretty much all the things we need to create a very basic Spring Boot application. We're going to click on the latest version and select Gradle. And we're going to copy this right on our build-up Gradle file, the dependencies section. I'm going to paste it here and then hit greater refresh. And then we can see that it got downloaded properly. Now I'm going to get back on the main class and right here on the class level and go into annotated with Spring Boot application. These are rotation comes from, of course, the Spring Boot framework identifies the entry point for our Spring Boot application. And in the body of the main class, we're going to say Spring application dot run. And right here we're going to provide the main dot class object. So this is a, this is the identifier for the main class where the spring with annotation is located. Then we're going to provide the arguments that were provided on the main method. So what this line actually does is to start, the actual framework is basically a blocking instruction. So the application, the process, JVM process will not exit until the application is killed or until it gets, the process gets terminated in some way, right? Any Spring application, I mean, any web server actually should be long running because it should accept continuously connections from HTTP clients. So when we click on run, we're going to see in the logs this output. So you can see this nice art saying spring as well as the spring version. And on the logs we can see that we got here the logs from Tomcat web server. We can see the port on which the application is running, and we can see that it started successfully. In other words, Tomcat is basically a web server which comes with Spring Boot. So you can also install it independently, right? It's built by the Apache community and it's basically a classical web server, just accepts connections, follows the HTTP protocol and all the stuff. The main reason it was imbedded into the framework, I believe, is because it's very lightweight. So it doesn't consume too much memory and too much, too many resources. And probably this was the reason it was chosen to be part of the springboard framework. I believe we can also change it if you want with Apache or caterer or other web servers. This is how it works in a default version, right? Right, so this is how our first Spring Boot application actually works. Currently application doesn't do anything, it just accepts connections on ADHD. But if we go in our browser and say localhost, local, solicit, local host ADHD, and we just click on it. We can see that we don't have anything. This error actually comes from Spring Boot or from Tomcat, I believe, because it needs to find some paths to map the request and on the default, Patty doesn't have anything to map to. So currently our application just runs and we haven't specified any kind of action to be executed on a particular interaction, right? So this is currently the state, right? We just have an application that doesn't do anything. How do we tell to this obligation that it needs to do a specific action when the clients are interacting with it in a specific way. So for that reason, we're going to create a class which is called a controller, a rest controller. And we're going to put that class into a dedicated package called controllers, right? Just created package and then I'm going to call this user controller. So when a Spring Boot application, a controller is the first entry point for a request in the application. So when the clients are making a request that needs to hit the application, usually it will hit a controller first. Then based on the logic defining the controller, the request will get propagated in other components, as we'll see further in this course. So to make an idea on how a controller works, let's create a method here called public void, actually public string get user. This method is a very simple classical method. It just returns something like user John Doe just returns a string. And very important, this method will be annotated with get mapping followed by getUser right here. We can have any kind of string which actually should start with a forward slash because it needs to have a path-like structure. So what this annotation actually does is to create a path or a route in our application. So when a client, either a browser or any HTTP client is going to call that path. This method will be called right inside our application, right? So this is how it actually works. Now let's rerun our application in order for those changes to take effect. And we're going to hit Enter on this one, right? So as you can see here, we've got this string back right? Now, if we click on Inspect to see the actual request, if we go So on the Network tab and hit refresh, we can see that the browser actually launched this HTTP get request on that URL, localhost 80, 80 getUser, the browser by default, when you refresh any page, it makes this get request. Actually it makes, actually it initially makes this get request. And then it can download some JavaScript back, which then gets executed by the browser, which then can allow other requests and so on. So in practice, this is even more complex. But in this very simple use case, the browser just launched a get request on which actually hit our API, which returns this string object. So this is how you get data back from our API. Now, if we just click here, if we click here on the response, we can see our string payload. And if we click here back on the headers, we can see that on the response headers we also got this information here. Those headers were actually added by the framework. So we didn't, we didn't do anything to that data to show up here. Those are the request headers. And by the way ahead, that is just a key-value type of information entry, right? And this is what the browser Chrome actually added on the request to our application. Now, of course, we can change those headers by using the Spring Boot mechanisms. But a very important thing to note is that their structure, the name, the key name of the headers, and the values are actually regulated by the HTTP protocol. So the HTTP protocol, and by the way, HTTP stands for Hypertext Transfer Protocol. Hypertext actually refers to HTML, but it's more of a legacy naming because you can actually transfer binary data using HTTP. So HDP has a number of rules. Any protocol basically has a number of rules which governs some kind of action. In this case, HTTP governs the communication between the client and the server. So you can see basically all kinds of details about the way header should be passed away. Your proxies actually work. And in other words, if a client and the server respect the same rules, they're able to communicate correctly using the rules of the HTTP protocol, also caching. But the scope of this course is not to go deep down on the HTTP protocol because it's very, very complex. And lots of details are inside this particular topic, maybe for a different course in the future. But for now, we're going to limit ourselves to these very basic usage of this protocol. As a short summary, when you make a get request to a web server, you are basically requesting data from it. When you're making a post request, you're delivering some data to that server. In this case, we define a good mapping, which means that we instruct the API, the Web server, to allow GET requests on that path. We also have post mapping, which means that we instruct the web server to receive data from external clients on a different path, e.g. edges. And this is what we're going to do next. In the next lecture, we're going to continue to build this user controller in order to explore that interaction with external clients even more. 4. How can we use POST requests?: So we saw the way we can basically get some data back from our API. Now let's learn and play with this input, output mechanism of Spring Boot, which is the controller and the mapping setup. A really nice thing about testing with a browser is if you have HTML returned back from your application, because browser will actually render the HTML. If we say something like HTML closed, and then we say body, of course this is not, this is just for testing purposes, just to play around to show you that the browser renders the HTML, just any texts here. So if we run this again and reload the page, we can see that the text is basically rendered by the browser. Accordingly, we return HTML, but it gets rendered automatically by the browser. Now, when you have web server as you usually transfer data in some kind of format like JSON or proto buff. And you don't really need this kind of interaction with the browser, but it might be useful if you have this kind of use case, just returning back HTML. Now, instead of the browser, we're going to use dedicated HTTP client, which is called postmen. This is basically a tool which has this nice user interface that allows us to interact or test an API with different kinds of requests, types, and different kinds of payloads that can configure in a very easy way. So when you design web service, usually play with this kind of tool to see how it works and to test different things. So the exact same request that we made from the browser, we can, we can make from Postman by saying localhost 80, 80 followed by Git user. And if you click Send, you can see that you get the HTML ran, returned back, right? You can also format and response in different ways. So now let's say we want to return a string back from our API. That string should actually be the JSON representation for our user object. So let's first define a model in our application. I'm going to create a new package called model. Right here, I'm going to say User model. This is the class for our user. And inside it we're going to have private String, firstName and lastName. And let's say we also need to provide integers a membership by d, right? Which is kind of a premium platinum user or things like a single server level in, in our application just to test things around. So we're going to add, first of all, a constructor. We're going to also add getters and setters for all the fields, right? Intelligent idea helps us to do this really, really well. The only controller we're going to return a user model back, right? We need to import that class. And right here when we return that, we need to say New User model of John Doe and 1234, okay? Of course, we play with classes in real-world, we play with actual objects models. So for that reason we need to experiment with that as well. So when I hit send on the response, we get back this JSON. So as you can see, the, the, the framework actually converted our object into adjacent, basically the, our object, a model gut serialized into adjacent format, right? And this was done automatically by the spring would framework. Now, if we go back to the controller, we can have a situation where we need to return different users based on an ID, right? So e.g. let's say we have here a map, private map of string to UserModel, right? Call this user map new HashMap. Alright, and let's say we add a small controller right here, public user controller. And on this map we have two users. Let's say, let's say on the user map we add, we put first of all the user John, which has this, this model right here. And then we also put the user Jane e.g. and this is Jane Doe with different membership by d. So basically we have those two users in this map. And when we want to get the user from our API, we want to get it depending on the name, right? And this means that the name needs to be provided on the request. So the client should actually add here a name that can be a variable. And this one should be called username, right? This is the way you specify on us, on a path, the fact that you want to extract a variable from it. So right here on the username, we need to also add it on the parameters of this method using the path variable annotation. Here we need to specify the type of the variable and the same exact name that we added on the path, right? So when you make a request, if you say getUser John right from the browser or from postman, The John value will be propagated on this username variable. And we can use it like any other variable. So in this case we can say user map dot get of username, right? So let's rerun this. And actually I go to also hit Debug and put a breakpoint right here to see that this variable gets populated properly. So the application started. I'm going to get back on postman and say getUser dot John and hit Send and rice, we can say that the username variable has the valid John, and it will just go into the map and return the actual object, right? So I'm going to hit Next and back. We can see that we get the same thing. Now if we use chain, we can see that the variables so that we played properly and hit F9, and we can see that we get the other objects. So this is the way you guys basically provide some data to the application on the path, on the request path so that you can select different kinds of information. This can be a user ID, it can be an email, it can be anything like that, anything that actually makes sense in your application. Now let's shift gears and play with some pause to requests, which is the way a client can provide data to an application. For Spring Boot application, we want to create a user, right? We're going to say create user. When we create a user, we don't want to have anything back, but you want to update this, this contract. Second, we're going to say here, post mapping, right? Because we want to provide some data to our webs are in that data should be the user details, right? The FirstName, LastName, and so on. So we're going to say Add User, and that's it. And right here on the parameters we need to provide something like response, request body. This annotation tells Spring Boot that it needs to extract some data from the request body and put it into an object. That object should be e.g. the user model, right? So this means that on the user map we can say put and we can say user dot get firstName followed by the actual object. Yeah, I don't have to return anything here, right? Because the method doesn't have any return type. So in other words, I'm extracting the user model from the request and I'm putting it on this user mapper. Let's do this. And the first time I'm going to try with a debugger to see that the user object is populated properly. Yeah, So the application is started. So I'm going to create a post request. I'm going to make a new tab here in Postman. And I'm going to select here post, right. I'm going to say Add User. And right here on the body, I'm going to say your row, and I'm going to select JSON application json right here. I need to provide adjacent which contains the actual information for the user. I don't want to create that Jason should follow the schema of that object or the user model object, right? So you should convey the first name, last name, and the membership ID. I can simply get them from the other tab. And of course I'm going to populate them with different values, e.g. Daniel, Craig. And this should be a value like any integer that we want. If we click on Send, we can see that we get an error called internal server error or something happened. Let's see what happened. So if we go right here on the logs, we can see that cannot construct an instance of user model, no creators like default constructor exists. So this is an arrow that you can probably see pretty often actually, if you play with objects, with serialization, deserialization, things like that, which actually tells us that when you provide this Json, right? And the spring with the receives that Json, it basically tries to create a user model object. But when he tries to create this user model object, it doesn't use this constructor, right? Which has those three parameters. Instead, what it expects, it expects to have a constructor with no parameters to just create an instance. And then it expects to use the setter methods to set all those three fields one by one. This is what actually the Jackson civilization framework actually expects, right? This is the component inside springboard that deals with serialization and deserialization. So in other words, we just have to provide here a default constructor with no parameters. And it will work creating again, running again the application with debug mode. It should have started. Okay? Now, going back to Postman and click on Send, and it says that we have a bad request. Let's see what the error now it says JSON parse error numeric value is out of range, right? So it looks like this number that we add here is out of the integer range, so we just have to add a smaller number here, right? Now if click on Send, we can see that it works. So if we click on this user parameter, we can see that it populates with the right values. And if we click on F9 to continue the execution, the value should be stored in the map. So if I'm using the other tab to call getUser for Daniel, we can see that we got back the proper response. So this is how we actually add data to our API. 5. Implementing standard responses: One thing that I wanted to also mention about these controllers functionality is that usually when you play with microservices, you need to be able to specify the right status for your introduction for your request. In this case, we can see that we only have Status 200 for all the requests that we made is this is the default one, status to 100, okay? In HTTP, protocol means that the interaction happens successfully and everything worked well. Now you can also search for the HTTP status is online, and this is the full list of statuses that are mentioned by a protocol, right? So e.g. if you have status 500-599, that should be a server error. Successful responses is 200-299. And this will also has all kinds of status is like if you respond with 201, this means that you created the resource successfully. All kinds of interaction models that happened in your application, right? So well-designed. Web servers, the responses and the status is of your application should reflect the actual thing that happened in your application through this status code. And in spring would have a way to do this in the controllers using an object that we need to return on each method, which is called response entity. And this response entity is a generic type. We can also add here http status object e.g. and what this actually means is that we can return from that method something like return, response entity, response, entity, dot accepted, dot built responsibilities. It follows a builder pattern. And when we say accepted here, it means that we add this HTTP status accepted, which is 20.2 on the response, right? We build this object. So basically now when we run the application and we create a new user. So now when we go and postmen again and say Add User, and we provide here some data. We click on Send. We can see that on the response we get to zero to accept it, right? Which is a status code that we add a right here. This of course, for the best practice of your, of your application right? Now, same thing can be done here and all over the place in your application, in any controller you should have this kind of interaction. Also need to mention that the inner controller, you can also have other types of methods, right? Also managed by the HTTP protocol, e.g. if you search for HTTP methods, actually this one, you can see that we get a number of methods here, right? So until now we used GET and post methods. But you can also have head PUT, delete, connect options, trays, patch, and those are all of them. E.g. if we want to use delete, right? If we want to delete a user, e.g. we just have to go right here, copy this method, say delete mapping. And right here we need to identify the user, e.g. we need to say delete user followed by a username, which is again a path variable parameter, right? So we can say here, remove followed by the username, which means that we just get the user out of our map. And when we return the response entity back, we can just say deleted or nutrition if there's any status with no content, can be used for delete operations, right? So if we just reload the application now, and by the way, when we restart the application, which is the only way for the changes to take effect, the map is getting empty again, so only those two users will be added from the constructor, right? So if we add some users and then stop the app and restarted again, the new users will not be in the map when the upper is restarted, right? Because it's of course stored in memory. So let's see, we want to get the user Daniel back should be here, actually now, or it needs to be the user John, right? So this is the user, and now we want to delete. So we want to create a new tab and say Delete. This is the request type delete request method to be more accurate. And I'm going to say delete user followed by John, write, delete it. It says to zero for now content, which means that the deletes what's successful. And then I'm going to click Send again to get the user John. Again, I see that I don't have anything. We can also of course, reshape this a little bit to say something like if the user map contains key username, then I'm going to return it directly. Otherwise I'm going to say return a response entity dot not found, built. And here of course I need to return a response entity of user model. And here I need to say response entity of this one. And this should be actually an optional, optional off this one. So in other words, if I have the user in the map, I return the actual user. But if I don't, I'm going to return not found, which is 404, right? So let's rerun the obligation again to see this functionality inaction, right? So I'm going to get a user John back. I can see that I have it because I just restarted application and the data populated thrown. The constructor actually is in the map. Now, I want to delete a user John, right? When I get the user John back, I can see that I have 404 not found, and not 200. Okay. This is the way we can, of course, update the HTTP status to reflect the right operation that took place in other application. Alright, so with that, we learned about the way we can play with controllers, the way we can get some data from SAP clients, from Postman, and also the way we can get the data back in a proper way. Now, let's shift gears and talk about services in Spring Boot framework. 6. Creating Services in Spring-Boot: Alright, welcome back. So up until now we'll work with the rest controller. We saw the way we can add and get information from our Spring Boot application as an HTTP client and also play with Postman to launch your requests. Now we're going to continue with a structural change over application because as I mentioned initially, a rest controller is the entry point of your application. So it allows you to specify how you should get the data from your clients and also how you should deliver it back. But usually those components should actually forward the interaction inside your application in other structures. In other words, you shouldn't add application logic or you shouldn't connect to a database from your risks controller. You should only get the data in the model that you want and then call a different component, a different class where your logic should be executed, right? The first component of this kind that we're going to dive into right now is called a service. So we're going to create here a new package called services. It may seem that I'm creating here one package for each class, but I'm actually creating a package for each category of class. Because if you want to add your models, you have a dedicated package for that same four controllers, services, and other aspects. So usually you should structure your code in this way in order to make it scalable. So I'm going to call this user service. Now, a service in Spring Boot is just the class annotated with the service annotation. And what this annotation actually does is to enable your application to be seen in the dependency injection framework of Spring Boot, or it registers your class into that setup. So in other words, if we click on that interface to see what's behind it or to see the implementation. We can see that this notation is basically an interface because this is the way you can create annotations in Java. And it also has this component annotation, which is the root annotation in Spring Boot and also other ones. Now, the only functional role of this annotation is the one that I mentioned previously, right? Is it registers the class into the dependency injection framework. And it also has an informative role, right? It tells you that this class is expected to do some kind of computation logic, either calling external services or do some validations, or do any kind of logic that has something to do with the user management. So we're going to move this part right here with the user map storage into this user service and also this particular initialization. We're going to put it into the user service controller right here. And of course we're not going to have access to that map in the controller right now. We need to create some methods which reflect the ones that we have in the rest controller. To enable this separation, we're going to say public, public, UserModel, getUser. And we're going to have here the username, right? So we're going to say username dot yet. So this is a regular class, doesn't have any anything to do specific with the rest controller, so we don't have to return a response entities from services. This is a class which, which connects to the way we get data back on the HTTP client. So he has a moral framework level are all right. But in a service or in a generically in, in any component class, we can add any kind of basic plain Java code. So this is getUser. Same for AD user. We need to have here a user model. And right here when you say Put of user, and here we can say void or something like that. Of course we need to say here user.name, firstName, and then user. And we're not going to return anything. And we also have delete user, right? So we're going to say delete a user by user name, firstname. Actually, we're going to say remove username. Now, the main question would be, we move that logic into this user service class, right? How do we work with this class from our controller? Because we need to have on the instance of the user service in our controller, right? To be able to do the exact same things, right? Adding, deleting or user. So the way we do this is by first, I mean, there are actually two ways. One which is not recommended in one which is recommended. So the first one would be to create an instance of the user service, right? Either top-level right, as a private field or on the constructor write. In this way, we manually create this instance, right? So as long as the controller leaves, it will have one instance. This is one way that it would work. But still, if we need to have, if the user service has a constructor right in the future, let's say, right. A public user service, right? And right here it will need some kind of other class which concerns only the user management, so it doesn't have anything to do with controllers. Then we need to update this constructor right here, this call right here, right, to be able to get that dependency, that validation service, e.g. and provided right here on this construct, this problem is getting given bigger, right? As more parameters are added because we'd no longer have any kind of decoupling between user processing logic and input output classes, right? So we're mixing concerns if we do this kind of approach right here. Instead, the recommended way to play with instances generically in spring is to use the dependency injection setup of spring. So spring with has this very interesting pattern which can also be found in external frameworks like juice, e.g. Google juice, which is called the dependency injection. And essentially a dependency injection framework is just a way to get instances in our application in a decoupled manner without using the new keyword. Because every time you use the new keyword, you hit this problem where when you need the class, you also need to provide all its dependencies, right? And this is problematic, goes to this concern mixing problem and dependency injection framework allows you to approach that problem in a very clean way. So in other words, what we need to do here is to say, is to create basically a private level variable user service, and to add it on this constructor here. And then we can say this dot service equal service, or we can rename this one. It actually knows that we're talking about different variables here. The scope level one and the class level one. But what does, is that when the user controller is being instantiated, right? So when the, when the framework instantiates the user controller class in notices that this user controller needs a user service object and it tries to create an instance of the user service class. And this happens behind the scenes. You don't need to worry about this. And it says that the user service doesn't have any constructor parameter and it just creates the instance like you would do it, the new keyword. Instead, if the user service had any parameters in the constructor, the framework we'll go ahead and search in and try to create an instance for those parameters as well. And it will go like that recursively, right? Until it manages to create all the instances that needs to be resolved. If it can manage to create one instance, it will just fail on the compile-time. That's a very useful thing because you can see that right away. So let's see that in action. So I get this User Service right here. And of course I can use the Contains key or metal right now because it's internal to the user service. So instead I'm just going to say response entity of user service, actually service dot get users by username. And in this case, I have to ensure that getUser returns null or something like that. If I don't have the key on the Add User, I just have to seek service dot add user of the user model that I got from the parameters. And same thing I have to say for the delete. So delete user by user name. So right now we're going to run our application actually, let's, let's make sure that it compiles first, right? So we're going to hear the debug to see a little bit how this controller is getting instantiated, right? So as you can see, the user service has an instance. The framework created this, this user service instance. For us, this is the dependency injection framework that created this instance automatically. And it's very convenient, right? You just have to provide this in the constructor, and that's it. You don't have to worry about how that instance gets created. Of course, let's run it to see that it still works in the functionality should be the same, right? So I get the user John. I can see that it works. I add a user, Daniel Craig. It got to zero to accept it. I request for the user Daniel. I get it back. I delete the user John. It worked. And then if I ask for John again, it looks like I don't have the user John. Let's see what happens. Usually when you've got 500, something went wrong, either a null pointer exception or something like that. Yeah, actually we have that NullPointerException. So in the getUser, we can see that we get optional off. This one actually throws if you have a null value here. So we need to say off nullable. So when you say optional of nullable, if you provide null right here, it will just transform this into an optional of empty. Okay? Let's try that flow again to see how it works this time, right? So I get the user John, now I delete it. And right here when I get, get it back, I can see 404 Not Found. Right. So this is this is how it works. So yeah, this is how the dependency injection framework. Works behind the scenes in a springboard. Now I want to show you one best practice that you really need to internalize because it's absolutely mandatory when you play with co-design and you will create services and play with Spring Boot in general, which is that you usually have to depend on abstractions, your classes, and not on concrete classes. And if we take a look right here, we can see that the user controller class depends on the user class, on the user service class, which is a concrete class. Instead of having that, we need to create an interface called actually first, we need to rename the user service class into the user service implementation I MPL. I'm just going to make that short. And right here I'm going to create an interface called User Service. And that user service should contain those methods. Get user at user and delete user void. And this one should be user model, right? That interface should of course be implemented by the user service implementation. As you can see, IntelliJ idea highlights the fact that we implemented that interface now. And this is the core idea behind this strategy, is that in the user controller, I'm going to request the interface, the user service interface, and not the implementation. And Spring Boot does the following. When it's tries to instantiate a user controller, it looks on the constructor, it sees that it needs an interface, and it actually interprets this in the following way. So the user controller class has a dependency of a class that implements the user service interface. So it tries to search for a class which implements the user interface. In this case, we have a single class that implements the user service interface. And it will go to create an instance of that. If you have multiple classes implementing the same interface and you're asking for an interface and a class, then you need to be more explicit into which class you actually want, right? And you do this by using the qualifier annotation. The qualifier annotation just allows you to add a string and string that you want to add here. That string should also be added when you request an instance of a class, but also when you create that class, right, on the class definition. So if you have two classes, implement the same interface. You need to add a qualifier for both of them so that the spring would knows which one it should provide in which place. You can also experiment and see how this works in action with two classes. So this is how you should actually build a service in a production grade, let's say implementation. It also helps out with the testing because when you're trying to test the user controller, you need to create a new user controller instance. But when you want to create one, instead of having to create all the dependencies with all their dependencies and so on. We just have to mark an interface here and provide the Dominions were for all those methods, right? And you're done. You don't have to go on the dependencies of the user service implementation on all that stuff. You just have to mock that interface. And that's it, right? Also try out with a unit test to see how it works. You're going to see a big difference in terms of the way you implement testing. Alright, so with that, let's jump into the next lecture where we're going to call an external service from our Spring Boot application. 7. Adding configs in application.yaml: Welcome back. In this lecture we're going to reshape a little bit this particular time service implementation, as you can see here, we're using the uterus to make a get request to this world time API to get the current time. But you know, this endpoint might change over time. You may have to use a different API or you may have multiple endpoints in your application and you want to manage them from a single place. So instead of searching for them in all kinds of classes, it's usually better to have a config workflow where you can store all your constants and details of your application that can be, that should be managed from a single place in a dedicated configuration file. Spring Boot has this configuration mechanism which is very simple to use, and it integrates really well into the dependency injection framework of it. So we're going to use it right now. So first of all, we're going to go on the main class. We're going to add this annotation enable configuration properties. This is required because we're going to use a dedicated configuration annotation that's really useful, that's mandatory for any configuration files. So we're going to create a new package called config. And right here we're going to call it time API configure this class. We're going to annotate with the Configuration annotation, which basically makes it available in the dependency injection system of Spring Boot, but also, but also tells Spring framework that this class should be used to store configuration data. We're going to also add a new annotation called configuration properties. And we're going to update this in a second with a parameter inside this class. We're going to have our fields, which we want to grab from the configuration file. In this case, we want to get the end point. So basically this one we want to store in our configuration file and also the continent, because we may want to shift the continent inner configuration based way. We're going to say private string, endpoint and also continents. And we're going to create getters and setters for those two fields. And where are we going to store the configuration file? We're going to go into the resources directory and we're going to create a new file here called application dot YAML, spring with nose to Logan in this location resources, right in the resources directory. And it will look for this application yaml file. If this is present, it will look inside it for configurations. So in this configuration file I'm going to say api dot API endpoint. And right here I'm going to paste the endpoint of our application, which is this one, and alert you also paste here the continent, in this case Europe. So having this configuration here will allow us to store the data in a single place. Now, in this time, maybe I config on configuration properties. We're going to set a prefix for our configuration. Now a prefix for our configuration is basically what as the name says, the prefix under which our configuration for the application should be located in the application yaml file. So in this case, the value for our prefix should be API, because under this API key, we have those two fields that we want to store into the time config class. In other words, this allows us to have all kinds of hierarchical configurations, right? And depending on the prefix, you can select which area of the configuration you want to store in your class, right? Because you may definitely don't want to have a big class with all the configurations in application yaml, right? Alright, so once we have this class created, we're going to use it into the time service implementation. We're going to basically inject it right? In the same way we did with the other services that we added on the constructor. Dependency injection framework took care of their initialization. So we're going to say constructor time API config where you want to store that in our field, and that's it. Now we're going to use it, right? So we're going to say time API, config dot, GET endpoint. We're going to concatenate this with get continent and then with the time zone that we get from the parameter. We're going to also make this a little bit more short on that line. Okay, so the end point, if we take a look a little bit on documentation and in slash, and then we have the continent, which is Europe, and then we get a time zone. So we need also an extra slash here because the time zone is a direct string. So we need to add an extra slave ship. That should be it. Let's put a breakpoint here to see if this actually works. Alright, so now we're going to make a request to add a user and we're going to take a look on this time called API config. And we can see that we got our values populated correctly in this class. And if we make the request, it should work as we expect, right? So we get to zero to accepted if we get it back yeah. Should work as we expect. Yeah, that's pretty much the way we can play with configuration classes in Spring, but we can also change some default configurations which are read by springboard, e.g. the port on which our application is running, in this case, ADHD. If we want to use a different port, we can easily say server port 9019. And when we realized the application, Spring Boot will read that configuration and it will change the port accordingly, right? As you can see, the change took effect immediately on the next run. Of course, the documentation covers all the available configurations that we can add here. You can also do the same thing using the application properties file. So if you're searching on the Internet and you're hitting this configuration file is pretty much the same thing, except that it has a shorter way of specifying the configurations application. Yaml works pretty much in the same way. So with that, let's jump into the next lecture. 8. Calling external services via HTTP: Welcome back. So usually in a web service, you either interact with a database to grab some data, process it, and then deliver back to your clients. Or you interact with a different service in order to grab some data or add some data to that service in order to execute some kind of business workflow that your application is supposed to do in our application. Let's say that whenever we add a user into our map, we want to also store the creation time in UTC when that user was created for the creation time of that user. And instead of doing this by calling the native methods that we have in Java API, we want to use an external API together time from in order to account for time skews or things like that. We're just going to make that also for the sake of the example on how to make an HTTP call to an external API. We're going to do that. So the API that we're going to go to call is called world time API. It's a very simple one. You just have to make a request to this URL with the time zone and you get back a JSON payload width to it some times, then we're going to use this one. So let's prepare all application a little bit for that. We're going to create a new service that we're going to call time service. Not necessarily the best name, but it's the one that we're going to use. So we're going to annotate it with the service annotation and we're going to also change that to time service implementation, right? And we're going to use the time service interface. So what methods do we need to use so we can actually return the actual time, right? Get current time, we can say get current time. And here we can provide some time zone, right? Which can be something like the city in Europe or in other areas of the global, we want to get the time. So going back to the implementation, we can implement the methods. Right here. We can, we can actually make the core, but now let's use that service in our service implementation. So on the constructor we can request from the dependency injection framework an instance of the time service time, service time surveys that we can also store as a private field, which can also be final by the way, right? Same thing with this one because we want to create the instances single time, right? So we got the serve, the time service here, and we're just going to use it on the Add User method. What of course we need a field in the user model where we want to store the creation type. Creation. Also need the setter and getter for this field. And we're going to create it using the intelligent idea functionality. So we got a getter, and we also wanted a setter for that field, right? So we're going to move those two methods down below after deconstructive. So now we have a place in our model where we want to put this creation time. We just have to say time service dot actually on the user model, right? When you say user dot, set creation time. And here we need to say time service dot get current time of, let's say Amsterdam. This should be a time. So let's say it's in Europe by default. Amsterdam is the city that we want. Now, of course, this, this time zone can be fetched from an external service, co-location services, which detects the location based on the client IP. So you can expand on this even more to get more and more complex functionality. But in this case we're just going to leave it as it is. The main question here would be, how do we get the time? How do we call that HTTP API? So for that, we're going to use an HTTP client which is called union rest. In Java, we can manage to be clients. We also have a built-in version, but this one is the easiest way I know to make an HTTP request from an application to an external API. So we're just going to import the dependency unit, whereas Java, we're going to put it into the build-up Gradle file and hit Sync. See if that's the right. 11311. Looks like great. Detected that there is a newer version of that dependency. That's the one. So in our in our time service, when we want to get the current time, we can say something like this. Union rest dot, get us a URL here. And the URL is the one that we have right here. But of course, it needs to include this time zone. Then we can say as Jason. So what this does is to make the request and get the response back. Now as Jason return an HTTP response of Jason node, which is a more primitive datatype. We don't really want to do this. We want to also convert this to a model. So let's see if we have other options for this, for this HTTP client. So let's say as object, right? We have this as object here. We also have the async version. So when we say as object, we need to provide here a class which has this format of the response that we expect from the API, right? So this is something that we need to create in and out. So in the models we can say time. Or timer's time API response. This can be a name for our class and we have two options, right? In, in defining this class, we can either create one field for each key value pair that we have right here. But because we're not going to use all those fields, instead we're going to use only this one. We don't necessarily have to create all of them. We can just create only this one. So UTC date time, we're going to say private string UTC date time, the name should match. We can add constructors, right? And also getter and setter for that field. And we're going to move the constructor a little bit up right here on this class level place, we're going to say json, ignore, ignore, ignore properties, right? So what this annotation does is to ignore all the properties that we're not at a right here as fields in our class. In this time, we just extract what we need from that payload. So having this model, we can use it right here. And you can see time service implement. We can see time API response to class. And we can have it right here. Get body, right. We shouldn't forget this body because as object returns an HTTP response of your type. So we need to use get body to get the right get the actual response object. Once we have this response, we can say response dot get you to datetime, right, extracting the field from our class. Alright, so let's see what we've done until now, right? So we use this service to extract the two together time from this external API, and we place that time on a new field in our UserModel class. Now, well, of course we need to see if this works. So let's hit that breakpoint and restart our application. I'm just going to also add a breakpoint inside our time service implementation to see if the coal has been done correctly. So I'm going to add this user back and I can see this response, right? And that's the one. So I can see some data here, which means that I got the response correctly from this external API. If you want to debug more things, you can also remove that yet body and use this HTTP response of time API response, right? And then say response dot, get body, get UTC, date, time. Because in this HTTP response, you can see more things like the HTTP status or if there's any data buffering, all kinds of details can be seen in this object, right? So I'm going to hit that again. And I'm going to see this HTTP response getting back right. So you can see that we get the status code 200. You can see that we got no error. You can see the headers that were received from this API. We can see here all of them. And also we can see the body. The body has this, this object with our datatype, right, hit F9 to continue the execution. And that's it, right? We got to zero to accept it. Now if we get the user back, we should also see this creation time because these get flow actually returns the whole object and displays it on the HTTP response. So that's pretty much all about calling an external service from your application in Spring Boot. That's a very interesting way of connecting with other services. And in the next lecture we're going to work a little bit on this time service implementation to make it a little bit more configurable. So with that, let's jump into the next lecture. 9. Configuring MySQL with Docker: Hey everyone and welcome back. In this lecture, we're going to see how can we connect to a database from a Spring Boot application. Because as I mentioned in the services lecture, the microservice can either connect to an external service to grab some data or send some data, or it can actually connect to a database for the exact same thing, right? So you somehow need a way or a place to store your information and retrieve it back from your application. And of course, bring wood has a number of mechanisms to allow us to do that in a more easy fashion compared to, let's say you're doing it on our own. And it's also important to see this in the context of having multiple database flavors and models and data modelling schemes. So we're going to look to this exercise from those lands of this complex, let's say, data storage ecosystem that we have in the industry as of now. So basically what we're going to do in this lecture is to replace this user map with my sequel table, which will actually have a schema with very similar to the one that we have in this user model, right? So pretty much all the same fields with, let's say with an ID that will serve as an identifier for a record in the database as a primary key. So basically this lecture will have two parts. The first one will be the one where we're going to create a database and configure it to create the actual table. The second part will be to actually modify our Spring Boot application to interact with the database. So let's start with the first step, right? I'm going to open my terminal and I'm going to use Docker to run a MySQL container. Now of course, Docker is not a prerequisite for this course. I don't expect you to know how it is. So for that reason, I'm going to make a very small introduction to this particular technology and I'm going to explain all the commands that I'm running step-by-step. So it can be actually easier for you to follow along. First of all, Docker container runtime. You can actually go right here on docs.docker.com. And you can actually find a lot of details about Docker as the technology. In a nutshell, docker is a technology that allows us to run containers. And container is basically a lightweight virtual machine which doesn't require a hypervisor, like VirtualBox or VMware or Hyper-V. So you can basically run a container using darker if you install the Docker Engine on your operating system, and of course if you run some commands. So e.g. we want to run MIC called container on this machine, I already have Docker installed here for Mac. So to be able to run a MySQL container, I have to say Docker run minus E, my square root password, and then a port mapping, and then my sequel image followed by version. So let's see what this command actually does. Docker run means that I want to run a container using darker, right? Then minus e says, I want to create this environment variable and make it available in the container. Environment variable is basically just a key-value pair of data which is accessible in a specific environment, either in the current show or in a container, usually on a system level, right? That's the reason it's called basically environment variable. So in this case I want to set the root password for the root user because to be able to login into my sequel, we need to have the password for the root user. And in this case, the value for the password will be simply test. And then minus p means that I want to make a port mapping. A port is basically an identifier for an application in the context of a bigger system with multiple processes. So an operating system has a number of ports that you can connect to over the network. And each port basically identifies an application. And the application can receive connections on that port and handle them and get responses back and so on, right? So in this case I want to say, I want to map this port treaty O6 from my local machine. From the machine when I'm running this command, which is also known as the host to the port 3306 in the container. Now, in the container on this port, my secret process actually rise. For that reason. I chose this portrait, the O6 right on the container. So on an axis, the process through this port and the host port can be something different. So I can have at a different value here. And from our Spring Boot application, when I want to connect to this MySQL database, I have to specify this host port that I, that I sit here right. Now for simplicity, I can simply say that I want to use the same port, which is the default one for my school, so that we don't run into other problems. I mean, you can simply see if the port is not right because it will just fail on connecting to the database. So you can immediately change it to the right one. The next argument is minus d, and minus d stands for them on container. So when I run this command, the terminal will not wait for the container to be killed or terminated. It will simply start a container in the background. And the final argument of this long command is my sequel, followed by calcium, followed by latest. My sequel is basically the name of the image that we want to run. The images for the containers can be found if you're searching for my sequel Docker image. And you can see this website, Docker Hub, where you have basically all the images that you can get publicly, right? So they're going up is basically a public image repository. And this one is the official line. So if you are e.g. if you are running this command docker, pull my sequel. It will start to download this image on your local system right, from the remote repository. I already have this image. Download it, so I don't have to download it again. Now, what latest actually means here is the image version because the image can have multiple tags or right, or versions. So I'm currently using the latest, but you can also use an older version if you want 8031 or any, any other ones. So let's run this command. So as you can see, we got this error which says that the port is already allocated, probably because I have this container running, let's say docker ps tells us which containers are currently running. So e.g. I. Can actually say docker kill this container and this command will simply destroy the running container, which was created previously by me. So if I run docker ps now it says that I don't have any container running. And if I run the command that will start a container again, which of course would be a different container. In this case, I get back this very big ID, and this is the ID of the container is basically should be a unique ID that Docker generates for us. Now, if I run the Corp, yes, I can see that the container is running. I have this ID here which identifies the container is basically a shorter version of this one. Then I can see the image which is used by the container, followed by the first command which is being run when the container starts. And this is inside the image itself, so we cannot control this and the forest. Other important information around this container is created status and so on. Also the port mapping that we saw previously are also displayed here. So we have this container running. Now let's login on this container so that we can configure the MySQL database. So to login on this container, we just have to say docker exec minus IT, followed by the container ID, followed by batch. So i t means interactive terminal. I want to execute this command. Exact means I want to execute this command in an interactive mode on this container. And the command is simply Bash that I want to get shell access to these containers. So if I run this command, I can see that the shell actually changed. And it changed because now I'm basically executing commands in the container, right? So I'm not on the local host anymore. I'm on the container file system and on the container system basically e.g. if I'm running the ls command, I can see that I have a different set of files, right, compared to the one that I got before. Now of course, the thing that I'm interested in right here in this container is to access the lab. So to do that, I have to login on my screen. So I have to say my sequel minus U, which stands for User route, right surrounded login with a root user minus p and then Enter, now I have to enter the password for the root user, which is actually this one that I provided through this environment variable. So I can say test here, I just typed test and then Enter. And I can see that. And now I'm logged in on the my sequel database. So the first thing that I need to do here, because this is a fresh database. I have to say create database test. I want to create a new database which is called test and that command, now I have to use this database. So I have to say use test. And now I need to create a table inside this database. So I already have query which allows me to create this database, which is this one, right? So I integrate this table user entity, which has this primary key. And I did that is auto incremented. And then I got the fields which already are part of the user model in our Spring Boot application, right, so I'm going to just copy this command, paste it here, and then the query was executed successfully. I want to get some data from that new table. Of course I'm going to get zero results, but just to see if the table was created correctly, right? I got an empty set. So now the database is basically set up. There are no other things to do here will give the user Spring Boot app to actually add data in that database. 10. Configuring our Spring-Boot app to work with MySQL: So let's switch to intelligent idea to start configuring these pre-multiplication. Alright, so the first thing that we need to do is to of course import some dependencies because we don't have built-in support for data access in the Spring Boot starter web dependency. So we need to add the following two dependencies. For the moment, we're going to see if we need other ones. Along the way. We're going to search on the web for Spring Boot Data, JPA, Maven Central. So JPA stands for Java persistence API. And Spring Boot has a dedicated dependency which deals with any abstractions or are they actually the entire API that allows us to access data using Spring Boot. We're going to copy this dependency, Spring Boot starter Data JPA. And then we're going to also search for MySQL connector, Java, Maven Central. This is basically a dependency that allows us to connect to my SQL database. You basically need to have a connector for each database that you want to connect to. And they should be in the same repository. So still on, on my central. But this one is for my sequel and we need to, of course, important. I'm going to hit gradle sync using the shortcut. And of course we were going to wait for for Gradle to pick the dependencies up so we can start working on the project. Alright, so now we have the dependencies on, we need to do the following changes. So we're going to create a new package that we're going to call data. So this data package, I'm going to create one class that I'm going to call user entity. And this class is the one that we're going to, that we're going to use in order to send data to the database and get it back. So you may wonder, why don't we use the UserModel class for this? Well, because this class is part of the domain model that we use for communication with the rest controller. Or saw this, this schema is the one that we are getting from the user directly using Postman. So we need to decouple those two models, right? Because we may not necessarily have the exact same structure in a real application. From the front and from the client side, all the way up to the database women, we may have a different models right on this floor. So for that reason I'm creating a different one, which is going to basically be very similar to this one. So I'm going to basically copy it and paste it right here. I'm going to say user entity. This one is a little bit different because it needs to implement serializable interface, right? In real life. So the reason it needs to implement serializable is because this class will be passed to the database, right? It needs to match the columns on the table that we created. So as you probably saw right here, we got firstName, lastName, membership ID, creation time. So those fields are actually those ones, but of course, written with the underscore between the words, right? So they basically need to match the ones that we have in the table. And also we need to annotate this class with a very important annotation which is called entity, right? This class, which comes for Java, Persistence API, basically tells us that this class needs to be matched with table in our, in our database, right? We can also annotate fields with all kinds of annotations related to the entity class. So we can customize this class even more if we have a more complex scenario. But for this course we're not going to go into too many details on how to configure this class. We're just going to keep it simple for the moment to see how things connect end-to-end. And you can also explore more aspects in this area if you're interested. So we got the entity class. The second aspect that we need to create is the user repository. Now the user repository is basically an interface which extends credit repository of user entity followed by a string. So why do we have here, we have an interface called user repository, which is annotated with a repository in which actually extends crud repository. This interface which is part of Spring Boot, is basically the main abstraction for a data access which provides create, read, update, and delete operations. And we need to also provide here the objects on which we want to execute those operations with the database course. And also the primary key that we want to use when we execute the operations on those entities, right? So as you can see on this interface, we have save, save all fined by the exists by ID. So the operations that we can execute directly. So now that we have this user repository here, we can actually use it directly in our user service implementation. So we can inject it right here, user repository, we can store it as a field and we can also use it. E.g. in the getUser, we can say return user repository dot find by ID. Now we need to provide an ID. So we added this find by first-name metal here, which basically allow us to make a query in our database by using the firstName and right, and getting back a user entity. Now first, we have this small problem that we need to convert the user entity to user model. And for that, we're going to create a mapper writing a class that especially that is designed to convert from user entity to user model and back. But before going into that part, we're going to also use the user repository to add some data. So to add data in the database, we need to use the save method. And on the save method we need to provide, of course, a user entity, right? We're going to provide it right away once we have the mappers created. But let's also implement a delete the user methods. So we're going to say user repository delete by username, right? So we need another query right here. So to do this, we also need to create a new method, delete by first name. So we're going to say here, delete by first-name, adding the username. And also we need to remove these user map. Actually we don't need it anymore. And also let's create that mapper class that I mentioned previously. So we're going to create a new package called Mappers. So a mapper is basically just a class, let's say user entity mapper that allows us to convert from one type to another. So let's actually create an interface first called entity mapper. And this interface, let's say has to generate parameters and it has two methods. So nFET mapper basically allows us to convert from this type to this type. So we're going to return, you say map, and then we're going to take entity as a t, as a parameter. And we also provide the reverse operation where we convert, where we get a t from a you write. So let's say this is the abstraction that we're going to use. And the user entity mapper will implement entity mapper of user entity and user model. Okay? So if we implement those methods, we can see that the first one will get us a user model from a user entity. The reverse map will get us a user entity from a user model. So we're going to also make this class a component, right? Because we use it as a tool. In this case, we're able to simply return user model of user, actually entity dot FirstName, LastName, membership ID, and creation time, of course, with a new and of course this is a little bit redundant in this case, but in a real scenario you're, you're going to have those models drifted. So you need to add some changes right here, right? Some class will not have a specific parameter, the other one will have it. So you need to make some conversions right here to make some sanitization sometimes. So I'm doing this more like an exercise to kind of know that this may and will happen in a real scenario. Now with this user entity mapper, we're going to inject it on the user service implementation. But of course we're going to use the interface, right, to have things decoupled. So entity mapper, where you have to use the entity mapper, which is this one, let's say user, let's say entity mapper to be, to be sure we got it as a field. And right here where we find by first-name, right? So when we get the user entity back, we're going to say map because we have the entity and we want to get back the user model. Okay? So this is what we want. Now, when we want to save a use an entity, what you want to say entity mapper dot reverse map. And we're going to pass the user, right? We pass the user model, the reverse map retrieves a user entity that is used for the same operation. So this is basically the way we would do it. Of course, we don't have error handling, we don't have exception management in this code. It's basically simple as possible so you can get the main idea. We can also make those final. And the last thing that we actually need in this application to be able to connect to the database is to add here on the application yaml configuration for the database, right? So for it, so basically endpoint the port and this configuration is the following, right? So I just, I just pasted this configuration from a file. The restored previously is basically a spring data source configuration where we pass the URL, right, which includes the endpoint a port. This is the host port, very important. So the first one in this command right here, right? So this one, the first one, the host port, followed by the database name right here we got the username and password. So with those details, we can connect to the database. Of course, there are other ones in production grade applications, you need to specify the all kinds of connection pool setups and lots of other details. But to keep the example, this is the minimal configuration that we need to provide here to be able to connect to the database. So let's run this application in debug mode to see if it works. Most probably it won't because it never works in the first try. So as you can see here. We have no class. They found Java x, x xml. Very weird exception, right? Usually when we have a class not found, a dependency is probably broken. And in this case we're basically talking about this dependency, J XB minus API. Not really sure what's the problem. Found that on the internet as being a common issue. So we're going to add it here to see how it works, right? So now it says that we have no identifier specified for entity. So this means that we need to add a identifier for that user entity. Identifier is basically a field annotated with the ID. So in our case, we have to add this ID annotation, of course, on the primary key. In our case, we don't necessarily want to add, let's say, an integer ID right here might not be useful. Let's say we can try it out it firstName and see, and see how it works, right? So as you can see, the applications started. Now let's try to add a user in our application. So we're going to go right here on the safe metal on the Add User method in Rio to use Postman to add a user, right? Let's see what it says. We hit F9, no exception, we get back to zero too. So it means that no exception from the application, right? So we may hit select from user entity. We can see that the user is on the database, which is of course really great. I mean, we managed to add data in our database. Let's also add a different user. So it seems to work as we expect. Now let's try to get some data back. So this one, it looks like it works. If I if I'm searching for Daniel, seems to work pretty fine, which is really great. I mean, yeah, let's also delete a user. Yeah, So on this operations looks like we have a problem, looks like we have an error. So what it says, it says that no entity manager with actual transaction available for current thread cannot reliably process to remove coal, right? So this error tells us that we don't have this transactional annotation on the delete method. And this is very important key point that I wanted to touch base upon because usually delete operation is very sensitive. I mean, you can actually run it from multiple threads, from multiple, let's say execution flows because you may run into concurrency issues. So you can have actually inconsistency issues, race conditions. To solve those in Spring Boot, you need to use this transactional annotation, which basically tells us that all the operations in this method related of course to the user repository will be executed in a transaction which is basically an atomic operation on the database, which can either succeed or fail, but it cannot be executed partial, right? So for that reason, we need to have this transactional annotation on our method so we can have the delete operation executed properly write. So let's also add a new user so we can see that it works. I deleted the markets user to see if this works. If I delete, let's say the Daniel user, right? Looks like we got 204, okay, and the user is deleted from our database. So this is how it works. I'm going to let you fix this problem with the user entities. So just try it out, see if you can use, you can find in the documentation and annotation that will allow us to generate an ID. So in other words, you can, you can try it out to grab this ID field here on the table to add it as a field only user entity and see if it works. See if we can generate it automatically from our Spring Boot application and not from the table. So this is basically a way you can play around and covered things. See if it works, see if it doesn't work. See, investigate why. This is the way you can, you can learn basically all those things. So this is basically a very simple way to access a database like an end-to-end without too many complex aspects on it. As I mentioned initially, because this landscape of databases and flavors is actually huge, you may end up running into all kinds of issues with dependencies, with versions, with classes which are not present as we saw previously. So expect this flow to not be flawless, want to not be something easy to achieve. So with that, we'll jump into the next lecture.