Transcript for:
Developing a Springboard Application Using Microservices Architecture

in this video you're going to learn how to develop a springboard application using microservices architecture this is going to be a highly practical tutorial so to follow along i expect you to have at least a basic understanding about spring boot and basic understanding of what microservices architecture is and why you use them so we'll be building a simple online shop application using microservices architectural patterns using mainly springboot and the latest spring cloud technologies so we're going to cover all the interesting and important architectural patterns like service discovery centralized configuration distributed tracing even driven architecture centralized logging and much more if you are not aware of what are these fancy terms don't worry we will cover this in the tutorial so before going ahead and implementing our microservices let's take a moment to understand what is spring cloud spring cloud is a project under the spring projects ecosystem so it's another project like spring boot spring data spring security or any other spring project but it mainly concentrates on helping us to build the reliable and robust micro services it provides us a common set of design patterns which are implemented already like the configuration management service discovery circuit breakers so and there are many other patterns which are implemented into the spring cloud project we'll have a look at it in depth in this tutorial you don't need to worry about that we're going to use spring cloud to mainly develop the micro services that's what you need to know as you understood what is spring cloud now let's go ahead and let's go ahead and check what are the different services we're going to build in this tutorial so the first service we're going to build is going to be a product service so this service provides us api to create and view products in our application and it also acts like a product catalog where we can view all the products inside our inside our application so the next service is going to be an order service where we can order the products which are available in the app and uh after that we're also going to have an inventory service where the order service can check if the product is in stock or not before submitting the order and lastly we're also going to have a notification service where we can send email notifications after the order is placed successfully and out of these four services we are going to mainly have the ordered service inventory service and the notification service talk to each other we mainly have the in synchronous and as well as the synchronous communication as part of these three services so now let's go ahead and check the overall solution architecture of our project all right so this is how the solution architecture diagram looks like so mainly we are going to first look at the services we are developing so we have the product service which is talking to a mongodb and an order service which is talking to the mysql database and the inventory service is also talking to the mysql database to store all the inventory information and we have the notification service which is like a stateless service which it does not have any database but it is responsible to just send out notifications to the users if you are talking about a microservice architecture you cannot call it as a microservice architecture if the services are not talking with each other right so here the order service is talking to the inventory service so whenever the whenever order is being placed we'll first check whether the inventory is available or not by making a synchronous communication and after that we are also going to send out the notification once the order is being placed successfully so for that we are going to make an asynchronous communication with the notification service if you are not sure what is synchronous and asynchronous communication don't worry we will also cover this in detail in the in this tutorial coming to the asynchronous communication we are going to make use of two softwares like uh we will call it as message queues uh so we are going to see how to deal with both the popular message queues in the market like the rabbit mq as well as kafka so we will see how to configure both of these um message queues to communicate to do the asynchronous communication and coming to the outside world we have the surrounding services which are which enable the microservice architecture we have the api gateway which acts like a gateway to send the request from the user to different services so for example if i am a user and i want to communicate with the product service i don't want to uh give the host name or the ip address of the product service to communicate with it right so the api gateway acts as like a gatekeeper to send out the requests to different services we like is also so our applications is also being secured using the authorization server called as key clock we'll also have a look at it in the detail and other than that we also have different services like you take uh the config server we're also going to use vault to store the secrets we're going to use zipkin to do the distributor tracing and also to do the customer to do the logging to do the centralized logging you're also going to use elasticsearch logstash and kibana and again don't wait don't be overwhelmed with all these details we will have a look at each of them in detail in this tutorial all right so if you'll have a look at the logical architecture of each of the services we have a controller service and repository layer for each of the services so in the controller layer we will be receiving the http request from the from the clients and from there the business logic is being executed on the service layer and in some of the services we are also going to communicate with a message queue so that's why we have this message queue communication and mainly in the order service we are going to make use of the message queue and also the notification service and after that we are also going to store the information in the database so for that we are also going to maintain a repository layer which mainly talks to the database so we have a postgres and also the mongodb database so both of them will follow the same pattern we'll have a repository which talks to the database this is how almost all the services are being structured so we'll follow the same process for all the services we have all right so let's start coding so first we are going to develop the product service for that i am opening this website start.spring.io where you can generate the initial version of the code so for that i am going to select this latest springboard version as of creating this tutorial that is 2.6.4 and for the group id i'm going to provide the text from programming techie and the artifact is going to be product service and the description is going to be also product service you can you can enter whatever description you like i'm going to use java 17 and for the dependencies i'm going to first make use of lombok to reduce the boilerplate code and i also need access to spring web so that we are going to make use where as we are building a rest api so i am going to use spring web and lastly i am also going to add spring data mongodb as the product service is going to communicate with a mongodb database this depend after adding all these dependencies i'm going to click on generate and the product service is going to be downloaded to your machine and this so i'm going to first unzip and open it on my favorite ide the first thing we have to do is to configure the mongodb uri inside the application.properties file i'm going to give the database name as product service if you want a detailed explanation on how to configure spring boot with mongodb have a look at the springboot mongodb playlist in my channel you can also find this in the description section after that we have to create our domain model which is the product class so let's create a package called as model and inside the package i am going to create a class called as product to define this product as a mongodb document i am going to add the document annotation to the top of the product class and i'm also going to add the lombok annotations to generate the getter setter methods and the constructors inside the class i'm going to create the required fields which are id name description and price and to the field id i am going to add the id annotation from spring data to specify that this is a unique identifier for our product and to store this product inside the database we have to create a spring data repository for that i am going to create a package called as repository and inside this package i am going to create an interface called as product repository and i am going to extend this interface with the spring data mongodb's repository interface and i'm going to pass in the generic argument as product and for the identifier i'm going to pass a string as the the second generic argument because this is the type of the id field in our product class now it's time to create the controller class so for that i am going to create a package called as controller and inside the package i am going to create a class called as product controller as we are exposing a rest api we have to add the rest controller annotation to the top of this class and also the request mapping annotation with value slash api slash product so now let's create the api to create the products so for that i'm going to create a method called as public void create product and this method has this create some products we are going to send a post request for this method so i am going to add the post mapping annotation and as a response we are going to type in response status and we are going to send out the http status as status as created so i am going to select http status created right and as a request body we are going to receive the product information for that we are going to create a new class called as product request right so this is going to act as a dto so i'm going to create this class inside a new package called as dto and also this class is going to have a long block annotation to create the getters and setters class data i am going to use the builder annotation to create the builder method and also the aulux constructor and the nox constructor so inside the product request we're going to mainly have three fields similar to what we have in product so i'm just going to copy paste this three fields inside the product request all right so we'll have name description and as well as the price so now we have the product request and let's go back to the product controller and we are receiving the product request as the request body and to actually create the product we have to do the processing like the processing of the business logic in the service layer you can't do it on the controller layer so for that i'm going to create a new package called as service and in here i'm going to create a new class called as product service so as this is a service we are going to add a spring boot annotation called service and we are also going to create a new method inside here called as public void create product which takes in the product request has the method parameter and inside here we have to first map the product request to the product model so for that i'm going to create a variable of type product so let's also import the product from the package from the model package and create a reference variable called product and i'm going to make use of product dot builder method so to build the product object so that i'm going to type in the name as product request dot get name and the description as product request dot get description lastly the price as product request dot get price and once we have set up all these information i'm going to call the build method so that it will create the object of type product with all the requested details and lastly we have to we have created so now we've created the instance of the product object now we have to save this into the database so for that we need to access the product repository so i'm going to inject product repository into a service class the product service class mainly i'm going to make use of constructor injection so i'm going to type in private final product repository and after i have added the declaration of product repository you can see that intellij is already complaining that the product repository is not initialized so i'm going to add the constructor parameter here so you can see the constructor is automatically generated so instead of doing this manually for all the classes what i can do is i can just remove this constructor which is generated and i can add the annotation required args constructor from lombok so what this will do is at the compile time it will create the constructor for us which all the required constructor arguments right so this is something handy which we have which you can use so now i'm going to um save this product inside the database by typing product repository dot save product so after doing that the product will be saved successfully to the database we can also add some logs here by making use of slf 4j so i'm going to type in slf 4j so this is coming from lombok and to set to add the logs i'm just going to create a new line under the save method i'm just going to type in log dot info product is saved right so you also have to give the information which product is saved right so maybe a product id would be useful so for that instead of concatenating the product id like this product.getid something like this using slf 4j we can actually make use of a placeholder so i'm just going to add a placeholder like a double curly brace and after that i'm just going to type in comma and add product dot get id so what this will do is it will dynamically it will get the id of the product and it will uh replace it on the placeholder so when you execute this you will get product followed by the product id is saved right so we have the create product method so now let's also create the so now let's call this create product method from the product controller so as we did similarly for the product service we also have to inject the product service inside the product controller so for that i'm going to type in again private final product service and to inject product service i am going to make use of again the required args constructor from lombok so now we have the product service i'm just going to call inside the create product method product service dot create product and i'm going to pass in the product request so this will create the end point to create the products so now i'm going to create another endpoint to retrieve all the products so for that i'm going to create another dto called as product response product response and similar to what we did for the product request so i'm just going to copy everything we have inside all the annotations we have defined for product request called product response and inside the product response we are also going to send the id in addition to the name description and price so for that i'm just going to copy everything we have inside the the product model class so i'm just going to type in product response so now you may be confused why i have created a separate class called as product response right so maybe why can't we directly use the product class from the model package instead of creating the product response this is because it's a good practice to separate your model entities and the dtos so ideally you should not expose your model entities to the outside world because if in the future in this product class if i've added some other two fields which are like necessary for the business model we should not expose these two fields which are not necessary outside to the outside world right so for this reason it's a good practice to separate your model entities and also your data transfer objects so in this case the product request and product response acts as the data transfer object so now i've created the product response so to create the get endpoint so get all products endpoint i'm going to first type in a get mapping annotation and this response status annotation is going to send a response status of http status okay right and now i'm going to type in public list of product response and i'm going to call it as get all products and i'm going to import this list class from java util package and now i'm going to create a method inside product service to get all the products so i'm going to call in product service dot get all products so i'm going to create this method as this is not existing yet inside the product service so this get all products should return a list of product response so i'm also going to import this list from java.util package again quickly and in here i'm going to type in product repository dot find all because i want to first read all the products inside the database so i'm going to store it inside a variable called as products and now i have to map this product this product class into a product response class right so for that i'm going to type in products dot stream dot map i'm going to make use of java 8 streams and the map function and i'm going to map each product into a product response object so for that i'm going to create a new method called as map to product response i'm going to create a new method inside the product service so this is not should not return an object but should return a product response right so here i'm going to create a object for product response using the builder method so i'm going to select response.builder.build and as part of the builder i'm going to provide the id as um you know what we don't have the product as an input argument so let me add the product as the input argument here to the map to product response method so now we have the product so i can just map the id of the product to the id of the product response by typing in product dot get id and again name as product dot let name so let me just scroll down to make it visible clearly so again we have the description so i'm going to type in product dot get description followed by the price so i'm going to type in product dot get price so now we are creating the object of product response and returning it back to the forget all products method and in here intellij is suggesting some changes here so as we are using a method inside the class we can actually make use of the method reference instead of lambda so i'm just going to select replace lambda with method reference and now after after we mapped it we are going to collect it into a list so i'm going to call to list method and finally i'm going to return this list back to the controller so we have the get all products which is returning a list of product responses if a list of product response objects so now i'm going back to the product controller and i'm going to add a written statement here all right so now we have both the create product and the get all products endpoint implemented so now let's start the application and check whether the application is going to start without any errors or not all right so you can see that we are able to start the application on the port 8080 without any problems so now let's quickly go ahead and test whether our application our rest api is working correctly or not so i'm going to open postman so here i prepared a post request for the url http localhost aba localhost 8080 api slash product so this is going to be a post request uh so for that i'm going to provide a request body draw in the type of raw json and here i'm going to create a request body name as iphone 13 description has iphone 13 and price as maybe 1200 right so i'm going to send this request and we can see that we've got 201 created response back from the our application now i'm going to create i'm going to copy this url and i'm going to create a new tab and paste in this url and now i'm going to send a get response get request to our api and you can see that we received the product which we have created in the previous step so our product service is working correctly but we are doing this testing manually the ideal situation would be to have some automated tests in the project so let's go ahead and write some automatic tests for our product service next so to be able to write tests for our product service application we can open the package source test and under java we have the test product service application test which is auto generated by the spring initializer for us so we are going to write the test in this class but before going ahead and writing the test we are mainly interested to write integration tests for this product service test right so we are not going to write unit test but we are going to create an integration test where we will spin up the application context the whole application and we will test whether the post api and the get api is working or not so before going ahead and writing our tests i'm going to first install a library called as test containers called as test containers in our project so if you are not aware of what test containers library this is a java library that supports us to write um junit tests by providing some throwaway instances of common software we need like databases web browsers for selenium and rabbitmq message queues and so on and so forth whatever external infrastructure we will be relying on we can provide we can use that as external infrastructure software as docker containers and we can run integration tests in our in our project right so some examples are you can test the data access layer integration tests using the docker instances of mysql postgres or any other database and you can also use the docker containers for message queues web servers and also this can be used in the ui and acceptance using selenium so it provides many different uh docker containers so that we can use this in our tests so that's why we have the name test containers so if you have a look at the modules which are supported you can see that it has different databases elasticsearch container gcloud module engines module kafka containers so on and so forth we have lot of modules which are available as of now in our unit in our in our tests in our integration test we want to have a container for mongodb so for that i'm just going to click on the databases and select the mongodb module and here you can see the documentation like the usage example how we can use this mongodb container in our tests right so before we go ahead and use this mongodb container we have to first install test containers in our project right so for that i'm going to click on home and i'm just going to scroll down until i find the section maven dependencies so if you want to install the test containers um individually you can just click on maven and copy the whole dependency so you can use this particular dependency the other thing you can do is you can have if you want to have multiple test container dependencies right we can if you want to have one test container dependency for mongodb one for kafka and one for i don't know any other module it's a good thing to have a bill of materials something called as a bill of materials where you can just provide the version as in one place and all the dependencies all the other dependencies you use for the test containers will take the same version i'm just going to copy this particular section and i'm going to open my form.xml and i'm going to paste this particular code above the build section right inside the dependency management section and i'm just going to load the maven changes all right so once this is done now i can install the mongodb container in our application in our project so for that i'm just going to go back to the test containers website and i'm going to click on modules databases and mongodb module and here i'm just going to scroll down until i find adding this module to your project dependencies section i'm going to click on maven and click on copy to go back to my palm.xml and under the springboard started test dependency i'm just going to paste in the mongodb test container dependency and again i'm going to load the changes so once this dependency is downloaded to your machine i can remove the version because as i'm already i'm already defining the version inside the dependencies management for the test containers bill of materials i don't need to explicitly create the version one more time inside the dependencies section right so i'm just going to again reload the changes so in this way if i want to no matter how many modules i use for the test containers i can just define the version only in one place here inside the test containers bill of materials right so this is the advantage of using the bill of materials inside the dependency management section and apart from this as we are using junit 5 to write the tests we also need to add the jn85 supporting module for test containers so for that i am going to open again the test containers website documentation website and i am going to click on the section test framework integration and go to junit 5 and in here all the way down in the adding test containers to junit 5 section i'm going to click on maven and i'm going to copy this particular junit jupiter dependency one more time and going back to the form.xml i'm just going to paste this below the mongodb dependency and similarly i'm just also going to remove the version tag from the junit jupiter disk container dependency and this i'm going to load this moving changes so now let's go ahead to the product service application test class and start writing the integration test for our product service so to get started i'm going to add the mongol so to get started the first thing i'm going to do is to add the test containers annotation on top of the class so that jnet5 understands that we are going to use test containers to run this particular test and after that i have to define the mongodb container inside our tests right so for that i can type in mongodb container and create an object for the class mongodb container and to this mongodb container you can see that this mongodb container class is deprecated because the noaa constructor we cannot use the noaa constructor anymore we have to manually specify the version of the mongodb we want to use so for the augment constructor we have to provide the docker image name for whatever software you want to use so i'm going to provide the docker image name as and i'm going to provide the tag as 4.4.2 right so this is the version i want to use for this test so i'm going to add another annotation on top of this declaration called as container so that janet 5 will understand that this is a mongodb container and i'm also going to add the static declaration because i want to statically add statically access this particular mongodb container and fetch the url of the mongodb database uh uri right so because as we are going to use this you know we need to set the uri of this mongodb container in our test properties so let's do that by first adding a method called as static void set properties and this method is going to take a [Music] class an object of type dynamic property registry and inside this method i'm going to type in registry dynamic property registry dot add and i'm going to type in spring dot dot data dot mongodb dot uri and i'm going to here pass in for passing the mongodb dot mongodb container get get replica set url variable so in this way at the start a time of starting the integration test first of all the test will start the mongodb container by taking by downloading the 4.4.2 image and then after starting the container it will get the replica set url and add it to the spring data mongodb uri property dynamically at the time of creating the test right because if you remember if you if you have a look at our source main resources folder we have defined the spring data mongodb uri manually in the application.properties file right but as here we are doing an integration test we also have to provide the spring data mongodb uri dynamically at the time of creating the test because as we are not using the local database local mongodb database we are using a mongodb docker container we have to provide the spring data to be ui property dynamically so to be able to provide this property dynamically we also have to add another annotation on top of this set properties method called as dynamic property source which will add this property to our spring context dynamically at the time of running the test right so after adding all these configuration we can go ahead and start writing our integration test so the first test i'm going to create is for the product controller create product endpoint right i want to send a send a product object a product request object and i expect the response status to be created right so that's what i expect whenever i send a product request object i expect the status to be created so let's test this behavior i'm going to open product service application test and this i'm going to change this context loads test to create should create product and to be able to make a request from our test from our integration test i'm going to make use of something called as a mock mvc some object called as mock mvc which will provide us a mocked servlet environment where we can call the product our controllers where we can call our controller endpoints and we can receive a response as per the response which is defined inside the controllers right if you want a refresher on the testing concept of spring boot testing concepts you can have a look at this spring boot testing tutorial crash course i have on my youtube channel it will provide a nice overview about what is the what are all the aspects you need to know to be able to write uh to be able to write tests using springboard right so for now i'm going to make use of the mock mvc object to make requests to the product controller so for that i'm just going to auto wire the mock mvc object into our test right and you can see that we are getting an error could not auto wire no beans of mock mvc type font because we have to auto we have to auto configure the mock mvc in our test so for that i'm just going to add an annotation called as auto configure mock mvc now you can see that the error is gone that means our mock mvc is auto configured and then now we can auto wire nokia mvc in our test right so now i'm going to make use of mock mvc object and i'm going to type in mock mvc.perform this perform object this perform method will take in a request builder and an object of type request builder so for that i'm going to type in mock mvc request builders dot post as i want to create as i want to do a post request i'm choosing the post method and in here i'm going to just type in slash api slash product because this is the root url of the product controller i'm just going to copy this particular url endpoint and provide it as the provided as the url template and after that we also have to provide a request body of type json so for that i'm just going to type in dot content type as media type application json and i'm going to provide content as a string right i want to provide a content as a string so for that first we have to create the request body of type product request because as we are receiving as we are taking a request body of type product request first of all i have to create an object of type product request for that i'm just going to create a method called as get product request i'm going to create a method inside the test class and in here i'm just going to return product request dot builder dot name is going to be iphone 13 and description is going to be also iphone 13 and the price is going to be big decimal dot value of 1200 maybe right and i'm going to finally call the build method to be able to construct an object of type product request and let me also just format this correctly and also this method should return an object of type product request but not void all right so now we have the product request object ready so i'm just going to also store this particular return type return return object inside a local variable called product request and now i want to send the product request object as the request body but this content method will only take the object of type string so now what i have to do is i have to convert this product request object into a string right so for that i'm going to make use of something called as an object mapper private object mapper from jackson data bind package so what this object mapper will do is it will convert a pojo object to json and json to pojo object it will help us to convert this particular objects to json and vice versa so i'm going to make use of object mapper and i'm going to type in object mapper dot write value as string and i'm just going to pass in the product request and this write value as string is going to throw an exception so i'm just going to add exception to the method signature and finally i'm going to store this written object into a local variable called as product request string i'm going to provide this now into the content method and finally i'm just going to also define another exception from the perform method all right so now we have provided all the required input for calling the create product api now the next thing i want to do is i want to verify whether the request is going to be the response status is going to be 201 created or not right so for that i'm just going to type enter and type and expect and i'm going to type in status this is going to be a static method which is coming from mock mvc result matchers i'm going to select i'm going to import the mock mvc results matchers.status method and after the status method i'm going to type in is created right so in this way mock mvc will make a call to the api product create product endpoint by providing the product request string as a request object and it will expect whether the status is created or not right so let's go ahead and run this particular test whether it's working correctly or not i'm just going to run the product application service test now what you're going to observe your very first time here is the test containers is going to if it's not already available it's going to pull the mongodb image from the docker container registry right so it will take some time as it needs to first pull the docker image and then start running the test and here you can see that the test has successfully created the mongodb container and then started running the test against this mongodb container right so you go to the should create product you can see that it has triggered the product service product of this particular id is saved to the database and let's do one verification whether the data is really saved or not i'm just going to auto wire the product repository right and i'm going to verify product repository dot find all dot size is going to be one right because we have inserted one product we expect that we should have one product inside the repository so for that i'm just going to type in assertions dot asset true and i'm going to add this product repository find all size method call inside the asset true method and just i'm going to verify whether the size is going to be 1. right so after making sure that the create product endpoint is triggered successfully we are also making another assertion that the product repository contains the product or not right and here you can see that the intellij is suggesting us we can simplify this assertion i'm just going to use assert equals here so in this way we can have the expected value and the actual value as the second parameter so now let's make sure that we run the test again to verify whether everything is working fine yes indeed so the test is working fine so in this way we can have some automated tests in our micro service so that we are not always relying on the manual test we can also have some automated tests in our micro service so i'm going to give an exercise or a homework to implement also the test for the get product endpoint i have created the test for the create product now it's your turn to implement the integration test for the get product as this is going to be a micro service project a micro service course i'm not going to go in depth about the testing part i've just provided you a hint on how to write the integration test for the micro services now you can go ahead and implement the required test for the other end points by yourself i'm also not going to implement the test for the other services like order service and the inventory service but if you are stuck when writing the test you can find the test inside the github repository so i'm going to give an exercise or a homework to implement also the test for the get product endpoint i have created the test for the create product now it's your turn to implement the integration test for the get product as this is going to be a micro service project a micro service course i'm not going to go in depth about the testing part i've just provided you a hint on how to write the integration test for the micro services now you can go ahead and implement the required test for the other endpoints by yourself i'm also not going to implement the test for the other services like order service and the inventory service but if you are stuck when writing the test you can find the test inside the github repository so you can refer whenever you want and whenever you are struck while writing the integration test all right so now it's time to create our second micro service that is the order service for that i've opened the website star.spring.io and here i'm going to go ahead and create another microservice our order service so i'm going to type in inside the group id com programming techie and artifact is going to be correct service and the name is also going to be order service and i'm going to select java 17 15 as the latest stable java version and coming to the dependencies i am going to add the dependency for lombok and also for spring web and as we are going to use mysql database for the order service i'm going to scroll a scroll down and add the dependency for spring data jpa and lastly i'm also going to add the dependency for mysql jdbc driver once you have all these dependencies you can just click on the generate button as we are going to create more and more services we have to maintain these services we have to run this services parallely by opening multiple triple id windows so that will create a lot of load on your machine right like so to get around that what we can do is we can maintain all these services inside one inside one project so for that i'm just going to create a new folder or last micro services parent something like this and i'm going to move this product service and as well as the order service into the parent project so in this way i just need to open the micro services project microservices parent folder inside intellij and i will have both these projects inside one id alright so now open intellij and i'm going to click on open and select the micro services parent folder which i've created before click on ok and now you can see that we are able to access both the product service and as well as the order service inside one folder so now let's open the order service and let's have a look at the palm dot xml we have the spring the boot starter data jpa and spring boot starter web and two dependencies for the and the dependency for the mysql jdbc driver lombok and the starter test dependency right so now first what i'm going to do is i'm going to create a package called as controller and i'm also going to create some other packages so that we will have this structure called as controller service repository and the dto right like what we how we did for the product service in this way right so let me create the package for repository another package for tto and lastly we need another package for model right and for the order service the model we are going to maintain in our database now mysql database is going to be to store the orders so for that i'm just going to create a new class inside model package called as order and this class is going to be a jpa entity so for that i'm just going to add the entity annotation from javax persistence package and i'm also going to name this table has t underscore orders and i'm going to add a getter and setter annotation followed by noah's constructor and all logs constructor for the order class and coming to the fields inside the order class i'm going to add a primary key as id with data type as long and i'm going to add the id annotation from jpa and also the generated value annotation with strategy as generation type dot auto and i'm going to also create a string variable and i'm also going to create a field called as order number [Applause] and followed by i'm going to create a list of order line items right so each order contains some items inside the order so each each order contains some outdoor line items so i'm going to create the order line items list and we have to also create this order line items object class we have to create this order line items class inside the model package so i'm just going to create this class inside the model package and this order line items is going to again have an entity annotation from jpa this is going to also be a table so i'm just going to add the table name as order t underscore order underscore line underscore items so similarly to order class i'm just going to add the getter setter holologs and the nox constructor from lombok and i'm going to also add the id of type long and i'm going to add the id annotation from jpa followed by the generated generated value annotation with strategy as generation type identity and the next field i'm going to create is going to be order number of type string and after that we are going to have a list of order items inside the order so for that i'm just going to create a list of order line items i'm going to call this as orderline items list i'm just going to import this list class from java.util package and we have this order line items and let me create this order line items class inside the model package so this order line items class is again going to have the the entity annotation from jpa the table annotation and i'm going to name this table as t underscore order underscore line underscore items and i'm going to add the getter annotation and setter annotation from lombok followed by all logs constructor and the nuage constructor so inside the order line items i'm going to again have a primary key called id which is of type long and i'm going to add the id annotation from jpa as this is a primary key and i'm going to add the generated value annotation with the strategy as generation type dot identity because then it will be as this will be auto incremented the primary key for each value for each new record which we are saving to the database and next in the order line items we are going to have we are going to maintain the sku code so i am going to type in the field of type string called skew code followed by the field price which is of type big decimal and lastly we will maintain the field called as quantity which is of type integer we have our basic model created but we are we did not defined any relationship between the order table and the order entity and the order line items entity as this is going to be as the order and the order line items is going to have uh one too many relationships i'm just going to add one two mini annotation which cascade as cascade type bot all so now we are done with the model part so let's go ahead and create the controller and the end point which will help us to take create orders inside the order service so for that i'm just going to create a class called as order controller i'm going to add the rest controller annotation on top of this class and inside the request mapping this is going to take the value slash api slash order and inside the class i'm going to create a post mapping and i'm going to call the method as called public string place order and this method is going to just return a string called as order placed successfully by default and this place order method is going to take a request body of type order request and we don't have this order request class created yet so i'm just going to create this class called as order request inside the dto package and here i'm going to add a data annotation so that we will have the getters and setters and all the default boilerplate methods for the class and i'm also going to add the all logs constructor followed by the nox constructor and this order request is going to have a list of order line items dto class so this is going to be order line items dto and this order line item studio is still not existing in our we have to create this order line item studio so let's go ahead and create this order line itemstto class quickly inside the dto package and i'm going to just quickly copy and paste the whole annotations from the order request class and paste it on top of the orderline items tto class and for the orderline items tto i'm just going to open the orderline items class and just i'm going to copy everything there is inside the order line items class and paste it inside the order line item studio because we'll basically have the same fields inside the online item studio also and coming back to the order request i have to fix the compilation errors by first importing the list class from java util package into the order request class and now the next thing is to create a service so that it will create the orders inside the database so for that i'm just going to create a new class inside the service called as order service and this order service is going to have a service annotation on top of the class and in this class i'm going to first create i'm going to create a method called as place order and this place order method is going to take a take the order request which is coming in from the from the controller and from this order request i now have to create an object of type order so for that i'm just going to create new order object of type order and i'm going to say order dot set order number as uid dot random uuid i'm going to provide some random view id as the order number and now i have to map the order line items which is coming in from the order request as orderline items dto to the order line items inside the right so for that i'm just going to say order request dot get order line items dot stream and i'm going to call the map function so that i can map the object of orderline itemcto to orderline items so i'm going to type in here orderline items d2o and i'm going to map to create a method called as map2do and provide the orderline item studio as the method parameter and i'm going to quickly create this method called as map2do inside the order service and instead of returning an object from this method i'm going to return i'm going to return an object of type order line items and inside this method i'm going to create an object of type order line items and i'm going to just map all the fields which we have right and finally i'm just going to return the order line items back to the place order class and inside this map method you can see that we can replace this lambda with a method reference so i'm just going to replace it with a method reference and i'm going to convert this to a list of order line items by using the dot to list terminal operator i am going to introduce a new local variable called as order line items and finally i'm going to set this order line items to the order by typing order dot set order line items and providing order line items and now we have constructed an object of type order and what we have to do is to save this order inside the database so to save this order to the database we need to create a repository for that i'm going to right click and go to new class and i'm going to create a new interface called as order repository and this order repository is going to extend jpa repository of type order and the primary key is going to be of type long right so now once we have the order repository i can just inject this order repository into into the order service so i'm just going to type in private final order repository and as this is going to be a constructor injection i have to create a constructor parameter for that instead of creating the constructor manually i can add the required args constructor annotation from lombok so then it will create a constructor automatically based on the parameters during the compile time and i'm going to use this order repository inside the place order method and i'm going to type order repository dot save right so in this way we are receiving the order request from the from the client to the controller and the controller is passing the order request to the order service and inside the order service we are mapping this order request to an order object and finally saving this order into the order repository so now let's go back to the order controller class and now we have to call this ordered service from the order controller right so for that i'm just going to add the inject this order service by typing private final order service and i'm going to also add the required args constructor so that will have a constructor parameter for order service and inside the place order method of the controller i'm going to type in orderservice.placeorder order request right so whenever the user places the order it will be saved to the database and it will return the text called as order placed successfully and i forgot to add the response status and the response status is going to be http status but created so let's test whether this is working or not so i'm just going to open order service application and i'm going to run this order service application and you can see that we are yeah we are getting an error because of course we did not define the data source attributes inside the application.properties we did not define the database url and all the related properties inside the inside the application.properties file so i'm going to do that now so inside the application.properties file i'm just going to type in spring datasource.driver class name this is going to be com.mysql.jdbc.driver right and spring.data is going to be my jdbc url so just i'm going to type in jdbc mysql localhost 3306 this is going to be my port on which loca mysql server is running and i'm going to call the schema as order service right and i'm going to type in spring.datasource.username as root spring.datasource.password as mysql gpa.hibernate.ddl auto is going to be update and spring dot data source and lastly i'm also going to add the server dot port as eight zero eight one as on eight zero eight zero we are running the product service we want to run the order service on port eight zero eight one right so let's go ahead and start the application now and you can see that the application is started successfully but we see a warning that the class mysql jdbc driver is deprecated and the new class is com my sequel cj jdbc driver so i'm going to use this driver instead of the other one so i'm just going to paste this inside the application properties and i'm just going to restart the application one more time and now you can see that the application is started on port 88081 so now it's time to test whether the test whether the endpoint is working correctly or not so i'm just going to open the postman client i'm going to open the postman client and then now i'm going to type http localhost 8081 slash api slash order and i'm going to send a request body of type json and in this request body i'm going to type the and in this request body i'm going to send the fields for the order request so it's going to be an array of orderline items dto right so i'm just going to create an order line items gto array and inside that array i'm going to first send the skew code price and quantity right and instead of order line items ddo it should be order line items dto list the name of the key value of the json it's going to be order line items list and inside the object i'm going to create a skew code price and quantity right so i'm just going to create an object for sku code and an object for price and is going to be 1200 and quantity is going to be one right and for the skew code and for this q code i'm just going to type in iphone underscore 13 and i'm going to just click on 13 and instead of and i've made a mistake here it should be localhost 8081 but not 8082 and also i have to send a post request to the order service so now with this request body if i click on send i should receive a success response order placed successfully with status as 201 created that's perfect now the next thing we have to do is to create the inventory service which will check whether the products are in invent are whether the products are in stock or not right so let's go ahead and do that all right so now i'm in the start.spring.i website and it's similar to the other two services i'm just going to leave the defaults for the springboot options and also the packaging and the java version i'm going to add it as 17. the only change i'm going to do is to change the artifact name to inventory service and i'm going to add the dependencies similarly to order service i'm going to add the dependency for lombok dependency for spring web dependency for spring data gpa i'm just going to scroll down until i find spring data jpa and the dependency for my sql you know what i am so i'm scrolling down and you can just search for my sql driver here so i can just select my sql driver and once everything is done i'm going to click on generate all right all right so open the inventory service project inside the your favorite ide and after after that i'm just going to open source main resources and the first thing i'm going to do is to configure the mysql database properties inside the application.properties file so for that i'm just going to leverage on the changes we did for the order service so i'm just going to open the order service and just copy every all the properties which you have defined inside the application.properties and i'm going to paste it inside the application.properties of the inventory service so one question you may have is why did i not add the inventory service already inside the microservices you know microservices parent right because at this moment i am facing some issue to add the inventory service to the micro services parent but we are going to add them to one project by creating maven multi modules further down the project so you can just continue by opening the inventory service in a new ide and we will do the refactoring later right and the next thing i'm going to do is to change the server port to 8082 because 8080 is taken by the product service 8081 by the inventories by the order service and 8082 will be assigned to the inventory service so now the next thing i'm going to do is to create a package inside the root package called as model and inside this package i'm going to create a new class called as inventory and this inventory class will acts as the the model where the actual inventory which we are storing in the database so for this reason we are going to add the entity annotation from jpa and we are going to add the table annotation also with the name as t underscore inventory and we're going to add the getter annotation the setter annotation locks constructor no args constructor annotation and inside the inventory class i'm going to add a primary key called id with id annotation from jpa and generated value annotation strategy as generated value type dot identity and after that i'm going to add the field called as skew code which represent the product and lastly i'm going to add another field called quantity which will provide the number of items which are in stock for this particular skew code right so the next thing i'm going to do is to create the repository for this corresponding jpa entity so for that i'm just going to create the repository package and create an interface called as inventory repository and this inventory repository is going to extend jpa repository because as we are using spring data gpa and spring data gpa to store for the persistence and for the gpa repository we have to provide the inventory as the first generic argument as the jpi repository is going to take two generic arguments the first one is going to be the type of object which you're going to store and the second one is the type of the primary key and here the type of the primary key is going to be long so i'm going to add the type as long so the next thing is to create the controller where we can create our endpoints right so i'm just going to create the controller package and create the inventory controller class and similar to every similar to all the controllers we have created i'm going to add the rest controller annotation and request mapping annotation with value as slash api slash inventory and in here in this inventory controller class i'm going to have only one method and this method is going to be a get mapping so we're going to make a get call to get the inventory status and this response status is going to be http status dot okay and the method and the method name is going to be public boolean is in stock right so what this particular endpoint is going to do is it going to take in a skew code and it's going to verify whether the skew code or means the product is in stock or not right so for that we have to take in the skew code as a request parameter or maybe a path variable right so for that first half what i have to do is i have to add the path variable to the get mapping annotation so i'm just going to type in slash and type sku code and i'm also going to add the path variable annotation here it's going to be string skew code and as this is not going to be as part of this naming conventions i'm just going to add the path variable as skew code so so now inside the ease in stock method i have to query the database to check the inventory so far we are not going to access the inventory repository directly we are going to create a service class so for that i'm going to create a package called as service and inside the service i'm just going to create class callers inventory service and this inventory service is going to have an annotation called as service because this is representing a spring boot service right so inside this inventory service class i'm going to create a method called as public boolean is in stock and this is going to check in the string skew code as an input parameter and inside this is institute code is in stock method i'm going to query the inventory repository right so for that i need to inject the inventory repository into the inventory service where private i'm going to type in private final inventory repository and i'm going to add the constructor parameter by typing the required args constructor annotation from lombok and inside the ease in stock method i'm going to type in inventory repository dot find by and i don't have any method which defined by extension so i'm just going to type in find by capital s skew and capital c code so this will going to be an extension method from spring data jpa so i'm going to create this method in the inventory repository so spring data gpa is going to automatically implement the logic for this find by skew method so at the time of at the run time spring data jpa will require generate the the query to retrieve the inventory by this queue code right so this find by q code method should not return a type of void but it should return an optional of type inventory right so i'm just going to import the optional class from java util package and let's go back to the inventory service and here i'm just going to return this optional dot is present value right as the find based q code method is returning an optional i can just type in dot is present to check whether the object is present inside the optional or not and i can just return the value from the ease in stock method directly and lastly i'm going to add the transactional annotation on top of this method and this transaction is going to be read only transactional transactional annotation from spring framework and i'm going to add the read-only attribute as true now i think we have forgot to add the transaction annotation on the order service so let me check once so i'm going to open source main java service order service and yeah we didn't add the transactional annotation right so i'm just going to add the transactional annotation on top of the class by typing transactional from spring framework transaction dot annotation package right so in this way spring framework will automatically create and commit the transactions once this is done i'm going to go open the inventory controller class and i'm going to now call the inventory service dot is in stock method from the inventory controller so for that i'm just going to type in inside the inventory controller private final inventory service and i'm going to add the required hugs constructor from lombok and here i'm going to type in return inventory service dot ease in stock and i'm going to pass in the skew code so in this way we have created an endpoint which takes in skew code as the path variable and queries the database based on this queue code and will return the response whether the the inventory is whether the product is in stock and one last thing we have to do is to we have to create the data inside the database right so if we try to run the application and if we try to query this particular endpoint of course it will return false by default because there is no data inside the database right so for that what i can do is i can create a bin inside the inventory service application class so so what this will be will do is it will try to load the data at the time of application startup so for that i'm just going to type in a bean definition so i'm just going to add the bean annotation followed by the method public command line runner load data i'm going to name this method as load data and this bean is going to take the inventory repository as the method method parameter so this will be injected through the method injection and inside this load data method we are going to create a supplier and inside this supplier i am going to first create an object for the inventory class so i am going to first set the inventory's q code as iphone underscore 13 and the quantity as 100 so i'm going to now create another inventory object called as inventory one so here the skew code is going to be iphone 13 red and for this inventory i'm going to set the quantity as 0 right so after defining these two objects i'm going to save this two objects into the database so for that i'm going to type in inventory repository dot save inventory and the for the inventory one object i'm also going to this is the same thing inventory repository dot save inventory one so at the time of application startup this pin will be created and as part of this bin we are going to create both these objects and save to the database so before we test whether this is working correctly or not i'm just going to open mysql workbench and i'm going to first create a schema called as inventory service i'm going to click on apply and also apply this will create the schema inventory service and now let's go to the inventory service project inside intellij and start our inventory service application so you can open inventory service application and just click on this debug option and at the time of startup it should execute this particular piece of code where it will save the inventories to the table to the repository inventory objects to the depository so let's check whether this is executed correctly or not yes it does so we have two objects iphone 13 and iphone 13 red inside the database all right so before i've said that instead of maintaining these two projects inventory service and microservices parent we're going to club this everything into one project we are going to create one parent project and we are going to maintain all our services into that main to that parent project right so let's try to do that now so what i'm going to do now is i'm going to create a new movement project completely new moving project inside intellij so for that i'm going to go to file new project and i'm going to select the option maven and make sure to select the version you like i'm going to select jdk 17 here and i'm going to click on next and here i'm going to provide a name called as microservices new so this is the project name i'm going to give it's like a new parent and in the artifact coordinates i'm going to name the group id as com dot programming techie and the artifact id i'm going to leave it as micro services new and i'm going to click on finish and i will going to click on new window it will ask whether to open the project in this window or in a new window i will click on new window and now you can see that it created an empty maven project which contains just an empty source main java folders resources and the test resource folder and the test folder and it's just a complete empty maven project right so what i'm going to do now is to i'm going to create three modules one for the product service one for the order service and the other one for the inventory service so inside this project i'm going to create a maven module so for that i'm going to right click and go to new maven module and again select the sdk as jdk 17 click on next and i'm going to name this module as product service and i'm going to check whether the artifact coordinates are similar to the group id we have provided for the root project it's and the artifact id is going to be product service click on finish and this product service module is now created again with the bomb.xml file you can see that the artifact ad is product service and if i open the form xml for microservices new root project it's also added inside the module section the product service so similarly i am going to create a module also for the order service and the inventory service all right so now we have all these three modules inside our root project so as we have these modules we don't need the source from source folder anymore so i'm just going to delete this source folder and now what i'm going to do is and now i'm going to migrate every all these three projects we have before inside this microservice parent and in the inventory service i am going to migrate this into the micro services new project first thing i want to do is to open the is to open the form.xml of the product service so inside the microservices parent i'm going to open the form.xml of the product service and i'm going to copy everything copy everything under the dependencies section so i'm going to copy everything which is inside the dependency section so all the way down here i'm going to copy the dependencies tag and i'm going to paste it inside the form xml of the product service so just beside the properties just below the properties i'm going to type in the i'm going to paste in the dependencies section right so after adding these dependencies section so now what i'm going to do is i'm going to do the similar thing also for the order service so go back to the microservices parent open the form xml of the order service and again copy the dependencies inside the order service and go back to the ordered service inside the microservices new and paste them just below the property stack all right so now we have the dependencies for the order service let's do the same thing also for the inventory service i'm going to open the inventory service form.xml and copy everything inside the dependencies right so copy it and open the inventory service inside the microservices new folder and again similar to the other two projects i'm going to paste in the dependencies just below the properties tag so now we have the dependencies in all three projects now what we need is the inside the product service of the micro services parent i'm going back right so i'm switching a lot between these two projects i hope you are understanding so i'm now inside the product service of the microservices parent and in here we have the dependency management tag right so this is where we are defining the version of the dependencies for the test containers so i'm going to copy this dependency management tag and i'm going to add it inside the root folder i'm not going to add it inside the product service but i'm going to add it inside the root of micro services new project so you may get the doubt why i'm adding it in the root because if i add it in the root and if you want to have the test container dependencies inside the order service and as well as the inventory service you don't need to repeat yourself right inside the product service before we have to we are adding the dependency management tag and instead of repeating them on in on each module i can just define this inside the parent module under the dependency management tag and this dependency will be like propagated to all the child's services like order inventory and the product service so that's the main reason we are adding it in the parent and another important thing we have to do is to open the microservices parent like you can open any any of the form.xml and you can see that the parent is defined as springboard started parent for each of the services like product service order service and the inventory service in the old setup right so what i'm going to do is i'm going to copy the parent and if i open for example product service you can see if i scroll up you can see that the parent is micro services new project right but to be able to download all these dependencies to our project we have to define the parent as springboard starter parent so for that what i can do is i can go to microservices new project and i can define the spring good starter parent as the parent of the microservices new project right so in this way if microservices new project is the parent for order service and the inventory service so this springboard starter parent will be the grand parent of order service inventory service in the product service so in this way all the version will be downloaded without any problems to our um to our project so if i click on the load maven changes icon all the dependencies will be downloaded without any problems right and one last thing i have to do is now to add the spring boot maven plugin right if i open the one of the old setup so if i go to product service we have this plugin information here right like the spring boot maven plugin and also in the order service we have the spring boot maven plugin right so i'm just going to copy this whole build tag where we have the compiler plugin and the maven plugin and similar to dependency management i'm going to add it inside the root project inside the micro services new bom.xml so in this way the springboot maven plugin and the compiler plugin will also be added to the all the child projects right so again i'm going to load the maven changes to make sure that there are no problems in the setup so to be able to test whether everything is working correctly or not we have to also copy the source code right so now if you check the services we don't have any code inside we have already developed the code for this one so what i'm going to do is i'm going to first delete this source folder delete the source folder inside the product service i'm going to do the same thing also for the order service and the inventory service right so what i'm going to do now is i'm going to copy the source code from the old projects so i'm going back to the micro services parent project and i'm going to copy the source folder from the product service just right click copy and just paste it under the product service right click paste new name will be source click on ok and everything will be copied without any problems similarly i am going to do the same thing for the order service so go back to the old project microservices parent copy the source folder paste it inside the order service it's fine and now open the inventory service copy the source folder and paste it inside the inventory service click on ok and everything we should work without any problems now just to verify that everything is working fine what i can do is i can run a command called as maven clean verify so i'm going to open the maven tab to the right side of the intellij idea and i'm going to click on this m icon to execute a maven goal and here i'm going to type maven clean verify right so what it will do is it will just run the compile so it will try to build the project without trying to install the everything and finally you can see that the build is success and it took total of 29 seconds on my machine to execute this and lastly let's check whether the applications are also working correctly or not like are also able to start up correctly or not so i'm going to open source main java product service application and i'm going to run the product service application so you can see that the application is startup is started without any problems the product service application and the order service application let's start this one more time and it looks and it started successfully on port 8081 lastly the inventory service let's start this application and also you can see that it started successfully on port 8082 right if you are facing some problems if you are not able to replicate the same result as i am you can download this whole particular whole project from github i will upload this as a starter project for this particular series in github you can download this project and you can start working from that point right so again you can check the initial setup branch inside the springboot microservices new repository and there you'll find the complete setup the initial setup which we have just did before right so just download this project if you are facing any problems and then you are and you can start coding along with me from now on alright so before we go on there is a small bug inside the inventory service inside the inventory service application class so we are running this load data method multiple times whenever like whenever so we are running this load data method whenever we are starting up the application right so that means whenever we are starting up the application we are inserting this two inventory objects into the database so that means for sure we have some duplicates inside our database let's go open our mysql workbench and just i'm going to run the select query and you can see that this particular iphone 13 and iphone 13 red skew code inventory objects are are duplicated so to prevent this for now what i can do is i can just select all these duplicated records and i can just try to delete them manually delete and click on apply and this will delete all the records from our from our table right and to make sure that it won't occur one more time what i can do is i can go to resources application.properties and as this is not a production application i'm just going to add it as create drop the ddl auto as create drop if you are using it in a production setup please don't use create drop you have to use ddl auto as none and you have to use a database migration library like liquid base or or flyway to do this kind of uh migrations so please don't use create drop this is just use as a demo purpose and please don't take this as a recommendation to add this inside your production code right so having said that let's restart the inventory service application and now if you open the inventory service click on select you can see that we still have the two records we are not duplicating it because it's creating and first it's first dropping and then creating the schema again so