Transcript for:
Microservices Architecture for E-commerce Application

after a long discussion with the development team we agreed on the following architecture and Technologies first we decided to go with a microservices architecture with spring boot 3 and spring cloud and this is the diagram of our future application that we will Implement for our client now click on send all right so here we see that we have 200 and we have the ID of the newly created order so now let's open the browser and check the mail and see if we receive an email with the information that you specified and the template that you specified before so I will open a new tab and open my Local Host 1080 and here we have two emails so the first one we have an order confirmation so we have order details for the customer joho and this is the order uh the order reference that the one that we created we will create a new one and we will change the customer also and here we see the information or the list of the products which is the product name with the with the quantity and the the price and we have here a total amount and here we see another email which is the payment successfully Pro processed so payment confirmation hey what's going on guys and welcome back to this new video in today's video I will guide you step by step to the implementation of an e-commerce application using the microservices architecture so I know that you always have been waiting for so long for this video and now it's the time so in this application or in this video I will guide you to the implementation starting from the business requirement to designing the application applying the DDD approach and also we will see so many distributed patterns like configuration service to externalize the uh the configuration of our applications or our our different microservices a discovery server where we can register the different microservices and then API Gateway that will connect and collect the different microservices from the server and then route the application and of course we will see so many other things like how we can establish uh a synchronous communication between our different microservices and in this in this part we will see two different ways first we will see how to use open fan and then how to use the classic one which is restone plate so you have more more and more options to choose when it comes to real world applications so this is not yet the end also we will Implement an asynchronous communication between our different microservices using Kafka as a message broker so I will show you how to set up Kafka also how to uh configure all the requirements and do all the configurations in order to make Kafka communicate like in an advanced way between the different microservices also our application supports email uh email sending so we will Implement a notification service that will uh that will consume the topics from Kafka and send emails from there we all know that in a microservices architecture sometimes it's really hard to uh to determine what were what was the flow or the path of executing one query from the API service or from the API Gateway to the end service or like what are the spans or the different services that has been executed so for that we will set up a distributed tracing using Zipkin after that we come to the most important part when we Implement any type of application independently from the architecture so here we talk about security and for that I will show you how to integrate key loock within a microservices architecture application so for that we will see how to set up K loock how to configure a realm how to create a client and how to connect our K loock to our architecture in order to secure our ecosystem so this is briefly the application that we will build together during this video but here let me tell you a little bit about the requirements for this video so first you need to know about spring boot so if you are not familiar with spring boot I would like to invite you to check the video that I will post in here in my YouTube channel so you can learn uh and get all the knowledge that you need for a spring boot application so how to work with spring boot how to deal with the framework how to learn or how to use the framework then we we will use kfka as mentioned so for that also I will I will attach the video for this one so I recommend watching it before going or like completing this video or you can just post the video when it comes to the Kafka part and then like check Kafka uh check the video watch it and then you can come back and continue this one and of course when it comes to the infrastructure and the tools that we need to implement our application like uh the databases like mongodb uh postre SQL uh Kafka and so on so forth we will use Docker and I show I will show you how to set up Docker and what are the requirement and the necessary configurations in order to have a complete and up and working infrastructure for our microservices architecture the source code of this application is available in the description of this video and also you can check it directly on my GitHub account and just search for microservices and you will find the ripo there and of course don't forget to follow me on GitHub to get all the news and all the Rios and all the code that I that I will be pushing in the future and also don't forget to start the ripo and share it with your friends now before we start if you're new to my channel just go ahead and hit the Subscribe button give me a thumbs up and let can help share this video to more and more people and let's spread the knowledge all together and now with no further Ado let's get started and let's start coding our microservices architecture application so now I wish you happy learning first let's start with a business requirement let's imagine and pretend that a client contacted us and he needs us to implement an Ecommerce application so first let's go through the requirements so our customer has a problem so as a business owner in the e-commerce sector I'm currently operating without the aid of any digital solution so this means that our client is operating manually about everything so let's have a look on the business requirements or like what is the business of our client so my product line consists of a variety of items each identified by unique code and a compined by a detailed description a customers interact with my business by placing orders from this list of products and I identify my customers using their first name last name email and address each customer transaction involves a specific payment method and upon the completion of a successful payment transaction I take the responsibility to inform the customer via an email confirming the success of their payment or conversely notifying them of any payment failure and in a bit of a streamline operations and promote growth within my business I'm looking to invest in the development of a dedicated application so the application will serve to simplify my business process and contribute significantly to the over all efficiency and scalability of my online Venture so this is the requirement that was sent by our client and the next step is we need to translate and transform the small business requirement into an application so let's go ahead and work through how we will Design this application as always the first step is to design the application starting from the business requirement provided by our client so our client mentioned that he has customers interacting with his products to place orders and uh perform payments and so and so forth so here in the top part and the green one we talk about a customer so he mentioned that a customer is identified by a unique ID first name last name and email and each customer has an address so that's why we have two entities or two classes or models presenting the customer information so here we have a customer and we have an address then he mentioned that each customer he needs to pass or to order some products so that's why we come to the product part where a product is identified by a name description but for us as Engineers we need to come with extra solution so we need to discuss with the client and propose some functionalities and propose few things so the the customer did not mention anything about the available quantity or prices or something like that so we need to discuss and ask questions so that's why after our after discussion with the client he mentioned and he approved that yes we need to have an available quantity and a price so then also we propose that we need to classify the products by categories so that's why we need an entity or a class category and it will be this dis played or um organized by name and description and since we talk about an e-commerce application a customer and products so each customer needs or can place or order many products so now in order to organize and have a better organization of our orders we came up with this order and order line so the order is just to uh identify the order with an ID for example an order dat to keep tracing and also an order reference in order to uh have something uh well organized within the orders and each customer can order multiple products so this is where and when we can introduce this new entity which is order line and this order line will have an ID and a quantity and of course this will be the association entity between the order and the product because when we talk about the direct link or the direct relationship between an order and product we will have many to many so an order contain many products and a product can figure out in many orders so that's why we have or we created a new entity called order line then we talk about payment so each order should have a payment and the payment will be identified with an ID a reference amount and a status so since the the client mentioned that the payment can be successful or or failure so that's why we need to have a status so once the order is placed and the payment is successfully performed we need to send a notification to our customer so that's why we have here a notification entity and the goal of this notification entity is to keep Trace what we send to the customer so here we will have an ID we will have a sender so the sender will be always our system or the client uh and the recipient will be the customer here and of course we will have a content and a date when we sent this notification so this is the global design of our application so this is how we transform the small business requirements sent by our client into a system design or a design of our future database or our future application after several meetings with our client we discussed few things among them the the changes or the small changes that we introduced into our class diagram and then we try to discuss more things and the owner or the business owner he mentioned few things that led us to the decision how we will Design or how we will Implement our future application so he mentioned that he has a business owner he would like to uh that the application he wants it to be resilient to failure so ensuring that if one component goes down it does not bring the entire system to Hal so for example if the customer uh if the customer part is not available or if we are not able to create a new customer so the whole system should not go down and we should be also able to place order for uh orders for other customers then our client mentioned that he wants to run some uh marketing campaigns and uh bring new customers and for that he mentioned something about scalability and he said that as a business owner I want my application to be scalable to handle increasing traffic uh traffic and workload demands so this introduces us to something important which is the scalability of the application and then we spoke about the development and the time or the required time to implement the application so he mentioned something about about faster development or the speed of the of the development so he said that as a business owner I aim for Rapid development and deployment of new features and updates to stay competitive in the market then he mentioned uh also something we discussed about something else which is like enhanced monitoring and debugging so he didn't know about debugging so we had to explain what debugging is and we explain things in a way that he can understand since he's not coming from a technical area so he mentioned that as a business owner I require comprehensive monitoring and debugging capabilities to ensure the scalability and performance of my application so these were the first or the second discussions with our client about the future application so from that or from these discussions we decided as a team or as a development team to go with one specific software architecture so since he since our client mentioned that he wants his application to be resilient to be scalable he wants also a faster development he he wants also uh in the future a continuous deployment and enhanced monitoring and debugging so for that we decided to go with the microservices architecture for our application and when we talk about microservices the first thing that we need to discuss about or the first thing that that we need to put in place is to apply the DDD or the domain driven Design This means what this means that we need to identify the different domains of our application so for our case now let's go and see how we were able to identify or to split our design or application design into domains so here in the top part of this diagram we see that we have a customer domain so we need to manage customers for our application so now we talk about the global application but we will break it down into small parts or small domains so here as mentioned we have a customer domain so a customer is identified by the customer entity and the address entity so now let's not talk about these relationships between the domains we will explain them in just few moments then after the customer we have our product domain so the product is identified by the product and the category then a customer needs to place orders so we have an order domain or we came up with or we decided to have an order domain containing the order and the order line then of course we have payment and we have notification domain so the payment will take care of all the payment processing and the notification domain will take care of notifying the users and the customers of of our application about their order details payment details and so and so forth so in this way we were able to cut down or to split down our application into small domains and as you can see here we have five domains customer domain product domain order domain payment domain and notification domain so here let me explain how we would uh how we would take care or break down these relationships that we see between the different entities so this will be uh more clear in the next diagram that we will discuss together which is we need to ensure a communication between the customers but before talking about about the communication so let's let's see it or let's discuss about it from uh from a database diagram perspective or from database perspective so here when we have this relationship between the customer and the order this means that in the order table we will have an ID of the customer who placed the order so all we need to do when we talk about microservices architecture and domain driven design all we need to do is we will not have this relationship right here we will just have a customer ID in the order table all right so like we have exactly in a real word or like in a single database but the only thing that for example when we talk about spring ring and hibernate we will not have a customer reference or a customer object in this order table and in the other way we will not have a list of orders in the customer table but we will have just a reference uh well not this reference uh not this reference but we will just have the customer ID placed in the order and in the customer we will have nothing about the orders but if we want to fetch the list of orders by customer all we need to do is to query this domain and to send an HTTP request or a synchronous request depends on the decision or the technical decision that we will take later on so all we need to do is to tell this domain to send us back all the orders where the customer ID is the customer that we sent as a parameter for example and this applies for all the other things so for example when we talk about order line and product all we need to do is to have an order line or we need to have a product ID in the orderline table or the orderline entity from the product in the same way if we need to fetch all the orders or uh all the order Lines by product or uh for a specific product all we need to do is to query this domain this applies also in the same way for the payment domain notification domain and also along with the order domain so this is how our future domain diagram or uh domain driven design was applied in order to uh break down the application into smaller domains so as I mentioned we identify five domain just to remind you customer domain product domain order domain payment domain and a notification domain so now we identifi the different domains what we need to implement next is to set up or tow an architecture diagram of our application after a long discussion with the developer team we agreed on the following architecture and Technologies first we decided to go with a microservices architecture with spring boot 3 and spring cloud and this is the diagram of our future application that we will Implement for our client so here first of all we identify or we see that we have our five microservices or five domains that we saw previously so here we have a customer product order payment and and notification so for the customer we decided to go with a mongodb and an uh nosql database so going with mongodb is not a technical choice just don't tell anyone it's just for showcasing to to see and to Showcase that we can use different database systems when we when we work with microservices since each microservice will has or will have its own database then we will have our product mic service that will communicate with an SQ with a postgress SQL database and all the databases will be running on Docker then we have our order microservice payment microservice and then we have the notification microservice all the microservices and all the ecosystem will be running in a private Network so no service will be exposed to the public so after that we identify that we need to set up or to use some distributed patterns and for that we decided that we need to externalize all the configurations for all the microservices so that's why here we have our config server will be a micros service based on springbot 3 and also spring Cloud so this will be our config server where we will store all the configurations for all the microservices that we see in here like customer products payment order and notification so also we need to register all the microservices so they can be seen and and accessible via our API Gateway and for that we need to set up and configure a urea server or a discovery server then we need one single entry point for all our services and here as you can see we will expose only three microservices so here we have a customer so for example uh the user or the user can register himself or create a customer or even the owner and the admin user can create customers using our customer microservice then we need to create and adapt and update and adjust our products so for that we we see here that we have the list of products or the microservice that will take care of the products that's why we have our API Gateway that will point or will allow us to communicate with the product microservice and since our application is mainly about placing orders and an e-commerce application so that's why we will also have a route from the API Gateway to our order micro service then when we talk about notification we don't want to block the whole application and make it uh long and uh so heavy in order to process everything so once the payment is processed and also the order is processed we will send all the data asynchronously to a message broker and for this case we will use Kafka and for Kafka it will be an advanced usage it's not a simple usage just sending uh a string uh message and consuming it but it will I will show you how we will Implement Kafka or how we can use Kafka in a bit Advanced way all right so here that as I mentioned the payment will send a payment confirmation to our broker and then this payment confirmation will be consumed by by our notification microservice and then it we will send an SMS well not an SMS but we will send an email and we will store this notification into our mongodb database in the same way once the order is processed we will send an order confirmation so when a user um when a user passes an order uh we first we will process the order request or request a payment and once the order is processed we will send a an order confirmation and then the payment will be also processed in a parallel way and once the payment is successful or a failure we will send also another payment confirmation or a payment failure to our message broker and as I mentioned all these um messages will be consumed by our notification service and of course since we spoke about uh distributed tracing and monitoring we will be using Zipkin for this distributed tracing in order to see or to trace all the requests that have been sent or processed by our ecosystem so in the future we will also enhance this part and we will be using an elk stack which is elastic search L stash and kibana stack in order to have better monitoring and better uh dashboard to monitor our full application and here as mentioned and as you can see in this diagram the application will be publicly available only via the API Gateway and in the future we will also implement the front end part for this full application so again let's show let's see the full flow of our application so first we have our different microservices and all the microservices they will pull the configuration from our config server and when each micros service starts he will register himself into our Discovery service which will be our UA server and then the API Gateway we contact and connect to our urea server in order to get all the services that are registered in here and then and then in our API Gateway we will Define routes to the public or like the publicly accessible microservices and in this case we decided that we will have only customers products and orders microservices that will be accessible via our API Gateway and here for example we don't need to expose or to have a specific route for the payment since the payment will be only an internal microservice will be only uh used by the order the order micros service so now let's let's discuss how the flow of this full application will be so here let's imagine for example that user wants to place an order so let's start from the bottom side so when a user places an order with the required information like for example the customer ID the list of products and so the quantity the price and so and so forth so what we will be doing so the order microservice will First Connect or contact the customer microservice in order to make sure that the that the customer ID that we received as a parameter already exists with all the required information so for example in the future maybe we can decide that we want to disable a customer that we want for example to block a customer and so on so forth so we need to contact the customer microservice in order to make sure that the customer is eligible to place an order once we once we have for example a successful uh response from the customer microservice we need then to contact and to quer few data from the product so we need also to make sure that the products that have been placed as an order already exist and have an avail able stock quantity in this system so for example if the user wants to order a product with an id1 and this product only has two pieces uh available in the system and the user wants to place for example four uh four pieces or four elements as a quantity we need to block the request and send an error message to our user telling that no sufficient quantity for this uh for this product that you want to place so this this is the first process and this is how the first part will be communicating together once everything is fine so once we have the customer also once we have the all the products available with uh with the require required and the requested quantity we will process the order so we will save the order into our system and then we will send an email confirmation or an order confirmation to our broker and then we will start the payment process so we will also send and request um send a request to our payment server or service in order to start processing the payment for this order and then once the payment is successful we will persist it and save it into the payment database and then we will send an async uh payment confirmation to our broker and then our notification system will consume two uh two topics or will consume two messages or two types of messages we will see the details of the async communication later on so the notification uh Service First for example when we receive the order confirmation we will consume it process it send an email and save the confirmation or save the email that has been sent into the database the same way for the payment so the user will receive mainly two emails one email for confirming the the order and another email for the payment uh payment confirmation or for the payment denial for example if the payment uh was not successful so this is the global overview of our application and of course as mentioned before all you see inside here will be will have a distributed Trace tracing using Zipkin and in the future we will upgrade this one to uh the elk stack as mentioned before so this is the global overview and the global diagram of our application now we can start and we can move to the implementation of our application so first we will go and we will use as always the monor repo approach so before many of you asked me how to set up this monor ripo approach or how to set up our working space as a monor repo approach so all you need to do is to choose a folder or a destination where you want to set up your working space and then using anj all you need to do is to do file and then open and then just select the folder and click on open and you will have in the beginning this EX exactly structure so here you will have the the folder name and you will have this idea. idea folder and that's it so in the beginning this is all we need to do so now to start first I will create few folders in order to organize my application so the first thing I will create something I a folder I will call it diagrams and in here I will place or I will uh leave uh the diagram that we uh that we saw together in this in this folder and then I will create another another folder and I will call it resources and here I will uh I will leave or I will uh place a few resources for you like for example the the PowerPoint that we saw together and all this stuff and then I will create another folder and then we call it services so services will be the folder that will contain all the services and the microservices that we will Implement together so here just make sure you have these three folders or at least the services folder so the diagrams and the resources are not mandatory they are just for you in order to have all the resources that you need now we can go ahead and start creating the different services but before that we need to set up our infrastructure and create the required services and the required tools that we need to work on our application so for example I'm talking exactly and mainly about the docker compost file where we will have our post degree SQL postgre admin uh mongodb Express and also mail Dev to in order to start implementing our application step by step so now let's move on to the next part and prepare our infrastructure file all right now let's start creating our first file which is which will be our docker-compose do yaml file so only one dot and here all we need to do is to set up or to create the services that we need for our application so first let's have our services and then the first service will be postgress so postgress and now I will give my container a name and I will call it Ms for microservices _ PG for postgress SQL and uh for postgress and then underscore SQL and for the image I will use the post address SQL or like the post address and now I need to set some environment variables as always so here we have first our post address uncore user and for this case I will call it alibu for example and then we have our post address password and we call it again for example also alibo so like here you feel free to have uh better uh username and password but for my case it should be also fine and now we need to have our postgress data this is where we will map or like we will set up our postgress SQL data so by default postgress SQL Works under VAR SL lib SL poost address SQL and slash data so this is the the PG uh PG data now we are done with this part or the environments we can set up few volumes so before setting up the volumes I will scroll down to the bottom right here and I will create all the volumes that we will need later on so first I will create volumes and the first one will be postgress and the second one I will create another one for postgress admin I need colum here and finally we will create one for all right so we are done with the volumes and before moving forward I will also prepare my network so here I will create networks and I will call it microservices Das net like for network and then I will use the driver Bridge all right so now we are done with the basic setup for our Docker compost file we can move on and continue the implementation of the setup of our different containers that we will use so here let's specify volumes and for the volumes I will use postgress SQL for and this exactly same path so it will be postgress SQL or postgress which is this name right here and then colon and then which part we want we want it to be persistent so which is this one where we have the data of our postgress SQL so now then we need to expose some ports and as always you know that postgress SQL operates on 5432 and we will expose it over 5432 so this is is the container port and this is our external Port that we will be using so now let's assign this one to a network and then for the network let's say our microservices Network and I will add one final option so which is the restart and I want it to restart unless stopped so here unless stopped so if this container is stopped I want to perform an automatic restart so this part or like this the next service which will be our PG admin or postgress admin so this postgress admin is mainly for the people who are not using or who do do not have access to uh to the anj ultimate version because uh this option right here this database option right here only available for the ultimate version of NJ so otherwise you can use this PG admin and I will show you how to use it once we once we finish this setup so let's give our container and name and again it will be uh Ms for microservices PG admin PG admin and then let's use the image which is uh I think it's called D page sl/ PG admin PG admin 4 yes that's it and then let's set up few environments and here we have a PG admin underscore default email so like this is just to set up the default email so we will use a value in this way so PG admin and then default underscore email so default uncore email colum and then I will use Dash PG admin uh by the way all this is available on uh on Locker Hub when you go for the PG admin um container or image you will find all these details already uh in the readme file or in the description of this container and here at uh PG admin. org all right so this is the first one the second one I will Define a PG admin or postgress admin default password and then the value it will be again in this way so PG admin and then default _ pass password so here whether we use this one uh admin yes and then colum and here let's say admin as a default default password so I will add another environment variable which is PG admin or post agress admin config server mode and I will set it to false so let's set it here and a false with a capital f all right so this is the configuration of our postgress admin now let's let's add some volumes and for the volumes I will add my PG admin and then I will do it over SLV SL lib slpg admin so just in order to have something or like a persistent volume for our container then we need to expose some ports and by default PG admin uh Works uh or like um exposes the port at but since the port uh 80 can might be used so I will be using the port 5050 just you can choose any any port like you you do not need or like you should not or it's not the must to use the same configurations or the same values as I do it's just as I mentioned before just for showcasing now let's assign this to our microservices Network so here Network in this way and we can remove also the colums so like exactly in the this in this way what that we did it before so once we have the network also we can add add the restart andless stopped and now we are done with the setup of our postgress SQL and postgress admin so the next one is to set up our DB so I will create another service mongod DB and I will give it a container name and let's say for example mongoor DB or Ms just to follow the same pattern uh my micros service mongod DB and then I will have some ports uh sorry before the ports we need of course the image which is will be and then we can expose the ports by default mongod DB operates over the 2707 Port so we can use also the 2707 Port all right so now we need to add the volume so the volume will be and then colon SL dat and finally we need to set up some environment variables so the first one will be init DB underscore root uh underscore username so this will be the username and let's say uh alibu for example and in the same way we have the INB root and then password and I will also set it as alibu so like both of them are fine also by the way here you see that we Define the environment variables in this way but also if you see something like this this also correct so like we can use it in this way all right so we so let me set it in a different way so at least we learn new thing every time so here INB root username and init DB password so this is the setup for our mongod DB cont container now we can move on to our Das Express so I just here you can call it anything you want by the way so first we need an image so the image will be Express and let's give it a container name and let's call it mscore mongoor express as a container name so here let me just reverse them and here we have the container name uh so for example let's stay restart always so I want my Express to be always uh restarted like when uh when it stopped for example and then let's expose some ports so the port we will expose the 8081 over the 8081 so Express operates on these ports now we need to set up few environment variables and here we can use the same representation and here the first uh the first one it will be me uh- config or like underscore config mongod DB so mongod DB uncore admin username equals and let's use also alibu and here I will duplicate it and here instead of admin of instead of admin username it will be admin password the final one is it will be meore config _ mongodb and here instead of admin it will be server and for the server we know that we want to use our DB server which is which is this one so now we are done with the basic configuration since we also we we want to implement a notification service with uh with sending the emails you also know that which tool or which service that we will set up next so we will use our mail Dev all right so this we can set it up in in the later uh phase but we can do it now so the container name I will call it msor maale _ Dev you can also use dashes by the way it's also fine and the images we will be using mail Dev slma Dev all right so then we we need to expose some ports uh 1080 over 1080 for the UI and the 10 25 over 1025 for the SMTP server so now we are done with the with the setup of our infrastructure all we need to do is to run and start all the services and make sure that everything is working fine and we need to check it or to see it also in the dashboard so what I will be doing I will just run the docker compose up minus D for detached mode and we need to make sure that all uh that all the containers are starting correctly so this is the case so like we created the volumes the networks and everything and here we have all the servers are uh all the containers are up and running and started we can also uh we can also make sure and ensure that everything is running fine using the docker dashboard so let's go ahead and check it so here in our Docker dashboard we see that we have this e-commerce app and we see all the applications or all the containers up and running among uh Ms among Express which is like you will see it sometimes flickering because it's always restarting we can also add or like change this option here if we go back here to our Express and we said restart always and here we can say for example unless stopped all right so now let's bring down or like let's say Docker compose down to stop all the containers and we can start it again and we will make sure that all the containers are are up and running and everything is fine so now let's just go to the browser and start do some checking for example we want to make sure that the postgress admin is up and running also as well as the Express and so and so forth all right so now if I go to my browser and try to reach the Local Host 50/50 slash this one it will be automatically added so this is the port of our postgress admin so this one this PG admin you remember we exposed it over the port 5050 so now if I go back to my browser the first thing will be prompted to Define root password or password for PG admin you can choose anything for my case I will be using root but uh in the future I will not be using uh this interface since I have everything in anj so it's just for you in case you don't have the ultimate version so now all you need to do is to add a new server and here you just give it a name and then the connection you give it the for example the remote address or the host name address the port username password and all you need to do is to click save and start using PG admin as your Tool uh to uh to check or to have all the databases in one place so this is the first thing the second we will also try to reach out and to see if our Express is up and running so all we need to do is to go to Local Host and then the port 8081 so let's change this one 8081 and now let's see if this can be reached all right so it seems that Express is not accessible and this let's check our uh dashboard so here we see that it's not able to connect so authentication failed let's go back and check what we made wrong so this is the configuration of our Express and here we have admin user and admin okay so here we have the typo it's admin password not admin a password so all I need to do is to run Docker compose down again and Docker compose up minus D and now we normally like logically we should be able to reach out our Express so now we have everything up and running and if I go back to my browser refresh this page and here we see that we have our Express so this we will you we will be using uh Express in order to uh to check the databases and the data for the microservices that will be using the mongodb database all right so now we are done with the configuration and the setup of our infrastructure so it's not the final setup of course like when we progress and we when we uh advance in the implementation of our application we will add the required or the the necessary Services one by one so now we can start implementing the different Services of our application so all you need to do is to follow along first of all we will start by creating our first uh microservices patterns so we will start first of all with the configuration service and Discovery service so for that we will go to the spring initializer and choose Maven project here the latest version at the time of the recording of this video is 3.2.5 now let's add some metadata so for the group I will call it com. alibu and for the artifact I will call it it config server config Das server so this will be our configuration server and here this is just demo description or this is the the description of our of our project so we can leave it uh we can leave it as it is or for example we can just say config server as a description so here I will just change the package name to com. alibu do config server so I will be using jar file and Java 17 and now we need to add one dependency all right so for now we will add only one dependency and later on we will add uh other other dependencies and I will show you and then explain to you why we need them when the time comes all right so now the dependency that we need to do is to search for config server all right so here you see that we have config server which is Central management for configuration uh via git SVN or haric Corp vault so let's select this one and here we can go quickly and check the check the dependency so here it should be uh 2301 for the spring Cloud version and here we have our spring config server dependency and the starter test and so and so forth so all we need to do is just to click on download and then take the the zip file and extract it so let's do it together so first I will download this one and then all we need to do is to go to our working space and inside this Services uh folder all you need to do is to extract the folder there and then I will show you how to do that all right now we see that our that under uh our folder called Services we have this config server project so now as you can see it's not recognized even as a Java project or as a maven project so what we need to do is to import this one into our working space so how to do that so all you need to do is to go to file and then new and then module from existing source and then all you need to do is to navigate to the location of your working space and select the pom.xml file and click on open so now this will load the start reading the maven project and loaded as a project so now just to make sure that it's a project so you will see this small uh square or rectangle the blue one right here so now if we navigate for example to our uh Java resources so here we can see that we have this default Main and like the annotations are recognized and so and so forth so now let's start first of all by configuring our configuration service so the first thing that we need to do is in our config server application the main one all we need is to add an annotation called enable config server so this is the first one so this is what we need to do first and then in order to set up and tell spring where are the locations of our different different configurations we need to add some properties so here I will go to the application properties and first I will rename it because you know I prefer using gaml over properties and now all I need to do is to provide few information so first let's change this one to yaml representation and then colon and then config server so this will be the name of our application and now we are missing this indentation right here so now let's start adding a few uh few properties so first I will specify the server. port for my application so I will use the port 8080 8080 so like uh 4 * uh 8 so let me also remove these empty lines so this will be the server port for our application and then for the profiles we can say for example uh spring. profiles. active and here we can set it to Native so this means that we want to use the native the native profile all right right so after that we have another property so this where comes the spring Cloud configuration so here we will have spring. cloud and then do config and after that we have config server so like this spring. cloud. config do server and then do Native so then what we need to do so like natively or by default we spring config server or our configuration server should uh fetch the uh should fetch or should search for the location of our different configuration files or configuration files for each configuration or for each micros service in our application so here I will add a property called search search location and by the way we can also configure uh this to fetch the locations or to fetch the data or the configuration files from GitHub for example or from any remote repository so for this one I will use class path so I will show you later on what what will this be and then configurations configurations so this will be the location of our of our configuration files so the class path means this one so the class path is this location this resources right here and then I will create a folder and I will call it configuration configurations sorry and then I will paste it all right so now we have our configurations folder and there we will place all the configuration files that are required or for each micros service that we will Implement Al together so now for now what we did is only we have our configuration or config server which will store uh all the configurations for all the other microservices so now we can just go ahead and try to start our config server application and see if everything is up and running and if we are able to run the application so as you can see here started config config server application in 1.2 uh seconds and so on and so forth so now this means that the application is up and running all right so I can stop this one right here and then I will show you how I run several Services all together so now we are done with the config server what we need to implement next is our Discovery server and you might ask the question why I started with those ones so first of all we need our config server because we need to store all the configurations for the future microservices that we will Implement and then we need our Discovery server because we want when we start or when we run an application we want to automatically register them into our Discovery server so that's why or like this is the decision or the reason behind starting with these two microservices before any other microserver so for example the API Gateway the distributed tracing and so on so forth this we will Implement later on because it's not uh a mandatory step or something that will block us from doing even like if you want config server is not something that we we we should try or like we should start with it uh in the beginning so we can start implementing the different microservices independently and then we can add uh we can add the different distributed patterns like config server Discovery and so on so forth but for us let's let's start by preparing everything and then we will see all the things working together smoothly all right so now we can move on and start implementing our Discovery servers all right now we can create our Discovery service so for this time I will not I will not use the spring initializer because so many of you um asked how we can create it using using anj or why I do not create my projects using anj so for me it's just preference I I prefer using the the web version but let me also show you how to create it using anj so here all you need to do is to select services and then go to file and then new and then Pro and in here all you need to do is to specify your working space or your working location or the location where you want to uh to create this folder and as you can see here we are under e-commerce app and then Services which is this folder right here so now let's call this one Discovery so this will be our Discovery server and in the group ID it will be com. alibu and uh for the for the artifact it will be Discovery and then for example for the package name it will be this one so we can keep it as it is and it will will be Java 17 and here don't forget to click or to select Maven all right so let's click on next and now it's time to start selecting the dependencies all right so here all we need to do is to select or to search for our config uh server and then we just need to search for config server all right and here we will find two so the config server is the one that we used previously to create or to add this dependency to our configuration server and now we need our config client since this will this is the one that will allow an application to connect to a spring config server and fetch the configuration from there so this will be the first dependency and we need then let's search for ureka and now we need our ureka Discovery server so like we have Discovery client and we have urea server so for this one we need our urea server because this is the the UA or the discovery project that we want to create so these are the two dependencies that we need so the just to remind you the config client is the one we need to fetch the configuration or like to uh that will allow us to connect to the configuration server and fetch the configurations and the uast server is because we want to create or we want to consider this this urea or this configuration not the configuration but the the current micros service that we are building we want it to be our Discovery server so now all we need to do is to click on create so this will open uh a project in a different or in a new uh new instance of anell J but let's close this one and in the same way so as you can see here this config server is considered as a maven module but this one not so here you have we have two options whether we go again with file and then uh new and then module from existing sources and we select the pom.xml file file or from here from this Maven we can add another one so we can add a module and here you see that we have Discovery and all I need to do is to click on pom.xml and open it so it will be loaded and considered as a Java project all right so now let's move on and proceed to the configuration of our Discovery servers so the first thing we need to do we need to go to source and then main Java and Discovery application so the first think we need to add an annotation which is called enable urea server so enable urea server so this means that we want to enable our Discovery service all right so then we need to tell this micro servers or these Discovery servers from where or from which location he should fetch the configuration since we have in our application we have here the spring Cloud starter configuration so this is the configuration server uh or the configuration client and it comes already with uh with the auto configuration and so on so forth but we need to provide few information so here let me rename this one to yaml file and here there is one thing which is very important we need to leave or like we need to set up this application. name and here let's call it Discovery for example or let's call it Discovery service all right so this name is very important right okay so then we have spring and then cloud and then config and we have an option called import so this from which from which location we want to fetch our our configuration so here we have something called optional so this means that if we cannot find the configuration of our of our micros service like we we don't want the application to fail let's also try to uh to start it and then we have uh config server and then colon and now we need to specify the URL of our configuration server so we mentioned or you remember that our configuration server runs already on the port 8088 uh 8888 all right so we need to remember that one so here we have Local Host colon 4 * 8 and that's it all right so here I think we have a typo so it's not spring Cloud it's just spring uh config and then import so spring config and then we have import so this where from where we can import our location so it's not spring. Cloud but it's just spring config and then import and here all we need to do is to specify the application name so this application name why we need uh why I mentioned that this is important and we need to pay attention to this one because when we go back to our configuration uh server and when we start the configuration so so now we will uh we will write and add some configuration to our config or to our Discovery service all right so how to do that so the way to do this is we need to go to our config server under configurations let's do right click and then let's create a file so the file I will call it exactly the application name of the current one that I'm configuring so in this case it's called Discovery server so do yaml so I will use the representation and now we can start adding some configuration or the configuration for my Discovery service so then when we start our config server and after that uh we start our Discovery server our Discovery service will connect to the config server and it will try to fetch the configuration using this application. name so it will try to look for a configuration called discovery-- service. yaml or property so like both of them are fine all right so so like you can use any represent any representation you want so now let's add some uh some configuration to our Discovery service so here we have urea and then colon and then we have instance and then host name so here we need to uh to define the host name so it's Local Host all right so this is this will be the instance name or the host name of our Discovery service so here I just just want to uh I can recommend something so before uh writing or typing the configurations directly in the discovery service since we don't have the discovery uh Discovery server dependency so we will not have the auto completion so the way to do it like or one of the ways like that I recommend what we can do is we can come here and start uh typing or like adding the properties and then we can take them and put them in the discovery service or in the conf configuration service inside the discovery service. yl file all right so here let me show you what I was writing so here instance and then we have host name so instance host uh name so now we mentioned that this one will be Local Host since we will run first of all the application locally and then at the same level as instance so it will be urea do client Dot and then register with Eureka so the register with UA it's by default true all right so this one is by default true and we want to set it to false when it comes to UA itself so like this means that the discovery servers should not register himself into himself so like you see you see this is this is the problem that's why we need to set it to register with UA also for this one you might find it sometimes uh in this way so like uh in a camel case like register with UA this is also correct and this this poses uh this pose this does not pose any any issue because this is the property that we have already in our um in our urea client config configuration Bean all right so like both of them are correct all right so the next one we have fetch registry so fetch registry will say false we would don't want to fetch the registry or the discovery service because now we are configuring urea itself so this will change when we implement it or when we add it to another one so again here as I mentioned we can use it or we can use this this way of writing so like if you see both uh or in uh in the documentation or somewhere somewhere else you see it written differently so this is not uh this is not false all right and then finally we have our service URL and for the service URL and then we have default so service URL and then we have default Zone so here we have like service URL and then default zone so this just to define the default zone of our urea service so for that we will use something like this HTTP and then colon SL slash and here we can reference to to this one all right so we can reference to uh to this variable so it will be urea do instance. hostname so as you can see if I navigate so like if I highlight it so it's automatically highlighting also this one all right so then we need our or we need another variable so we need to mention the server. port all right so we don't have it yet but we will add this property just in a few seconds slash UA and then slash so this slash is important okay so don't forget about this one now let's give our urea configuration let's give it or like let's specify the server Port so here I will add server. port and we will run this one over seven uh 8761 this this port all right so here you see that now we are pointing this port to this one so this is like using environment variables all right so this is the configuration of our urea server so as I mentioned before all we need to do is to take this one cut it and then we need just to place it in here so now we are 100% sure that we did not t uh we did not introduce any typo or we have something like this all right so now to make sure that the application is up and running and everything is well configured what we need to do so we will come here to Services all right so then so here we have the docker services but we can add other services so here we have run configuration type and we can search for spring boot okay so for spring boot so this will add or like will fetch and update automatically all the available services that we have so here this is our configuration service application and this is our Discovery server Discovery application so what we need to do is first to run our config server because we have all the configuration stored there and when we run another application we need to make sure that the server is up and running so here you see that when the application runs it will display the port of the application so now let's run out Discovery application and make sure that the application is up and running or not so here we are able to fetch the information and now all we need to do is to go to our browser URL for example and uh try to reach this this this URL with this port so let's go ahead and try it out so now in the browser I will try Local Host and 8761 and this is the spring ureka UI so for now we don't have any instances is registered to our urea instance or to our urea server but later on when we start or like when we start implementing one of the services and register them to the urea we will start seeing the list of the services registered in here all right so now that's why we me like when we mentioned that we don't want that urea to register himself into the registry service this is why we do not see anything so far all right so let's go back we can stop all of them and now we can move on to the implementation of our very first microservice all right so from our architecture diagram we are done with the implementation and configuration of our config server as well as as well as our uast server which uh fetches the information and the configuration from our config server and now we need to start implementing the different microservices that we have so here we will start with our customer microservice so the customer microservice will include few dependencies so among them like the spring uh or like the mongodb dependency and we need two other dependencies like as we did for yua Server we need first of all our config server client or config client in a in order to uh allow the customer micros service to fetch the configuration from the config server also we need to add the urea client so here we we use the urea server because we consider this one as our server or our Discovery server now we need the client in order to allow our customer to register himself into the urea server so now all we need to do is to create this customer uh micr service and start implementing the micros service for customers so let's go ahead now let's open this one and here inside services in the same way I will go to file new and then project so here I will call this one I will call call it customer so customer again uh Maven project so uh the package or the the group ID it will be com. alibu and the artifact it will be customer so then for the package name I will not leave it customer but I would call it e-commerce all right so like I would I will have the same package name for almost all the microservices all right so now we have this one let's go and click on next so first let's search for mongod DB so spring data mongodb so this is the first one and then we need to search for urea but for this one we need to select the yureka discovery client then we need our configuration service or uh config client for this one it's like and spring Cloud config so it's called config client all right and of course we need now our uh spring web so let's go back to the classic dependencies we need spring web we need also validation or the spring uh starter data validation and that's that's it all right so also do not or let's not forget our Lum book so like the famous annotation for Less uh boilerplate code and that's it so now let's go ahead and click on Create and import our project into as a maven project so in the same way let's go to Maven plus and now we have customer pom.xml and then click on open and this will start loading our customer module or customer project so it's not it's not a modular application but it's just monor ripo and in order to have all of them working as I mentioned all we need to do is to go to Maven and then add Maven project and select the pom.xml and hit okay all right so now let's open our customer project let's here open the resources and application. properties let's switch it to yaml and now let's add few configuration so first let me break this down same here and now it's called customer so our application uh name we will call it customer application or customer service for example all right so here I will call it customer service service and now we will start adding few information so first I will add a server Port so for this one I will run it over 80 90 so like the the the choice of the port numbers is like 100% random for me all right so like you can choose any port number just don't uh don't mix up when you when you use it uh in the future in the different in the different projects all right so now let's add some configuration so it's spring uh data and then we have DB and then we have a username so the username we chose alibu and for the password also we mentioned that it's alibu so it's in the docker compos file we have here or we need to define the host not hosts so it will be Local Host uh so here it's not additional hosts but just just host uh and then we need to specify the port which is 2707 for mongodb and the database so the database we want it to be customer all right so like let's call it customer and here we need to specify also the authentication database which is admin all right so this is the configuration all I need to do is to take this configuration from here let me just cut it and let's create in the config server Anders Source main resources and uh sorry configuration and let's create a new file let's call it customer Das so customer-service yaml and we can paste this one so here we don't need this application name because we only need it in uh in our or like in the customer service configuration itself so let me remove this one so the configuration looks exactly This Way Spring data mongodb and then we have the server Port of our application so now if we go back here we can just paste this one again and now we have our almost our configuration for uh for the customer servers now we just need to specify a few things so now we need uh our config and then import and now we need the optional uh option and then config server and now we need to specify the HTTP colon uh Local Host uh colon SL slash and then Local Host and then the port 8 time 8 all right and that's it so now we have the basic configuration of our customer micros service so before that let me show you something so now I will start my config server again and then I will start the discovery server and finally I will start the customer application without implementing anything all right so my config server is running let's run the discovery server and now we will run our customer server or customer application so then we will see first like if the application is up and running which is yes and now if you go back to the browser and refresh this page and here you see that we have our customer service all right and the status is up and this is where the application is available so like this is the link for the application so for example if we include a health a health endpoint or for example like a basic endpoint we will be able to access it via this URL all right so now we have everything up and running we are able to fetch the configuration and also if we uh try to go to Express normally we should see right here uh okay so for the database it's not yet available when we insert uh the First Data it will be also ready in here all right so now we are uh are done with the configuration so now let's move on to the implementation of our customer micros service all right so here just one thing uh need I need to mention so here like the customer application did not start correctly because we made a typo when we uh when we specified the when you specifi the host name so like it was specified as a loc a host not without the L so all I did is just to fix the typo all right so if you missed this one just go ahead and fix it so now let's clo close our config server and let's start implementing our customer application so in under sources main just Java so here first I will start by by creating a document so I will create a folder uh called customer and then I will create a customer class so customer. Java I can make this one full screen first I will add few annotations so all arcs Constructor and no arcs Constructor I need also a getter or let's first start or add the Builder and we have uh the getter we have the setter and now to make this one as a document we need to add the document annotation from DB all right so now let's add a few attributes as specified in the class diagram that we Define together so here I will have a private string ID and this one will be the ID of my document and then we will have a private string first name first name and then private string last name all right so be patient with me guys uh we have also private string email and finally we will have a private address address so for the address we don't have it yet we need to go ahead and create another document called address so so here let's create a class address in the same package and now let's specify few information for this address so I will copy all these annotations first so like no need to retype everything manually so here instead of document so it's not a document I will just add a validated to this one because we need to add validations later on all right so here for this we have a private string street so so this is what like the attributes that we Define together I want to have also a private string house number and then I want to have a private string zip code all right okay so this is the this is the two documents or like let's say like the the representation of a customer within a mongod DB database now let's start with uh creating a customer controller and from there we will create all the required classes and services and so and so forth so let me create a customer controller class let me make it full screen and let's add few annotations so rest controller first of all and then we have a request mapping and for this one I want it to be SL API slv1 slash customer and then we need the required ARS Constructor annotation and now first I will create a private final customer service so it's a class that we don't have yet and I will call it service so let's go ahead and create this class in the same package and all I will do is to add the service annotation we will go back or like we will come back to the implementation of this one later on so now the first thing I want to add a post mapping which is a method that I will use in order to create a customer all right so a public response response entity of type string so I'll just return the ID of the of the newly created customer so let's call it create customer and here we need to require few things so first we have our request body and this one it should be a valid one all right so like we need to add validations so I will call it uh customer request and let's call it just request so we don't have this customer request yet so all we need to do is to go ahead and create this customer request class or we can make it a record so let me uh create it as a record so create record customer and we will come back to the properties that we want to include later on so now after uh after this one all I need to do is to return a response entity. okay and then let's call our service do create customer method so create customer and then we need to pass our request so we don't have this create customer yet so let's go ahead and create it and it should return a string so for now let's keep it uh return all and the first thing that we need to do is this customer request object so let's specify few attributes for it so for this we will need exactly the same information that you specified here so like you can just change the names or change anything you want but just since this is just a showcase and we want to simplify things so that's why I will use the same attributes from our document all right so here let's add a comma instead and that's it so the address we will use the same address object so like no need to create another uh or like um to repeat another address object just to use it as a representation so just just to simplify things we will use the same one all right so now I will just add few uh validation annotations so here this should should not be null so like it's non not null and I will add a message for example customer first name is required let me duplicate it also for the last name and here we have customer last name in the same way we want we want it for the email so customer email is required and now I will use also the email annotation for the validation and here let's say for example customer email is not is not a valid email address is not a valid email address address for example and here for this address right here since we added uh since we added also in this one we added this validated annotation this means that this object will be also included in the validation so in case we add uh validation annotations it will be also considered All right so let's move on with the implementation of our service or of our first method which is create customer in our customer service so now I need to add my required ARX Constructor annotation from lbook and I will inject my first service so here I will create a private final customer service or sorry not service but customer repository which we don't have yet and let's call it repository so let's go ahead and create an interface as you can see here I'm selecting interface so let's create an interface customer repository so for this customer repository it's like simple one all we need to do is to extend our repository interface and here we have customer so it's customer and then string as as the ID all right we can close this one also we need our private final customer mapper and let's call it mapper of course we don't have this one so let's go ahead and create a class for it and let's give it the service annotation so if we need something or a method we will implement it later on so now let's go back to our customer service and let's finish implementing this first method so now first I will just create a VAR customer equals my mapper or we can do it in one line so it will be repository Dove not save all just save and then map ER dot to customer and then to customer from my request object so you can also uh you can also split it so it's like totally fine and then all I need to do is return customer. get ID all right so now since we uh we need to implement this one so let's go ahead and create a method for it so I will just rename it first to remove the typo so it's a customer and now let's implement this uh tool customer methods and here for example all I need to do is to return customer do customer. builder. build and all I need to do is to specify the information that we have so request. ID and we have first name which is first name we have also last name which is last name and we have address which is our address object so not address but request. address and of course we have email all right so now this is the mapping method also we can add here for example if you want to we can add if request is null we can whether return null or or return just customer. builder. build but for now let's say null for example as a null check okay so now we can go back here and create customer method is already implemented and done then we will go back to our controller and add a put mapping to update a customer so in the same way public response entity and this will also like this one it will return a void so we can have it void or we can have interrogation Mark so like both of them are correct so let's keep void for example since we do not want to return anything so I will call the method update customer and for this update customer we need of course our request body and this request body of course should be valid and here we have again our customer object request so our customer request object let's call it request and now let's implement this method so here let's call service do update customer and we need to pass the request as parameter and all we need to do is to return response entity do okay or do accepted for example accepted do built now we don't have this update customer let's go ahead and implemented so let's go back to our customer service and implement this update customer Method All right so now what we need to do I will create a a VAR I will call it customer equals my repository do uh find find by ID uh not the request but the repository doind by ID and I need to pass request. get get ID uh sorry request just do ID since it's a record and now or else throw so if we cannot find anything I would like to throw an exception so here I will create a new custom like I will create a custom exception and I will call it customer not found exception just because like I'm talking with the outside word so I need to provide or like to specify a dedicated exception so first let's create this one and let's create a class and here I will create it and under a package I will call it exception all right so here not extends X but extends runtime exception so I will add uh an equals and hash code uh annotation with call with call Super true and I will add for example a data annotation all right so here all I need to include is a private final string MSG or like message so this uh equals an hash code and call Super true because we just need to call the super class of this one all right so let's go back here and now I will just need to provide my string message for this custom for this custom exception all right so here let's say for example that uh no customer cannot update customer no customer found with a provided ID something like this all right so let's use string. format method and here let's say cannot update customer and then customer so let's fix this one and here no C customer found no customer found with the provided ID which is our percent s and here all I need to do is to add my request dot do ID so also now we can optimize this one by adding a static import and it will be in this way all right so otherwise if I find my customer stored in the database I will create a method here and I will call it merge customer so like uh merging a customer just to make sure that we do not override an existing uh property or existing value with a null value that's it so like this is the only the only reason so I want to merge my customer with the request and then all I need to do is to call the repository Dove and then I want to save my customer so now let's create this merge customer method so it will be void and now all I need to do is to perform few checks so here if string utils do is blank so if uh so let's use is not blank so if it's not blank of my request do first name what I need to do like this this merge method is uh is quite simple so here all I need to do is to do customer do set first name my request do first name that's it so this just we want to perform a check if we have the first name so we update it otherwise we do nothing so I will duplicate this method and just perform few changes so this one last name and here also last name and finally we have uh we have email and here let's set the email and also in the same way we can do for address so but for the address we cannot use this is not blank but if we say this one is not null so here we can say set address and request dot address and that's it all right so now we have our update customer we can also move on and start implementing our next method next let's Implement a git mapping to find all the customers so let's add a get mapping and then we will have a public response entity and this one will be a type of type uh list of customer response so customer response so we will create this object uh in few moments and then find all so we don't need any parameters and all we need to do is to return a response entity. okay of my service doind all so do find all customers so let's call it this way and semicolon so first we need to create a class uh like customer response so a typo again so here let's fix it customer response and our customer response will be a class including or like we can even make it a record so like this should be also fine so let's use records and for this one we will use almost the same as the customer resp request all right so except we don't have the validations so just uh sorry just copying and just to make things a bit faster all right so let's remove the validation annotations this one and also this one let's optimize the Imports and here is our customer response object so now let's go ahead and create the find all customers method and here all we need to do is to call our repository and find all the customers map them and and then return the result so here this will be return repository do find all and then let's stream over it and then do map so when when we map so we can call our mapper and then from customer for example or like maybe we can call it to customer response like feel free to uh to choose the one you want and then collect and then collectors do to list so we don't have this from customer uh yet yet so let's go ahead and create and this one should return a customer response all right so it's always uh a good practice to split the response and the request object so please go ahead and do and do that so let's open uh let's open our mapper so which is here and now let's create our our object or like our mapping uh information so what we need to do is to return a new customer response and now in the Constructor we need to specify the following information so it will be customer. get ID customer. get first name and then customer. get last name then customer not ID but email and finally customer. getet address and now we have our our method so now we will implement the next the next method so the next method will be a check all right so we want to check if we have a customer or if a customer exists by ID so it will be a get mapping and then it will be slash exists slash and then I need my customer Das ID all right so then all I need to do is to return a public response entity of type Boolean all right so this is just a check to see or to check if the customer is exists or not so I will call it exists by ID and here we need our path variable and let's call it customer ID as we specified it there and all I need to do is customer ID so now let's return a response entity dot. okay and then I need to call my service and then exists by ID all right so now all I need to do is to pass the customer ID we don't have this method yet let's go ahead and implement it so first let's fix the typo so all I need to do is to return repository do find by ID and then we need to pass the customer ID dot is present so is present will return true or false true if the customer exists and false if not okay so now we are done with this method let's now Implement another method so I can also copy this one because it's almost the same but it will not uh it will not be/ exists but it's just find a customer by ID all right so here let's call it find find by ID and again we will have a customer ID and here let's call this one find by ID let's go ahead and create the method in the same way so uh yes here we have a typo this will be a customer uh response and find by ID should also return a customer response so here in the same way let's return our repository. find by ID and uh if we have it let's map it to mapper Dot from customer or else we can throw an exception so here I will throw a customer uh not found exception so it will be a new customer not found exception and here in the same way I will use the format method so for example no customer found with the ID or the provided the provided ID and here let's say plus ID and here we need of course our percent s and here we have our customer ID let's fix this typo and we are done with this find by ID method so now I think we still need to implement one last method which is deleting a customer all right so now let's add a delete mapping and in the same way we need also this one like we need the customer ID and we can copy also this one just to make things a bit faster so this one it will be a response entity of type void and here let's say delete by ID or delete a customer all right we need also our path variable let's copy it from here and now all I need to do is to call my service. delete customer and then we need to pass our customer ID and then let's return a response entity do accepted for example do build now let's go and Implement our delete customer method and in this delete customer method it's like just one line so so it's repository dot delete by ID and then customer ID all right so here we have uh we have two things so first we have our customer not found exception and also within our objects for example this customer request as you can see in here we have validations so I think you got it guys but we need to think about handling the exceptions all right so let's create a class and let's call it GL Global exception Handler uh okay so let me move it to a package called I will call it Handler for example and here move to package and this is my package handler so for This Global exception Handler I will just create uh wrist controller advice to handle the different exceptions of my application so here I will call it rest controller advice like well not call it but just add this annotation and first our first exception Handler it will be of type customer not found exception. class so let's say a public response entity and then I need to return for example let's say just a string and here let's call it handle for example so let me make it full screen and here of course we need our uh customer exception class let's call it exp for exception so here all I need to do is to return a response entity and then I will add a status so here for example it will be not found so it will be part of HTTP status so HTTP status from org. springf framework. HTTP do not found and then body and here for example we can get the body from our exception. get message get MSG which will which will which contains already the exception or the message for examp example here like uh cannot update customer or uh no customer found and so and so forth so this is the first one the second one we need also another exception Handler so I just copy this one and here we need to catch the method argument not valid exception all right in the same way method argument not valid exception so now instead of returning a string I will return an object I will call it error response so this error response like we will not use this predefined interface but we will create uh all right so here we need to create a class and let's call it error response so this error response will contain or will hold few information all right so we can also uh make it as a record so we can like uh let's use records in here and we will have a map of string and a string so like string it will be the the attribute or like the failed ones and the the string it will be the message so for example it will be first name first name should not be uh like is required and so and so forth all right so now let's implement or let's go back to the implementation of this method so in order to do it uh let me start from here we will fix this part later on so here I will have first VAR errors so I need to get the errors or like I need to initialize an a map equals new hash map and a new hash map of string and string all right as we specified it in our record the the object that we just created so now let's get our binding results do get all errors and then all I need to do is to for each element uh for each error that we have in here we can use a Lambda expression and here let's say for example VAR field name equals my error Dot get get field so here what we need to do in order to do that we need to cast this object to to a field error so we have an object called field error and then we can get get field all right so this will be the field name and here we will create another uh another attribute or another variable let's call it error message equals error. get default message and now finally all I need need to do is my errors dot put and then I need to put it for the field name and the error message all right so now all I need to do is to return a response entity but here it will be a bad request and the body will be my new response error so here new response uh new error response and here all I need to specify is the errors that we extracted right here all right so now uh normally the customer service or the customer micr service is fully implemented now we can move on and see what we should Implement next all right so now we are done with the implementation of our customer microservice let's move on and start implementing the product so here just let me remind you and give you one small comment why I chose to start with customer and product and payment and so on so forth because here we see that customer does not have any dependency with other with any other microservice the same for product and payment and here for the order we need to query uh things and like we need to check data uh from the product microservice as well as from the customer and then we need to send Payment Processing or we need to start payment processing and so and so forth so this is the order how to start or like how I personally start implementing the different microservices so like within a team you will you will just split different microservices and each team will implement one and all you need to do is just to agree on the contract Service between each one and that's it all right so now in the same way let's go back here and let's create a new service so file and then new project and in the same way I will call it product now I will choose Java and Maven project so here for the for the group uh it will be com. alibu and then product for the package name I will use com. alibu . Ecommerce as we did before so let's click on next now let's add few dependencies so first let's start with the config server and here we need the client also we need Discovery server and urea Discovery client then of course we need uh web spring web and then spring data jpa we need also validation and we need also Flyway so like for this uh for this project we will use Flyway in order to perform a database migration and we will not rely on uh on creating everything from scratch or like we won't let uh the application create the database and the tables and so and so forth of course we need our postgress SQL driver and finally we need lbook so this is our project and these are the dependencies that we need so let me check if if we need uh another thing or like another dependency but I think this should be enough if we forget something we can just add it later on so now all we need to do is to click on Create and in the same way let's go to Maven here add a new project and let's select product and then pom.xml and now we will have our product added here as a maven project so let's uh reduce this one and now we have product so the first thing let's go and change this one to EML file and here as you can see we have already a folder called DB and inside it we have another folder called migration and this one is automatically created when we integrate or we include the Flyway uh dependency so now I will just adjust this one so name and let's call it produ service okay so we made the typo somewhere so it should be product and let's also rename this one so let's rename the module product and also let's rename the the directory to product okay so now this is should be fine and if we check here we have product product product so let's also change the name here let's like fix this typo and everything should be fine all right so now before moving and adding the configuration into our config server for this product service first let's connect to our database so in here let me make this one full screen so here just adds and then search for postgress SQL otherwise if you don't have the ultimate version you can use the postgress admin for that so here as we mentioned before it will be alibu alibu as username and password as specified in the docker compose file and here we see that we have a success so let's apply it and now let's add a schema so here we have postgress SQL and here we need to create a database so I will right click and then database and then we call it product so product database and then let's click okay so now we have our product database let's go ahead and select it so I think I created it in the wrong place so let's recreate product database in here okay so already exists let's just try to display it and here we have ah okay so here we have product all right now it's there so we have our product database so here just I need to mention something which is which is very important so locally or on my local machine I will use uh one instance or one database instance to create all my databases so like I will use just this postgress SQL instance in order to run all the databases but and and this just because um I'm running out of resources and like my laptop will not support creating three or four instances but for your case and mainly when you move to production be sure on or make sure that each microservice has its own database all right so like uh services or microservices they should not share the same database all right so now we have our product database we can now move on and start the configuration of our product service so again let's go to config service and then Source main resources and then configuration so here let's just remove let me remind you we called it product service and then we need to create a file product service. yaml all right so now when we uh when we first configured everything like the customer service Discovery and so on so forth we just forgot one small configuration so here normally we need to um to tell our configuration servers few things for example here uh in this place or also in the custom customer also we need for example first we need to specify the urea instance so it's by default it will try to connect to it if it finds it otherwise it will not be able to find it also there is a property that we should not or like well it depends on uh on the on the application or what or on what what we want to implement exact so here what I will do since we know that uh configuration files they inherit uh they inherit from each other so I will create here file and then we call it application. yaml all right so all the other configuration or all the other yaml files will inherit first from this one for this I will first uh specify urea and then instance and then host name so here I will specify uh the host name of our um of our urea uh server so it will be Local Host and then we have UA and then client and we have the service- URL so you remember uh when we configured our UA server we used Service With Ur service URL with the capital u and this time we can use it in this way all right so here we need to specify also the default zone so default Zone and now all we need to do is to specify HTTP colon sl/ Local Host and and then 8761 which is the UA Port slua all right then so here I will just give a default name um name for example or or let me skip this one okay so now I will add uh another spring property which is the following that I mentioned spring cloud and then config and then we have a property called override system properties system. properties and this one is by default true so I want to set it to false because I don't want to override any properties so this means what this means when uh we have here for example our product service. yaml and here if uh if we override something or like um if we have another property defined already in here so when we fetch the configuration from the config service it will override all the configurations that we have in that specific service so this is is what we don't want to do so that's why I set the in here the the spring Cloud config override system properties equals false all right so now we are done with uh with the main or like with the generic configuration we can go back to our product service and add this configuration to our product service so in the same way we did before let me close all tabs and in product let's open our application. yaml let's leave the spring uh application name and now all I will do first I will add a server port and for this one I will use 850 for example and now I will add some configurations for our spring application so here we have data source so it's data source and then we have a username or first let's start with the URL as always so let me make it full screen so URL it will be again jdbc colum post gr SQL and then colum SL slash and then the port so Local Host and then the port for 3 uh 4 5432 and slash product so product is the name of the database we just created so username alibu and password again alibu and we need our driver class name which is org. postgress SQL do driver so now let's move on and add some jpa properties so we have jpa and we have hibernate and then we have ddl oo so for this one all we need to do is just to use validate because we want to rely on Flyway to create uh the schema for us then we have database we can specify the database as postgress SQL and then database platform and we need to specify the dialect so org. postgress uh sorry sorry or. hibernate do dialect do Post gr SQL dialect so this is the dialect that we will be using now let's add some Flyway configuration so here we have Flyway and then we have our Baseline on migration so it's by default false so here it like this one means like whether we want to automatically call the B the Baseline when migrating on empty schema so here we want to set it to true and also we want to enable it so it's by default it's true but I just want to set it in case you want or we need to disable Flyway so here let's say Baseline description so the Baseline this description how we want to uh like how we want to describe our Baseline and here let's say Baseline version by default it's one and I want it to start from zero and here all I like I can also specify the user and the password and so for so the user and the password should be the same as this one okay so now to make it Dynamic I can use uh spring so let me close this one spring. dat source. user name uh sorry here it should be username and here the same way spring. data source where is it okay so spring do data source. password so like it will be using so every time we change this one we don't need to change it again in here so like this one will reference this property right here so now we have all the configurations that we need let's take this one and let's move it or put it in our product service except we need as always we need to remove the spring application name because we need it only in here all right so now spring let's just leave application name let me make it full screen and also we can delete the server. port so now we have uh the base configuration of our product service now we just need to add few things right here so now I need to add spring. config do import and then optional and then config server and our config server is located under HTTP colum SL Local Host and then for four * 8 that's it so now our product is ready or our product service is ready now again if I start all the applications we should see everything up and running and all the services registering into urea so what we need to do next is first we will start by creating the entities and and uh create the schema or the script for creating the database and even inserting some data and so and so forth so it will be a classic implementation of our product microservice all right so now let's move on and start creating our different entities and start implementing our application so here in our product micros service or product service let's go to main Java and then let's start creating the two entities that we need so first I will create a package called Product and then a product class so this one let me make it full screen of course we will need few annotations so I will need all ARS Constructor and no arcs Constructor and the Builder annotation as well as I will need getter and Setter and finally I need the entity annotation so this is our product now we need to Define few properties so here I will have a private integer ID and this one I will give it the ID annotation as well as I want it to be generated value all right then as we mentioned before a product has a private string name so like the product name private string description and then we have uh a private let's say double or even we can use uh well so we can use double for available quantity then we have a private big decimal so uh like one one advice guys when you work with money like with currency or like with attributes that that represent pricing or money it's better always to go with a big decimal class since it has a lot of methods and it's well optimized for for this case so let's call this one price and find finally we will have a private category so we don't have this class yet but we will create it and let's call it category so for this category it will be a many to one relationship from the side of the product and I will add a joint column call it name and I will give it for example category underscore ID so for this case let's go ahead and create our class inside a new package call it category all right so now this is the new package so we have category and we have a product so let's go ahead and create or like prepare the the product or the category entity that we just created okay so I will just copy these annotations paste them in here and now let we can also copy the ID from here and I guess also name and description something like this so I guess we can copy all this and this will be the representation of our category and then of course we have a private list of product let's call it products and for this one it will be a one to many annotation and then M it by category so category here like this mapped by should be exactly the same name of this category variable uh or attribute right here also I will add some cascading styling uh type sorry it will be a cascad type do remove so when I remove uh when I remove a category or when I when I remove a product I want to remove all when I remove a category I want to remove all the products that are related to this category so like there is no reason behind this one it's just a personal choice I don't know why but it's just a choice otherwise like you can remove it or we can even just get rid of this one all right so now we have the two entities but we don't have the database or like they are not presented present yet in the database since we chose that we want so here if we open the product service in Flyway uh here in in this configuration we said that we just want to validate our schema we don't want to create anything so let's start by a script that will init or create our database so what we need to do let's go to resources and then inside this folder DB migration so if you forget to add the Flyway uh dependency from the beginning so you will not have this folder created by default otherwise the way to do it just create a fold folder called it DB and then inside the DB create another folder fer call it migration don't create a folder and call it db. migration because this will not work all right so now let's move on and let's create our SQL script for initializing the database so here right click and then file so now within Flyway I already provided um a video in my YouTube channel about how to integrate or how to use Flyway and the different configurations namings and so and so forth so here it will be the version so like just for ver versioning and now we need two times underscore so this is important and then the the script name or the file name that you want to add so database and then SQL so let's make it full screen and here I think we can also choose the dialect for post agress SQL and the session we can we can leave this one to default okay so now let's together create the script first we will start by creating our category table so I will do create table if not exist so if we don't have the table we want to create it and our table is called category and now let's open parentheses and let's start providing and defining our attributes so we mention that we want to have an ID and of type integer of course it should not uh be null since it since it's an ID and then it's a primary key all right then we have description description of type varar and let's say like by default the length will be 255 and again or like finally we have a name for example or like name and description description name it should be the same thing all right so now we want to add another table so create of course here we don't forget the semicolon so now create table if not exists product now let's Open brackets and let's start defining this one so we can also copy these three attributes which is the ID name uh and description and then we can Define the rest all right so the next one is our available underscore quantity let's not forget the comma here available quantity and I want it to be double and with a Precision uh and also it should not be null all right and then we have our price uh not primary key just price and I want it to be a numeric type and let's say 38 and two for precision so like it to it can be up to uh 38 digits on the left hand side and two digits on the on the right hand side now we need to add the the mapping or the relationship between our product and our category so here let's say we will have a category underscore ID as we named it in the category entity uh sorry in the product entity when we created a join and this one I want it to be of type integer and I will add a constraint so let me move this one so I want to add a constraint so for the constraint we can call it anything all right so like we can call it or like we can give it a random name or like uh primary key or for example uh foreign key uh category constraint or something like that and this is not a problem and then references category and that's it all right so again semicolon so here maybe let me call it foreign key one and with something something else all right so now uh we know that PO SQL when we have generated values it uses by default sequences so let's create a sequence so create sequence if not exists of course and here we know how postgress SQL or like how hibernate uh names the the sequences so it will be the table name underscore s so it will be category sequence and then increment by 50 since we know that the the default incrementation of the sequences is 50 in the same way let's create the product sequence so product sequence increment by 50 now if I start the application I should see my uh my two tables getting created all right so now if we go ahead and start the application we will see and we will find that the two these two tables are getting created with the foreign keys and with all the dependencies and all the reference ing that we created all together okay so let's go ahead and try this one first I will start my config server since there I have the configuration so I need this one to be running first now I can run my product application and see if I'm able to create this one okay so could not find product application I think when we renamed when we renamed it something happened all right so let's try to run it from here and now we have our ah okay that's because we did not rename this one so product application and then refactor and okay now it should be able to run it all right so all I did uh like here click or select the product uh Maven project click on un link Maven project and then import it again and the problem will be fixed so now let's go on and let's restart our product application so here we don't need uh the discovery service it might be also throw an exception but it's not a problem this is not what we want to do so our application is almost up and running so let's go and check the database if something was created or not so it's if we refresh in here let's select the public schema and see if we have tables and this is the case so we have our category table and the product table so for example for the product we see that we have a foreign key category ID also we see this Flyway schema history and this Flyway schema history will display the history of the different uh of the different uh versions and SQL scripts that we will run within our application so now I think uh we made some good progress and now we are ready to move on and start implementing our product micr service all right now let's start implementing our product controller so I will create create a new class and I will call it product controller so here I will add the annotations rest controller and my request mapping and it will be SL API slv1 SL products and of course I will need my required ARX Constructor to inject my dependencies and here we will need our private final product service which we don't have yet and we will create it in a few moments so let's go ahead and create the product service class in the same package and I will give it The annotation service and also the required ARX Constructor and we will come back to the implementation of this one later on so now I will first start by defining the the method that we will have or we will need in our product controller and we will start by the first method to create a new product so this one it will be a post mapping and it will be a public response entity of type integer since our ID is of type aniger so when we create a product all we need to do is to return the ID or just return accepted so both are fine all right so here I will need my request body and it should be valid since we will have uh validations and I will call it product request so let's call it request and here let's go and create our product request record let's leave it empty for now and we will add the information later on now all I need is to return a response entity. okay uh okay not accepted and here I will call my service do create product and of course I need to pass the request as a parameter all right so now let's go ahead and create this method leave it empty and we will come back for it later on so the next one we need another method to purchase products so we need to pass a list of product purchase uh request for example and it will return a list of product purchase response so like the the list of the products that we were able to purchase so it will be again a post mapping and for this one I will add purchase as uh as a path and then it will be as mentioned a public response entity of type list of product purchase response and then we call it purchase products so for this one as mentioned we we will need our uh request body which is a list of product purchase request let's call it request or well not requests but just a simple request this should be fine and here I will return a response entity do okay and then I will call my service do purchase products and then I will pass my request as a parameter so the first thing I will create a record of this object called Product purchase uh response and then I will need also another object let's also use a record and it will be our product purchase request so now let's go ahead and and create and prepare this method so it will return a list of product purchase response all right next one it will be just finding a product by ID and another one to find all products so this one it will be a get mapping and here slash and then we need our product ID product ID and then public response entity of type product response so here we will have another object so we need to create another object product response and let's call this method find by ID and we need to pass a path variable and let's call it product- ID and it will be of type integer product ID so now all I need to do is to return a response entity. okay and then we need to call our service Dot find by ID and of course we need to pass the ID as a parameter so let's go ahead and create our product response let's use record also in here and now let's create our findby ID method now finally the last method is a get mapping again and here it will be a public response entity and here it will be a list of product response and find all so in here in this method uh don't forget to add pagination we will add it later on but for now like we need to have it paginated all right so we need to return a response entity. okay and then we need to call our service do find all let's create our find all method and now we can start implement the different parts of our controller so in the same way here if we go to product we have have this name description available quantity and we have price and the category ID this what we need to pass as parameters to our to our uh record all right so this this is the product request and let me paste them in here and also if I use uh when I use uh shortcuts you can see you can see it in here in this in this popup all right so now let's add comma and finally I will add my integer category ID so now let's add some some validation annotations the first one it will be a not null and I will add a message and for example product name is required just as a simple message the same for the description product description is required the same for the quantity so like for the quantity we want it to be uh positive so like let's use the positive annotation and here we we will say like available quantity should be positive so available quantity should be positive and in the same way we will use it for the price and here let's say price should be positive and finally we will have we will add the not null annotation and here product category is required so product category is required so this is the first object now we can move on to the product service so let's implement this one so we will fill uh the list of um of Records one by one so now let's start by implementing our product service method to create a new product all right so here the first thing we need to inject our product repository that the one that we don't have yet let's call it repository and we need so let's make it final also and also we will need a private final product mapper and let's call it mapper so we don't have yet these two classes so the first one it will be an interface and then we need to extend jpa repository and of type product and integer so this is so classic we we already know that now we need also to create a product mapper class and let's give it the service annotation so now if we go back here first we need VAR product equals mapper do2 product and we need to pass our request as a parameter so let's go ahead and implement this method so this should return a product and all we need to do is to return a product builder. build and we need to set the different parameters so ID it will be request ID and we have name it will be also our request. name description it will be also description and we have a price it will be also the price so request. price we have also available quantity and it will be available quantity and we need to set also the category so the category it will be also another object category. builder. build and here all I need to do is to set the ID of my category out of my request all right so maybe let me break this down so it will be more visible and more readable for you and this is the first method or the first mapping method so once we uh once we map the product all we need to do is just to save it so let's return our repository do save so it's repository Dove and then product do get ID not save all it's just save. get ID so this is the create product then let's implement the findby which is also an easy one so here all I need to do is to return my repository. find by ID and then I need to pass my product ID if I have it I need to map it so I will call my mapper do to product or from product or to product response to product response and I say I can say or else so or else throw and I can throw for example a new entity not found exception and I can say for example product not found with the ID plus my product ID and then we need to implement these two product response method and this one it will return a product response and this product response it will contain few information like we have for the other one so it will contain like the ID the name description available quantity the price category ID category name and category description so first let's go to this uh record and we can paste the information that we have in here so let me clean this up and then we will have our integer category ID then then we will have a string category name and finally we will have a string category description so this is my product response now we can go and implement the mapper so here all I need to do is to return a new product response and here all I need to do is to pass this information so product. getet ID and then product. getet name product do get description and then product. get available quantity product. get price and now I need my product. get category do ID okay so this may be a little bit annoying uh all right so then we have our product. category. name and finally we have our product. getet category do description and this is the mapping entity uh the mapping method sorry so we can in the same way we can do the find all so this one it will be repository do find all and then I need to stream and map so my mapper to product response and then collect do collect collectors to list now let's go and implement the purchase product so purchasing a product we need to perform few uh few checks first we need to uh to check if we have all the products and we need to check the SI the we need to check uh we need to check if we have the available quantities for all the products we need to perform few checks and then if everything is fine we can go ahead and start purchasing our product so let's go and start implementing this one so the first thing I will need is to extract the product IDs from my request object so here from uh my product purchase request it will be a record and in here I will add a few information so first I will have an integer product ID so product ID and I will need a double quantity so this is all I need in order to purchase a product so here what I want to do is to add a not null uh annotation so with a message for example product is mandatory so like I'm trying to change a little bit the messages and here quantity quantity is mandatory all right so now we have our purchase request object ready so now let's first as I mentioned let's first start by extracting the IDS all right so here first I will create a a variable I will call it product IDs equals my request and then I need just to stream over it and map my objects so in uh I want to map it so I want to get my product purchase request. product IDs and then to list all right so this will return a list of product IDs okay so then I need to check or like I need to uh to check if I have all these products available in my database so for example if we pass an ID that does not exist or like a product ID that does does not exist in our product service we should block the request and return an exception so here I will create another variable and I will call it stored products just to say that these are the products from the from the database and it will be a repository and I will create a method and I will call it find all by IDs or by ID in so like I need to pass a list of uh product IDs and then I will order it by ID all right so here I will pass also my product IDs as a parameter so we don't have yet this method so let's go ahead and create it and this will return a list of products all right and that's it so now if we go back here what we need to do so the first check we need to check if my product IDs do size is different from my stored product do size so this means that for example if the use user wants to buy or to purchase uh five products and when I query the products and the database I only get four so for example let's say that the user wants to buy the product with ID 1 two and three and in the database in here I only have products with IDs one two and that's all so I don't have a product with an ID equals three so in this case we need to block the purchase request or the purchase process and return an exception to the user so let me delete this one and now in this case all I need to do is to throw a new product purchase exception so we will create this exception right now and let's say for example one or more products does not exist and that's it so we don't have yet this uh this exception so let's go ahead and create it so I I will create a class and in a package called exception all right so this is create a class and exception okay I think I will create it manually because my IDE I think it's just making some problem so I will create a class in exception. product purchase exception so this let me make it full screen extends runtime exception and all I need to do is to add a Constructor with string message and that's it all right so if we go back here let's import this class and we are done with this part all right so once we make sure that we have all the products available like the the products that user wants uh to purchase they are available in our database so here I will create a VAR stored request equals my request do stream and I will just uh sort the IDS so here I will I will use the sorted method from the stream and I will use comparator do comparing and I want to compare my product purchase. product ID so like I want to sort them by by ID and then do two list now we can start performing or like we can start purchasing the different products so for that I will add a purchased product s equals a new array list of type product purchase response product purchase response and now all I need to do is to Loop over my list of product so here I can return my product purchase response or purchased uh sorry it should be purchased products and now all I need to do is to have a for Loop so for in I equals z i uh smaller than stored products do size and then i++ so here semicolon and now all I need to do first I will create a VAR product object equals stored products. get at the index I and then I will create another variable which is my product request equals my stored products. get I so like here like the product request and the product both of them they I will get them from the stored products so uh here it's stored request not the stored product so it's stored request so let me also rename it so that's why I couldn't see it all right so stor the request and then all I need to do is I need to check if the available quantity so like I'm doing this just to check if I have the available quantity is less or equal to the requested quantity all right so here I will perform a check so if my product. get available so like typos product. getet available quantity if it's less than my product request Dot quantity so in this case we know that we cannot purchase this product so in this case I will throw a new product purchase exception and now I will say for example unsufficient stock quantity for product with ID with ID let's fix this typo so for product with ID and here product request.get do ID so this is the check that I want to perform I need to check that we are able or we have a sufficient quantity to purchase this product so if this is not the case so if the quantity is is sufficient and is available so here I will create a new uh like an another object I will call it new available quantity so like I need to update so for example let's say that the product we have on the database it has uh 10 10 uh available quantity equal 10 and now I want to purchase three of them so like I need to update the available quantity and make it seven all right so now equals product. get available quantity minus product request do uh do quantity all right so like we need to update this one and then all I need to do is product do set available quantity the new available quantity so just updating the quantity and then I need to call my repository Dove and I need to save the product and finally so here what I want to do I want just to uh to fill this purchased products list once we purchase a product so I will do my product uh my purchased products do add and now I will call like I will create uh a mapper or like a method uh in the mapper so I will call it to product purchase response and I will pass my product object and also the product request. quantity and that's it so now in the product purchase response it will be also a simple one so here let's create this method and now let's also fill this object so since we didn't do it yet so I will have an integer product ID and also I will have a string name so like this is the information about the product that we purchased uh a string description and then we will have a big decimal price and finally we have a private or like a double all right so this is my object and now the mapping method will be super super easy all right so now all I need to do is to return a new product purchase response and here I need my product doget ID product. getet name and then product. getet description and finally we need the price from the product. getet price and finally we need the quantity that we passed as a parameter so this quantity right here all right so now once we finish this one this implementation so this is the end of this purchase product so here let's just uh resume and re explain the method so first of all I need to extract the list of the products ID since I need to check that all the the products that we want to purchase they already exist in the database so that's why we created a method find all by ID in so like ID in we we need to pass a list of uh a list of integers so in here as you can see in here so it can be a list of integers or we can also pass a a simple uh a simple array okay so we can close this one yep all right so then if the the size of the two list so this products ID and the stored products ID IDs so like I'm talking about the sizes if the sizes are different we know that uh that the IDS that we received in parameter we have among them one or more product that does not ex exist in our database then first I stored uh I I extracted the IDS of my storage request and then I have uh I created an object of purchase product and then we need to perform a check to to make sure that the quantity that we want to purchase is already available for that product so for example if you if I want to purchase uh five pieces I need to make sure that the product has already five pieces or more available in uh in my database and then just uh updating or recalculating the available quantity and update my product and then just return uh the list of the purchased products all right so after implementing the product methods or like the product service methods we need to handle some exceptions so I will just make it uh a bit faster so I will go to customer and then Java and I will copy the full Handler package and I will paste it here in my product so here I will paste it and now we have our Handler so we have our global exception Handler and now all we need to do is to adjust it a little bit so here we don't have this customer not found exception but if for this case we want to add uh our product purchase exception. class and in the same way here product purchase exception class and for that we want to return a bad request so it will be a bad request and now instead of get MSG it will be do get message also I can import this one stat Ally and then we have this method argument not valid exception which also uh stays the same we don't need to change it and we need to add one other exception Handler so let me duplicate this method right here and now all I need to do is to uh is to manage or like to catch the entity not found exception. class so let's say entity not found exception because here in our service in our product service in here we throw uh when we get the find by ID we are throwing the entity not found exception all right so let me bring it back as full screen so this is the one so like even the entity not found exception we need just to catch it and return a bad request or also we can since our exception Handler accepts uh a list of exceptions we can add uh another like we can add um also as here as a the second parameter our entity note found exception but for me I always want to separate things in case I want to have something specific so in this case we are able to uh to handle our exceptions so let's optimize the Imports so we get rid of this error and now we need to do one final thing so here in this database migration we already created one first file to initialize or to init our database like to create the schema of our database so then I like I will ask chat GPT and I will provide this uh this uh SQL or SQL script file and I will ask chat GPT to uh insert few data for me so first I will create my file and I will call it V2 uncore like two _ insert uncore dat. SQL so I will just um ask that GPT and copy and just paste the result all right so this is the result from chat GPT so this is what uh what he mentioned and here let's say postgress SQL and the default session so this will be or this script will insert few data into my database so let's go ahead and try this out so again we need Services we need my I need my config servers to be running and I will also run the discovery so I will run all of them so also we can see that we have all uh all the application or all the services getting registered into the discovery service application so I will start the customer and finally I will start my product service so let's wait for it so now everything seems to be fine so one the first thing that I want to make sure that we have the data available in our database so if I open the category we see that we have computer keyboards Monitor and so on so forth this is the data that we just inserted and in the same way we have this list of products with available quantity prices category and so and so forth all right so also if we go to the browser and refresh this page we see here that we have customer service and product service both of them are up and registered into our Discovery service so now the next step is to go and Implement our so let's go back to our diagram right here so we need to implement this order micros service and then payment and finally we need to implement the notification and after that of course we will set up gafka and so on so forth and we will test the application and of course before that we need to set up our API Gateway so let's move on and continue implementing our application all right so now we made good progress so we are done with the customer microservice as well as the product microservice so now we can move whether to payment or to the order microservice but we will start with the order since it's it's related to product customer and also payment so here in this one we will implement the relation or like the communication with the product microservice and the customer microservice and I will show you two ways how to do that then the order microservice needs to communicate with the payment in order to initiate a payment but this one or this functionality we will do it or like we will implement it once we finish the payment mic MOS service we will come back and update the order microservice so we will leave it just as it to do as well as we need to uh establish an as synchronous communication between the order microservice and our Kafka broker so also we will see how to customize or how to create uh a Kafka instance or to how to start a Kafka container uh from our Docker compost file or like using Docker since uh since like the the tutorial that I provided about uh Kafka was like installing locally kfka so now it's the time to see how to install and set up kfka on Docker compose and using Docker all right so now what we need to do next is first to create the order microservice configure the order microservice and then we will start implementing it one by one so in the same way I can close this one so here let's click uh on new project and then in the same in the same path so here let's call it order and now of course Maven and Java a language so here for the group it will be com. alibu and the artifact it will be order and here in the package I will call it in the same way eCommerce so Java 17 andage our file so now let's go ahead and select few dependencies so the dependencies that we will need for this one are like as as always so first we will need our spring web since we want uh web application of course post SQL driver and bring data jpa since we will connect our micros service to to uh to an SQL database and we need of course our spring starter validation and as well as Discovery service clients like our urea Discovery client and we need also our config server client so here we need the config client also uh let's not forget about uh about lbook as always so let's select also lbook and now for the for the synchronous or for the yeah for the synchronous communication using the HTTP protocol we will use two different ways so like I will show you how to implement it using rest temp plates and also how to use open F so let's search for open Fain so maybe let's search for Fain so here we have open F so all we need to do is to select open fan and I guess that's it with with the starters that we need for this microserver so let's go ahead and click on Create and if we need something we will add it later on all right so let's click create so in the same way let's go back here and then file module from existing project and let's select our order and then pom.xml file so now let's click on open and we will have our project loaded in here all right so now as I mentioned we have our conf we have our project so the first thing we need to do is to add the configuration so let me change this one to a yl file and then of course we need to change the structure let me make it full screen oops I made the typo so I need to rename the file so it should be yaml and then we have spring application and then name so our application name is order- Service as always so now let's go and see what are the properties that we need to add so the first thing we can go back here to our config server and then main resources configuration and we can take for example the product service and we can take all this data source part all right so maybe we can copy all this one and then we can remove what we don't need all right so here I will paste everything so just me let me move this up okay and we can remove the Flyway we don't need it and here we have spring data source and then application name all right so here it will be order instead of product and the username and password are the same so here uh I will use create or update so like we can also we can also add Flyway to uh to the order micr service so now that this is this is what we need but I just will need to add few other dependencies so for the port let's change it to 8070 for example so here let's review uh what we have so we have spring data source we have the use URL username password and the driver class name we have the jpa so we defined the ddl auto we defined the database the database platform and here of course we have the application name since we will leave it in this file and we will move this configuration to our config server so let me remove this extra spaces so in here I will just start defining few uh few other properties so I will call it application and then I will create uh like a Sub sub naming for example config and here I will create first my customer URL so this will be the URL to connect to our customer micros service so it will be HTTP colum Local Host and then the port so here the port there is something tricky in here here so normally we should here so for example like when we think about it for the first time we say okay like I will just Reach the the customer service using this port right here but since in our application let me remind you here in our application what we have so we can connect the order microservice directly to the customer microservice using its uh address and Port since both of them or like all the microservices are in the same private Network so we will be able to reach it but we know that each microservice will register to you to the UA server all right so here we have two options whether to fetch the information or to fetch the uh the microservice URL from the urea server or using the API Gateway and the question is why so why we need to do that why we should not directly use the the address and the port of the specific micros service so when we talk about scaling the application so for example if we have high demand on the customer microservice maybe we want to scale it up to 2 3 4 5 and N instances at the same time so in this case the customer will have multiple instances with multiple or like with different port so the port can be also randomly generated so we will not have an idea about which Port we need to use in order to connect to our customer microservice for example and this applies to all the other microservices by the way so here here one of the ways is always to reach the microservice using the API Gateway since the API Gateway contains also a load balancer so the API Gateway will know all the instance all the instances of a specific uh microservice so the order will connect to the API Gateway since it's public uh it's a public URL and it's available publicly and then the API Gateway will redirect the request to the to the microservice with a load balancing also all right so this is how we need to think about it so for now just uh for the first phase I will just use the port of this one because like maybe we we we want to start testing it but later on we need to change it all right so like we maybe we we will test the flow before even finishing the whole application or maybe we will test it at the end so for now just I will set it to 8090 as as I set it up in here so like the service port of the customer service it's 89 and we know that all our apis are under a/ API slv1 SL customers all right so this is the first one the second one we need also another property so here we need the product URL so product URL in the same way we we will do it as as we did before so we will use the 850 port for this one so let's go back in here and 8 50 and it will be / API slv1 SL products and as I mentioned later on we will change this port to the port of our API Gateway and I will also um just here uh I will try I will make it just in advance and I will create the URL or prepare the URL for the payment micros service it's not yet implemented but we can we can use it so here let's say it's payment since we follow the same uh naming pattern and here for the API uh for the payment uh payment service we can use for example the available Port like uh 8050 let's for the payment let's maybe say it's 8060 for example all right or what we can do in here so we can just set it to this one so for the API Gateway I personally I always use the port uh the port 8 uh 3 * 2 or like 8222 so we can set it from now to the port 82 2022 so here just if uh if you are running the application locally without the API Gateway so you can specify directly the port in here otherwise just specify the port or the URL of our API Gateway so let's leave it this way and we will come back to it later on so now all I need to do is to copy this one this configuration and now in the config server in this place all we need to do is to create an order- service. yl so this is the yl file let's paste everything in here and all we need to do is to remove this application. name now if we come back in here let's move all this and leave only the application. name and we can also and we will also adapt and adjust the rest all right so now let's finish this one so here we need our config do import so we have optional and then we have config server and we know that our config server is under HTTP colum Local Host and then the port 4 * 8 all right so this is uh Local Host like the same type as always so here we have this is the configuration of our of our application all right so now our order micros service is ready to use and also just to remind you here we have in the configuration we have this application.yml that all these configuration files will will inherit from it all right so now we can close this one close all tabs and now we can come to the order micro service and start implementing it all right so the first thing that we need to do is all right so here let's open again the order Source main Java and the first thing that we need to implement is to create the entities all right so let's start with the order entity so I will create new class class in a package called order and I will create a class called order let me make it full screen and now for this order let's add few attributes we will come back to the annotations later on so here I will have a private integer ID and I will need a private string reference and then I will need a private big decimal total amount so this will be the total amount of the order amount and then we will have a private payment method so this will be an inam containing all the payment methods that are supported by our application so we will create it in a few moments and then here let me also show you again the domain diagram so here we have our order which is linked to our customer and we mentioned before when we work with microservices and when after applying the ddddd domain or like the domain driven uh design here if we have a relationship all we need to do is to take the the key or the ID of one entity and make it as a as a a foreign key to the other entity so like we don't need to add a constraint since we cannot add a constraint since our databases are not connected or like another the databases but the entities are not are not connected or are not under under the same database instance or they are not even located in the same on the same server so like we we can have for example the customer database on an AWS the order database uh on Azure for example and we can have another one uh deployed locally or like on a VPS server or like uh on premises server and another one for example on Google and so and so forth all right so now after the payment method what we need is a private string customer ID so a string because I know that my customer ID is of type string since the customer application or the customer micros service uses uh uses a nosql database so I know because like we need to know this information um in advance so for example if you are not sure I think string can hold all all the types of uh of IDs all right so then what we need to do we need also a private list of order lines so here let's say order line and let's call it order lines so we don't have this entity yet we will created later then I will have a private local date time so this one it will be created add so I want to add some some auditing also uh I will need a private local date time last modified date modified date and now let's start creating our our other uh object so first let's start with the payment method so I will create it as an inam in the same package all right so for the payment method let's for example Define few payment methods let's say that our application supports Paypal payment uh credit card for example you can Define as many as you want uh Visa card and let's say for example also m card I'm just trying okay so let's add Bitcoin that would be uh that would be nice all right so here let's say these are our uh our payment methods so this is since this is Anam we need to add the enumerated enumerated annotation and here let's say it's of type string we can also um import this one statically so add static import and now we have uh we have order line so that we need to create the order line so let's first just create a class and and I we create in a package and I will call it just order order line so I will change the package name and now we have our order line we will come for it and implement it later on okay so now we need to start adding few annotations so first I will add the all arcs Constructor the no arcs Constructor uh so like maybe you don't need those but but it for me it's just a habit so I will add the Builder annotation uh or again like getter like the classic annotations like the classic lbook annotations now we need the entity annotation and then we need to add an entity listener so here for the entity listener we will use the auditing entity listener class and here we will add finally add table annotation and we will give our table a name so let's call it customer underscore order all right so here I'm using customer order or like this table annotation since the E the keyword order is already reserved so that's why I called it customer order so here we need to add the ID and also generated value but we are not done yet for this created ad or like created date maybe let's make it uh like let's rename it this way so it will be created date and for this one I will add also the colon annotation and I will say it's updatable false I don't want it to be updatable and also Noble false so let's duplicate this one and for this it will be last modified date and now I will say insertable false so like I don't want it to be insertable and of course it can be notable all right so here for the order line we will like we will change it or like we will add the attributes in few seconds so we know that one order um one order can figure out in many order lines so it will be one to many and we need our maed buy so I will call it order since I know like we will call the attribute order uh order in the order line and now we are done with the implementation of of our order entity so again let's go to the order line and add this few or like uh let's add the attributes for this one and then we will start implementing the different Services all right so here they can also copy um I can copy this annotations paste it in paste them in here and also we need our ID so we can also copy it from here let me paste it in the order line so now for the order line we have a private order and then order so for this one it's a Min to one and then we need our join column so let's give it uh so well the joint colum it's not mandatory but we can also specify it so if we don't specify the joint colum The Joint column will be by default named order and then ID so order underscore ID so this is how hibernate and jpa they compose the ID so like it would be exactly named in this way but I prefer I prefer always having my uh my like the full control over everything so now we need also uh a private and here we have an integer product ID so here let's go back to uh to The Domain diagram and here we have an order line is already connected or has a relationship with the product all right so the order line or like uh in each order line we should see the reference to the product so that's why we need to add the product ID in here and then we have of course our private double quantity and that's it so like we can have we can also add a bunch of other information if you want for example you can add the price uh to keep Trace uh to keep trace of the of the selling price that was used at that moment and so and so forth but we don't want to over complicate the application from business-wise all we need to do is all I want to do is to focus more on the implementation of the microservice architecture and then we will extend the application step by step mainly when it comes to the front end when we when we will implement the front end for our application all right so now we are done with implementation or like setting up these two entities so now we have the the required entities for our for our order domain or our order micros service now we will move on to the implementation of the order uh of the order service so like we will create everything related to the order and we will see how to do that all right first we will start by creating an order controller so order controller class and here I will add my rest controller annotation and re uh request mapping so let me make it full screen and it will be slash API slv1 SL orders and of course I will need my required arcs Constructor from lbook and that's it so here first we will start by creating a private final order service class we don't have it yet we will create it in few moments so we have a service so let's create the class order service in the same package and I will give it uh the service annotation as well as the required ARS Constructor so now we will start with the first method so the first method will be create an order so this will be a post mapping and then it will be a public response entity of type integer so I would just need to return the ID of the created order or just returning a void or like whatever you want so here let's call it create order and for this create order I will need a request body and it should be also valid and here I will create an object called order request so we don't have this order request yet we will create it in a few moments all right so now all I need to do is to return a response entity do okay and then my service do create order and I will pass my request as a parameter so let's first start by creating uh a record for our order request and for this record we will need few information so first I will need my integer ID so the ID in case I want to update my order and I will have a string reference so the reference we can also uh create a small algorithm that generates automatically the reference of our of our order so let's call this one reference and then we will need a big decimal amount and of course we need uh a payment method so let's call it payment method we need also a string customer ID so we need to know uh for which customer this order is and finally we need a list of purchase request so the purchase request so this will hold the information of the list of the products that we want that we want to purchase so let's call it products we don't have this purchase request yet but we will create it in few seconds all right so before that let's add a few annotations so for the amount I will add a positive annotation so this is for the validation and let's give it a message so for example order amount should be positive so let's fix this typo order amount and then of course another typo positive uh we will need also a not null annotation for the payment method and here we say for example payment method should not should not be null or like should be precised should be precised all right so then we need the same thing for the customer ID so here for example for the customer ID let's say for example customer should be present so customer should be present all right so in the same way I will use also not empty and not blank so this one it will be not empty and not blank and in the same way for these products I will use the not empty annotation and here for example I will add a message you should at least least purchase one product purchase one product so since this not uh this not empty annotation so here you see the supported types Char sequence uh collection map and array so that's why I used it in here all right now let's go ahead and create this purchase request uh record so I will create a record and I will create a package I will call it product so here it's selecting the the the wrong target destination but I will cancel this one and I will create it manually so let me copy the name and in here I will just create a new uh record in this place and product as a package all right so here we have our purchase record so the purchase record it will contain first a not null uh annotation and with a message uh product is mandatory for example and it will be an integer product ID and then we will have also a positive annotation so for example a message like the quantity is mandatory and it will be a double quantity so for example maybe for some product we can order 1.2 1.3 uh quantity of of a specific product for liquids for example or like for for other for other types of products so now if we go back here we need to import this record and now we are done with the order request so then we can go back to our order line service or to our order controller and let's go ahead and create our order Method All right so now uh when creating this method so we'll see what we need to do so here we have few steps that we need to perform so here first check the customer so we need to check if we have our customer or not so this is the first thing and then we need to so here purchase the products so purchasing the products is using the product microservice so product micr service maybe let's make it this way and then once we purchase the product so here we need to uh persist order so we need to persist the order object and then what we need to do is to persist the order the order lines all right so once we purist the order lines we need to issue or like to start payment process so this one uh this one will be a to-do since we don't have our payment uh payment microservice ready yet and then what we need to do is to send the order confirmation to our notification micro service we don't have this one yet but we will just use so here we we will use Kafka so we need to uh to send a message to our Kafka broker all right so now let's start with uh checking the customer so for checking the customer here we will use open Fame so what we need to do is first to create a customer client so I will start by creating a private final customer client and I will call it customer client we don't have this one yet but we will just create it so here I will create an interface and I will place it in the customer okay so again like the same uh the same issue so will I will create it manually so here I will create a new interface in a package called customer. customer client so here for the customer client it's so easy like uh using open fan is so simple what we need to do is simply to add here at Fain client and then for this Fain client we need to give it two main information so first it will be our customer service so like the name of this client so this is customer service and we need our URL so the URL uh of course we need comma right here so for the for the URL we will use uh something like we will use the interpolation in order to fetch the property from our uh properties file so like I'm talking mainly about this property right here so main resources configuration and then order service so we need this customer URL all right so and you see it's under application. config doccom URL so let's go ahead and do it so it's application. config Dot customer Das URL so now all we need to do is to add our method so we know it's a get mapping and we know from our customer let me remind you in here so in our customer microservice we have here under Source main Java and then our customer controller we have the/ API slv1 customer and we have a find customer by ID or find by ID which is SL customer ID so all I need to do is to provide this information in here so let me close all the unnecessary tabs so it will be/ customer ID so this one it will be an optional so I will use the optional of an object I will call it customer response so I will create a record or class customer response and I will call this method find customer by ID and then I need to pass of course my path variable and it's called customer ID and it's of type string customer ID so like you can use ID or customer ID like feel free to name it so here all I need to do is to create a record in the same package okay so now like it's choosing the correct one so here let's go ahead and create our customer object response so the customer object so it will contain a string ID so this will be the ID of our customer a string first name first name and string last name and of course we need the email since we want to send an email to the customer all right so when working with uh with open fan in here when we work with open fan don't forget to add one important annotation so we need to go back so let me close all this so we need to go back here to the order application and here we need to enable Fain clients and also here when we implemented the the order and the order line we added the auditing uh the the auditing listener so we also need to enable jpa auditing so enable jpa auditing so now if we go back to our order service let's import this one and now we have our we can also close this and this and we can also to close the order request we can also close the controller so here as mentioned first we need to check if the customer exist so here I will replace this one so VAR customer equals this Dot customer client or like directly customer client do find customer by ID and our customer is request.get customer ID and here or else throw so in case I don't find the customer I will throw an exception so the exception it will be a new for example and here I will create a new business exception so here I'm just trying to uh to create as many exceptions I like to show you as much information as I can in one video so here I will create uh a business exception so let's create a class in a package called exception okay so leaveing this the same Source I hope it goes correctly so here we need to extend the runtime exception so okay so it's the package is correctly created so for here I will just remove this one and I will add a private final string MSG just message and here I will use my equals and hash code with call Super true and of course I will add just the data uh the data annotation just to have uh the constructors and so and so forth so now we are done with fetching the customer so if we have the customer otherwise we will throw an exception and let's say for example cannot create order so here for example cannot create order and let's give some information no customer exists with the provided ID and here maybe we can also paste uh paste the customer ID all right so now what we need to do next so next we need as we mentioned here we need to pchas purchase the products so for this one what we will be using so here we used Fain client so here we will use rest template so using rest template is not the same as open fan so like we can also use open fan as you can see or as you saw in here it's so simple it's just an annotation it's just an interface with an annotation and just a simple method but I want to show you as I mentioned as many information as as I can so here I will create another private final and I will create for example product client and I will call it product client so we don't have this product client yet so let's go ahead and create our product client so here let's create a class in this this time so let's change it to product Okay so still in the same uh same folder and just here to make sure okay we have already product in here so now all I need to do I want to mark this one as a service and of course a required ARS Constructor so now what we need to do so first we need a private string product URL so product URL and here I will inject it using the value annotation from spring so then it will be dollar and then application. config so here I made a typo application. config do product- URL so this is the URL of my product microservice then I will need to create a private final rest template all right rest template and I we call it rest template so here it will mention that we don't have any Bean of type rest template defined or found in our application so what we need to do simply we need to create a bean for that so I will create a new class in here so let me reduce this so here I will create a new class in the config package and I will call it rest template config so creating a rest template is so easy so first we need uh so first we need to add the configuration annotation so since this class is a configuration class and all I need to do is to create a bin of type rest template so here public rest template and I will call it rest template and all I need to do is to return a new rest template and that's it so like here we can also add other properties and other configurations to our rest complate but for our case we can use it in this way all right so now we see that we have uh we have a bean and we are no longer having uh the issue telling that we cannot find a bean of type rest template so now what we need to do is to perform or like is to create our our method so it will be a public list of purchase request so we know that uh the response will be of type uh purchase purchase uh sorry not purchase request but it's purchase response and we'll create the object and here let's say for example purchase products and here we need to pass the list of product request uh not product but purchase purchase request so let's call it request body all right so now let's just just go quickly and create a record of type purchase response in the same package so the purchase response it will be uh exactly the same one that we created in the order microservice so here you see that I'm not trying to copy paste or like to reference one uh from the other because here we are working in a microserver so that's true that I created a monor repo project but imagine that each microservice is implemented using a different technology so that's that's why we need to uh when we Implement when micros service we need to focus only on that one and avoid thinking okay so I have this uh somewhere else so why duplicating it so let me move it to a common uh project or let me create a common dependency or something like that so this is not required just imagine and like put in your head that each microservice might be implemented using a different technology so like one can be use uh can be implemented implemented using Us in Java the other one it can be PHP uh nextjs JavaScript and so and so forth so like you need to keep this in mind so all right so let's move on now we have our we will create uh our product ID attribute and then we have string name String description and we will have a big decimal price and finally we will have a double quantity all right so this is our purchase uh response object so now let's move on and let's go back to the implementation of our rest template or to our uh for our purchase products method using rest template so now the first thing we need to uh to create an object of type HTTP headers and let's call it headers equals new HTTP headers so here we need to use uh I think I imported the wrong one yes so here let me switch it so we need to use the one from the spring framework so import class uh and it's the one from org. Spring framework. HTTP so now I will set few information so the first thing we need to set the content the content type so headers do set and like the headers is you can imagine it or like you can consider it has uh a map so like it will be a key value so here I will use first uh first of all uh HTTP headers do content type headers do content type so this is the header and by the way you can even you can also specify it as a string and this is the value for it but since we have it in here why not using it all right and then as uh as the type so it will be media type application SL Json value all right so also the application sljs value is this value right here all right so let's import both of them uh statically so let's add static import and now we are done with the first part so then what we need to do is to have or like to prepare an object of a request entity so I will create an object of type HTTP entity again from the same package or. springf framework. HTTP and this one it should contain the type that we are expecting and we are expecting a purchase response uh sorry not the not the type that we are expecting but the type that we need to pass so we need to pass a list of purchase request because it's already a request entity not a response uh a resp response entity all right so let's call it a request entity equals a new HTTP entity again from the same package and here we need to pass our request body which is this one or like the the products list and we can also pass the headers so here for the headers for example if you need to pass uh a token if you need to pass an API key or any value you can also pass it in here all right then I will create an object of type parameterized parameterized uh type reference always from Spring framework and this also will be a list of now I need my response okay so like the first time this HTTP entity is for the request and now I need a list of purchase response so here let's call it response type let me also fix this typo response type equals a new parameterized oops I made the typo again so parameterized type reference all right so we can also leave it this way so we okay so let me I think maybe I can break the lines so this will be more visible we can also move the remove the type so here we create an object of type parameterized type type reference and this be this will be our response type and this response type is the object that we will pass to our uh response entity or to The Exchange method in order to ask it to uh to pass automatically the response to this to this object so we will see it just now so now I will create an object of type response entity of type list of purchase response all right since this is the final object that we want and let's call it response entity and now we will use our rest template object this one and we have a method called exchange so this exchange method first it takes the URL so it's product URL and then plus and we know that we have uh the end point called purchase the one that we created in the product uh microservice and then we need to pass the the method the HTTP method so it's a post method I will import it statically and then we need to pass our request entity so this is the object request entity and now what is the response type all right so now this is why we need this object response type and this this is why we declared it of type parameterized type reference so here simply we need to do uh or we need to return our response entity dot body so our response entity. getbody so this will contain the body of the response or the response itself but here I will just make a small check so if my response entity do get status code so we have a method status code and we have a method called ease error so e error will check if the response is an error type or not so like if it's uh of type five XX or for XX all right so whether if it's a client error or a server error we want to throw a business exception so throw new business exception and here for example we can say an error occured while processing the product purchase and here we can say for example we can get the response entity do get status code so we will know what is the status code exactly so here we can add colon and space all right so this is how we can use rest temp plate in order so you might already like remark that using Fain client is uh is much easier but in case or like for some cases we need to use or we can use or we want to use rest template so here you have all the information that you need now we can go back to our product uh uh to our order microservice and uh well not the order micros service but the order service itself and we can finish implementing our create order method so here for purchasing the product all I need to do is this do product client. purchase products and here I need request. getet products all right so here we have something so it is required purchase a request I think we made uh all right so here it should be purchase request yes so here should be purchase request not order request so I made the typo there so now we have the part or like the step that will purchase the list of products from the product micro service so now what we need to do next is to purchase the order okay so here I will create a VAR order equals this do repository so I don't have it yet so maybe first let's go and create a private final order repository we don't have it uh we will create it in a few seconds so let's create an interface in the same package so here extends jpa repository for my order object or my order entity and then integer as an ID all right so now I can finish this save and here I will need my mapper so I can use for example mapper do2 order for example out of my request object so I don't have the mapper yet so here I will create private final order mapper let's call it mapper and we don't have this class so let's go ahead and created let's give it the service annotation and now we can create these two order Method All right so this will return an order so return a new order. builder. build so here I guess we have yes we have the Builder so return order. builder. build and here all we need to do is to set the different information so we have ID we have uh customer ID we have reference and we have amount also we can get the request do amount and we need finally our payment method so request do payment method and that's it so we have ID we have the reference we have have the customer ID and we have the amount and the payment method all right so now we go back here once we uh we processed the order the order itself we need to process the order lines all right so let's move on and here so I will just create a for Loop so for purchase request so it's an object of type purchase request and then we call it purchase request of my purchase request do products so like I need to get all the products and out of the products I will create an object uh like I will create an object of type order all right and here for this one like I can I can inject here for example the orderline repository but I will do it in a different in a different way so here I will create a private final orderline service so I will call it orderline uh service and I don't have it yet so let's go and create this class in the orderline package and let's give it the service annotation and also the required ARS annotation so it's just like we will create a service that will handle or take care of creating the order lines so here I will do order line service and I will create a method save order line in the same way because I will show you why I need uh why I delete negated this to a service and then I will pass an object of type new order line request so this will be uh this will be a record and I will pass a null as an ID and also I need my order. get ID so get ID and then I need the product ID so my purchase request. product ID and I need my purchase request do quantity so this will be my uh my orderline request object so like this is the ID of the order line the order ID product and then quantity so here since we don't have this method yet let's go ahead and create it and it needs an orderline request now let's create a record of type order line request in the package order line so here you see that automatically it tries to to detect what are the information that we want to pass so here let's just rename it so this will be the ID this one will be the order ID let me also break the lines and this one it will be my product ID just I will try to make sure that they are in the same order so like the order ID the orderline ID the order ID product ID and quantity all right so it's correct now we can go back here and of course of course we forgot a parentheses so one two all right so now this for purchasing or like for saving the order lines now let's go and implement this method first like the save order line all right so let's go to this one so here like as always I will change this one to an integer and now I will inject my private final orderline Repository and let's call it orderline repository or simply repository and then I will need also uh a mapper so private final order line mapper and let me call it just simply mapper so first let's create this interface in the same package and now extends jpa repository of type order line and integer all right so we are done with this one let's create the older orderline mapper class and let's give it the service annotation and we will implement the methods as as we need all right so first I will create a variable I will call it simply order for example and then mopper to order line and I need to pass my request so orderline request I will just rename it for a shorter name so I will name it uh to request and then let's Implement quickly this method so it will return an object of type order line and here all I need to do is to return order line. builder. build with the required information so here we have the ID which is from the request we have also the quantity and we have the order ID or like here we need to pass the order so here let's say order dot. builder. build so let's say ID and then we have here Order ID and then dot build let me format and then we need our product ID and we need the amount I guess or I think it's it's that's all so we have four information all right so now this is uh this is the mapping method and all I need to do now is to return my repository dot save and then I need to save my order object and then do get ID so this is the orderline method all right now you see like when we when we progress a little bit we need to implement few things like from here and there so that's why we asked like um I just wanted to show you how I would implement it in real life all right so here we need to start the payment and then we need to send the order confirmation to kavka so before so this one we said that we will come back to it later on so I will just mark it as it to do and then for sending the order confirmation first we need to set up Kafka so we need to update our Docker compost file and make sure that Kafka is up and running then we need to configure Kafka to configure our topic and then we will send like and then we will implement the sending uh of the information of or or the notification to the notification service now let's prep prep the infrastructure for our Kafka server so again we will open our Docker compost file and here let's add a new server so after Express or like you can choose where you want to add it and here we will add first we know that Kafka needs zookeeper so I will add the service and I will call it zookeeper and I will pull it from the image confluent in it is called confluent slcp zookeeper and then we can use the latest like latest version so this is our image let's give our container a name so let's call it for example zookeeper and then we will add few environments environment variables so first we I will add zookeeper _ server ID so this configuration is only only required when you work on uh locally but but when you need to deploy your application you maybe you need to add few other configuration and maybe like enable um other properties so I will give it an ID one again I will use zookeeper underscore client Port so here just to define the port for our client and by default it's uh 2181 and we have also another property called zookeeper underscore tick time so the tick time let's define it uh so it's sck underscore time and let's define it to 2 seconds then we need to enable some ports and for the ports let's say uh so like as you can see here it's 2181 so just add add a two and 2181 so like it will be 22181 over 2181 which is the default Port that we defined for our zookeeper then I will assign it to uh to my network and uh the network that we called microservices Network and that's it for the Zookeeper now we will Define the the the property or the service for our Kafka broker so I will call it Kafka and then the image so it will be the same one as in here so like it's the same prefix it's confluent in C uh not confluent in C but confluent in and then letter C and then slash it will be cp-a and then we'll also lose use uh not lose but use the latest version and let's give it a container name or like let's give it a name and they will call it Ms or like microservice and and then Kafka so then I need to Def to uh Define a port so I will use uh 9 9092 over 90 92 which is the default one used by Kafka and here we have something called depends on so here our uh our CFA broker needs first zookeeper to be up and running so I will just say and tell it that it depends on zookeeper and now we need to Define few environment variables so here here I will just paste it and explain them one by one so first we need to define a Kafka offset topic replication Factor so like how many replication we want so as I mentioned like locally we only need one so here we also we have a transaction State log replication factors it's also one so here like I learned uh this one by experience like when I when uh working locally with Kafka on uh on Docker so we need to Define this ones otherwise you will face few issues and the the Kafka container will not start so also we have a transaction State log U me iser it's also defined to one and here we need to define or like to give it the URL of our zookeeper so here zookeeper since the both of them that are in the same Docker compos file so we can reference it using the zoo uh the zooe keeper instance name or like service name right here all right so I guess I pasted it in the wrong place so let me fix it so here it should be part of Kafka not maev all right right so then we have the Kafka listener security protocol map so we will play like we will add this uh this information so it's plain text over plain text and plain text host plain text and then we have the Kafka advertised listeners so here we need to define the port like or or what is the port for for our Kafka broker which is Local Host 9092 all right so then of course we need to define or like to assign it to our Network so it will be microservices Network and that's it for the configuration for Kafka and zoo keeper so now if we uh what we need to do is just let me clean this one it's just Docker compose up and then minus D just to restart everything and create all all the containers so here there is something I think we made the typo somewhere so let me double check it yes so this one like uh we need to uh we had double slash so let's try again to start uh our container and as you can see all the containers are up and running all right so now we can move on and continue the implementation of our order micro service now let's go back and continue implementing our order micros service so here the first thing that I need to do is to configure my topic so in the config package I will create a new class and I will call it Kafka order config or order topic config so I will call it this way let me make it full screen first this will be a configuration f file and then I will create a bean and then what I need I need a public new topic it's a called uh it's an object called new topic but we don't have it yet because we need to add Kafka dependency to our pom.xml so first let's open the pom.xml from the order microservice and then we need to add the Kafka dependency that I will show it to you just right right now so the dependency is called uh so here maybe let me scroll down a little bit so maybe after open Fame let's add a dependency and uh it's called spring-kafka so like this one and here it's coming from uh the package org. springf framework. cafka and all I need to do is to refresh my dependencies so now we have our CFA dependency available so we can go back to the configuration file and add our new top object so here it's called new topic let's import the class and as you can see it comes from the Apache Kafka clients admin and then new topic so let's call this one for example order topic so order topic and then all I need to do is to return a new like a a topic Builder so it's called topic Builder so here my IDE is not recognizing it so but let me try to import it manually so here I will say use uh import org. springf framework. CFA and then config and then we have topic Builder so let's try to use this one so it's a topic Builder or maybe I made just a typo okay yeah I made a typo that that was the reason and here let's say name and let's give it a name so for example let's call call it order topic also the this topic name we can externalize it to the configuration but it's fine here to leave it also hardcoded in here since like we will use only this topic even for example if we decide to move to another environment so now we have the configuration of our topic we have the topic uh the order topic let's close this one and now in order to be able to send uh an element or like an information to the CFA broker we need to add uh some other methods so here I will create a new class and I will call it order producer so since our order microservice is the producer so I will call it order producer and I will put it in the package I will call it gafka so this order producer it will be a service let me make it full screen so it will be a service and then I will need the required ARS Constructor and for example I can also add the slf forj if I need or if I want to add other logs so what I will do is I will create a public a public void so public void and I will call it send for example order confirmation and this order confirmation will take an object of type order confirmation object so order confirmation we don't have it yet but we'll create this record in few seconds so let's go first and create this record order confirmation and this order confirmation it will contain the the the data or the information that we need to put or to uh to send to our Kafka broker so what I need to send to my notification service I need to send the order reference order reference and then I need to send a big decimal amount or like the total amount just the total amount and then I need my payment method so like I need all this information just to display or to send a decent or a correct email with all the necessary information so let's call this one payment method and we need also a customer response so the customer response will contain the customer information so I will call this variable just customer and then or finally we have a list of purchase response and I will call it products so this one will present the list of the products that the customer has purchased so now let's go back to our uh send uh order confirmation method and let's finish the implementation so first I will just add uh a simple log so log. info and then here let's say sending order confirmation just uh just to make sure or like to be able to follow and see the logs later on when we do something so here what I need to do is to use a message object and here the message is uh from or Apachi kafa common. protocol uh sorry I think uh no it's the wrong one I think we need to use the spring uh yes it's from or. spring. messaging so we need to use this one and here we want to send an object of of type order confirmation and then let's call it a message equals and then we need we have message Builder we have a class called message Builder and then we can say with payload and our payload is the order confirmation and then we have we can set a header so to which topic that we want to send our information so here we have a class called Kafka headers and then we have a uh a topic or a type called topic so this is the one and it's called Kafka topic so you can even you can also use this string directly but it's better to use uh to use something predefined already and now we need to to pass the header value which is our order topic so this should be exactly the same name that we provided when we created our topic and then finally we need do build so now we prepared the message we logged and we have everything so now we need to send the message or like to produce a message from our order microservice to the Kafka bro broker for that we need to inject something so here I will inject a private final and we need a Kafka template so we need an object of of type Kafka template so here it will be of type string and what is the object that we want to send it's of type order confirmation and let's call it Kafka template and here all we need to do is Kafka template. send and we want to send our message and this is how we implement or like how we send a message to a topic so this is how we produce a message to to a Kafka topic but this is not the end we need to add also some other configuration but before that let's go back and finish our order service implementation so here we mentioned that all right in the order service here we mentioned that we want to send the order confirmation uh to our notification microservice so here first I need to inject my Kafka or like my my order producer so it will be a private final order producer and let's call it for example order producer and here all I need to do is to say order producer uh so it's order producer dot do send order confirmation and for the order confirmation all I need to do is to pass a new order confirmation object so this order confirmation it will contain the request.get reference so this is the order reference we need also uh the request. amount so this will be the total amount of our uh order and again we can get the payment method from the request and finally we pass the customer object that we uh that we got from here from the customer microservice so there we have all the information about the customer and we have also our purchased products so my object it's called purchase all right so we forgot to save the purchase product so this uh purchased product we will save it or we want to save it to a variable that's called purchased purchased products equals so let me fix this typo and here we can pass our purchased products all right so like we know that this product client. purchase products will return a list of purchased products and now this is how we send an object or this is how we send and uh produce a message to our CFA and finally all we need to return is our order. get ID since this is this should be the return type or the object that we need to return so now so now if you remember from the from the Kafka video that I produced before so we need to add few configuration when we produce something and also when we consume something so like the producer and the consumer they both of them they need to Define few information and among this information we talk about the serializers so we want we need to Define what are the ser serializer or like the key serializer and the value serializer of our producer since here we are not sending a simple string so we are sending an object and this object should be serialized in order to be to be able to consume it later on and to also to uh to cast or to deserialize this object again to an order uh to an order of to an object sorry not an order but to an object of type order confirmation so to do that what we need to do we need to go to our config server and add few properties so here if we go to Main and then resources and here configuration and in the order service configuration so for that I will just in the beginning as I showed you before I will do it in here so just you see uh you can see the autoc completion uh from uh from the IDE so what I need to Define we have here spring and then we have an information called Kafka and then we have producer so since our order microservice is the producer of of uh of our messages all right so first we need to Define our bootstrap server so here let's define the bootstrap server or servers because we can Define many of them so it will be our local host and then 9092 this is the configuration that we defined before for our Kafka producer or like for our Kafka server and then we have a key serializer so the key serializer we need to define or like to tell Kafka what is the serializer of our objects or of our messages so it's by default org. Apache doka and then common we have a package called common and then serialization and then we have a string ser serializer serializer and this is for the key serializer so now since Kafka does not have a default uh value like a default Json serializer so we will use the one from provided from the spring framework so here I will add the value serializer and it will be from org. springf framework. gafka and then we have a package called support and then uh I think it's called serializer and then it's the class is called Json serializer so if you want to implement uh serializer so let me fix this one all right so also if you want to implement your own Json serializer you can just do it whether by extending or implementing the this interface or defining your own serialization so then we have something else that we need to add so here we can we need to add few properties and then we have a Json a property called Json type mapping so here let's add properties and then we have a property called Json uh it's called sorry spring. Json like it should be written in this way so spring. json. type. mapping I will explain what what is the reason or like the the value or like why we need to specify this information so here since we want to serialize or to send adjacent object or an object so the producer needs to inform the the consumer of our topic what is the object that we are sending so here we are sending an object an object called order confirmation so order confirmation this is what we defined in here all right so this is what we defined in here so what we need to do is the this is the order confirmation and where this one is coming from so we need to provide the full package of this order confirmation object so it's coming from com. alibu do Ecommerce and then Kafka and then order confirmation so we are just providing this order confirmation object so this one right here and we are providing this package name so let me copy it and paste it again just to avoid any kind of typos and that's it and then it's the class name so then when we send this one the consumer will be aware of this object that this this object can be accepted so this is like a security level from Kafka that we cannot produce or like we can we should when we produce and consume something we need to inform like to the two sides so like the producer need to need to inform the consumer what what is or from where the object is coming from so like this means for example we are we trust this package or we trust this class and we it's able or like it's uh it's fine to to consume it all right so this is the configuration for Kafka I will just copy uh or like cut this part right here and then just place it in the order service so here after datab base and the same level of jpa because the information or like the property is called spring. prod producer and so and so forth so this is the configuration that we need and don't forget to add this configuration if you skip this part you will face issues when sending and consuming data from the Kafka topics all right so this was this first method so the first method is create order and I think this is uh the most complicated one or like the the one that has the most uh of the relationship so because we need to to get the information or like to contact or to connect to our uh to our customer microservice and then we need to connect to our produ uh product microservice and then we need to do or to interact with our Kafka broker now what we can what we need to do next is to implement the rest of the method so let me close all this one so close all tabs and now we can go back to our order controller and we can finish the implementation of the rest of the meth the methods so so the rest of them will be something simple because what we need to do is just to to retrieve the data or like to retrieve the orders find all find by ID and and that's it so first let me add uh another method it's called get mapping so here it will be a public response entity and here it will be a list of object of type order response so we don't have it yet we will create it and let's say for example find all so like for our case we will not uh use this one but I just want to uh to create this method so I will create a a record and I will just implement it in few seconds and here all I need to do is to return a response entity so response entity do okay and then I need to call my service dot find all so this find all like is a classic method nothing fancy in here so let's go ahead and create this list find all so now all I need to do is my repository do find all and then do stream and map so here I can use the mapper dot uh to order response or maybe let's change bit let's use from order for example and then of course we need uh we need to collect and to collect it to a list so now let's go ahead and create this method so this needs to uh this class or method needs to return an order response object and this order response will be a record as mentioned before so here we will just provide few information and here all I need to return is an integer ID so this will represent our order ID we need a string reference so this is the reference of our uh of our order and the big decimal the amount and then we need a payment method of course like we want to know what was the payment method and for example a string customer ID so you can also like extend this one by contacting for example or fetching the list of customers for each order return it and so and so forth but you can uh like we can make it also in the front end when uh when the user wants to display the customer information we can just add a button or like a link in order to fetch this one so like we don't need to fetch it uh eagerly so we can uh we can like fetch it in the lazy way all right so now let's go back here and all I need to do is to return a new order response so here it will be order. get ID and then we have order. get reference and we have also uh the amount so let's say order do amount then we have the payment method so I don't have the auto completion but let's say order. payment method and finally we have order. getet customer ID so this is the find all method and as I mentioned this one is like two classic one all right all right so the next one is finding an order by ID so it will be again a get mapping and we will have our path variable and let's say slash order- ID for example and then all we need to do is to call our service to fetch this order ID so it will be a public again like a response entity of type order response and then let's call this method find by ID so here we need our path variable so just path variable and let's call it order- ID and integer order ID so then we need to return our response entity. okay and then service. find by ID and Order ID as a parameter so let's go ahead and create this method so this is also a simple one so all I need to do is to return repository do find by ID and then order ID and then I can map it if I find something so here it will be mapper do from order and finally like if I don't find anything I can throw an exception so the exception let's say for example let's throw new entity not found exception and here for example as always we can say uh no order found or like uh no order found with a provided ID so for example we can use uh or let maybe let's use the string do format method so just to to be able to easily include or like to map the the attributes or the values so here we say uh no order found with a provided ID and then let's say percent D because we need to pass uh a decimal or like uh digits so here it will be order ID and that's it so this is defined by so now we are almost done with the implementation of our order micros service so what we need to do next is to implement a controller and few uh things for our orderline uh orderline uh entity so here what we need to implement really is for example like a get mapping to find uh to find by order ID like find all the order Lines by order ID this we might need in the future when we implement the front end the front end part so let's go ahead and Implement that one now in the orderline package let's create a new class and let's call it order line controller so also by the way this method that we will create in here we can also move it to the order controller and have everything there but I just want it to split a little bit so here I will add a rest controller and a request mapping so the request mapping it will be slash API slv1 as always and here Order Dash lines so then I need my my required RX Constructor and let's add the method that we need so first I will need my private final orderline service so orderline service let's call it service and then I will need my get mapping and it will be slash order because we want to fil or uh fil to filter or to find all the orders by all the order lines for specific order by order ID so here let me add order - idid and now we will have a public response entity of type list so it will be a list of order lines or like order line response so order line response we will create this record in a few moments and then find by order ID so here we need our path variable and it's called order ID and then integer order ID so then what we need to do simply to return uh up wrong place so here return response entity do okay and then we need to return my service do find all by order ID for example so here let's give it the order ID as a parameter first let's create this class or this record so let's use a record in the order line we will fill it in a few moments and now we need to uh create this method find all or like find all by order ID so for the order line response here we will need just two information like S as simple as that so for example let's say we want to return an integer ID so the ID of the order line and for example just to make it simple if we need we will extend it later on so and here we have the quantity for example so the orderline service now it's like quite simple so here all I need to do is to return my repository do find all by order ID so I don't have this method yet but we will create it and here we need our order ID so let's uh first let's fix this one and let's create this find all by order ID so this will return a list of order line just not order line response but order line so let me close this in here so now let's go and check this order okay so here we have order maybe we have a typo yes so it's again a typo all right so it's order ID now if you go back here it's order it's called order ID and then we have a stream and then map and we have our mapper do to order line response for example and then collect collectors collectors to list so let's create this method so this will return an order line response so simply we want to return a new orderline response with orderline doget ID and orderline doget quantity as simple as that so now we are done with the implementation of the order line control roller so here we still like to finalize or to or to 100% finish the implementation of this order service we still have two things the first one is we want we need to come back to the order service and finish the implementation or like sending the information or like this to- do so like uh start the payment process and then since we have also like uh we are throwing exceptions business exceptions and so on so forth so what we need to do is of course to implement a Handler for our microservice so the next step is to implement the Handler and then we will finish the like we will 90% or like 95 95% we will finish the order service and then we will move to the payment service and finally we will implement the notification service so let's go ahead and implement the rest all right so now let's go to the order Source main Java and then let's copy this Handler package and paste it in our order micros service since we know that it's almost the same so I will just paste it in here and add few adjustments all right so here we have our Handler and we need to adjust our Global exception Handler so here instead of so the same The Entity not found will stay the same as well as the method argument not valid exception also stays the same so here I just need to to replace this one with a business exception the same for this business exception and here instead of getting message I want just to get my MSG variable that we defined inside our business exception class and that's it so now we have our Global exception handling which is up and ready so what we let me optimize the Imports since we imported like the wrong class uh from the from the other from the other project so now all we need to do is to move on and implement the next phase or the next microservice which is our payment microservice so here the payment microservice will connect to uh postag SQL database in order to save uh the payments and also we will need to send some data to Kafka also it will be almost the same as we did before with uh with the order and finally we will implement the notification microservice and then the Final Phase we need to set up our API Gateway and then we will be good to go to start testing our application and then at the end of this video we will set up the distri distributed tracing and enable zkin and we will see all the tracings and the logs of our microservice architecture all right in the same way let's start by creating a new project so in the same location and let's call it payment so this will be our payment microservice it will be uh Java and then Maven so the group it will be always com. alibu and the artifact is payment so I will just change the package name and I will as the same I will call it com. alibu Ecommerce and then next so now let's add a few dependencies we need our spring web we need validation we need spring data jpa so let's search for jpa it's easier and then we need of course our lumbo annotation and we need our Discovery Cloud client not clown so we need our urea Discovery client uh we need also our configuration uh client or config client and then what we need also we we can use Kafka so so here we have uh spring for Apache Kafka or spring for Apache Kafka streams I guess this is the one that we need so we will check the dependency later on also uh we need finally our post agress SQL driver so let's go ahead and create a project and in the same way let's add it as a maven project inside our inside our working space so here I will select payment and then pom.xml and click on open so let's quickly go and check the p. XML file so let me reduce this one and from the payment let's open pom.xml I just want to check if we imported the correct Kafka dependency which is which is this one so like we need to use Kafka not the Kafka streams and then we have postgress SQL we have lombok and so and so forth so now our project is up and ready we can start implementing our payment microservice so the first thing I will start by cre creating a payment entity in a payment uh in a payment package so let's call it just payment. Java for example so payment so this payment it will be uh a simple entity so what this microservice is about is just to save uh the payment that the payment was uh was issued and then maybe in the future we will set up for example one payment method like PayPal or uh stripe or anything else but for now let's keep it simple because because we want to to focus only on the microservice architecture and then we will add few uh few business requirements or like new few features in the future so I will add uh my all arcs Constructor and then I will also need the no ARS Constructor I need the Builder annotation also the getter and Setter annotation so like this the are the basic uh lbook annotations I will add also the entity entity annotation and of course I want to add some entity listeners so since I want to track the creation date and the last modification date and using here the auditing listener uh class and finally I will add uh a table annotation I will give my my table uh a name so I will call it payment so this one uh this one is not really needed because it will be the same as as the entity but it's not uh it's not a problem or like it's not harmful if we if we add it so here I will add my ID and then I want it to be generated value and let's say for example private integer ID and then I will need my private big decimal amount so this will be the amount of the payment and then we need uh a private uh payment method so payment method it will be like or we will have exactly the same payment methods as we defined them in here in the order microservice so let's open it and just copy the values so Java and then order and we have here payment methods so let's just copy the values from here and when you work in a real project you need to make sure that you are using the same values or the same payment methods so let's create an inam in the same package and let's paste these values right here all right so now we need to make it enumerated and then let's say it's uh n type. string and we can use a static import for it and then we need to keep track about the order ID so I will add an integer order ID and then finally I just need to add the create uh the create date and the last modified date so for that I will open the order. Java class my entity in here and I will just copy paste this ones to gain some time all right so here we have the created date and the last modified date and then of course since we have auditing we need to go to our payment application so let me reduce this one and payment application and here we we need to enable jpa auditing so don't forget this one otherwise the auditing will not work okay so now we have our entity all we need to do is to start creating our controller service and so and so forth so in the payment package I will create a new class and we will call it payment controller so this payment controller will contain only one method so here I need my rest controller annotation and my my required as Constructor and of course the request mapping so I will call it/ Api slv1 as always slash payments then we need to inject our private final payment service we don't have it we will create it as always and then I will create a post mapping so this post mapping it will return a public response entity of type integer so all we need to do is just to return the payment ID and here let's say create payment or what what we can also do is to create or to generate a payment reference and just return that one to our customer or to our clients so here we need of course our request body and it should be valid uh valid not value so from Jakarta let's optimize the Imports and here we need an object of type payment request so this will contain the information of our payment and then what we need to do simply is to return a response entity. okay and then what we need to do is just service. create payment and then we will create all the necessary classes so request first let's start by creating a payment service so this will be a payment and then let's add a service annotation and also the required ARS Constructor from lbook and then we will create an object of type payment request and it will be record all right so now to initiate or to create a payment we need view information so let's say that we need an ID in case for example we want to enable updating a payment then we need a big decimal so big decimal it will be the amount of the payment or uh yeah exactly the amount of the payment we need also our payment method so let's call it payment method we need also an integer order ID so integer order ID and then we need our string order reference so the order reference we need we need it to we need to send it to the confirmation service and then we need an object of type customer so here let's call it just customer so the customer we don't have it yet so let's go ahead and create a class or a record customer so in the same project so the customer will contain the information of our customer so this one since we have here in our controller the at valid annotation and when you use uh a complex object complex object I mean like a a record or another class you need to mark this class as validated so when you use this validated all the attributes that you will include inside this record they will be also validated or like all the annotations will be uh validated using the spring validation dependency so here let's add a string ID since we know our customer uh or like the ID from the customer is is of type string we also need our string first name also a string last name and finally we need a string email so here let's add The annotation so this one it should be not null and let's say for example message uh first name is required just to make it simple the same for the last name and here let's call it last name and finally let's say for the email also let's say email is required and also let's add the email annotation so email annotation and for example let's say the customer email is not valid or like is not correctly uh formatted is not correctly formatted so we need the email to be valid and well formatted because we want to send it to the notification service and then from from using this email we want also to send uh a payment confirmation to our customer based on the uh on our client requirements that we saw in the beginning of this video all right let's go back to our payment controller and create the method create payment in our payment service so this implementation will be quite simple so first all I need to do I will create a payment object and I will call it like I will call for example equals repository we will create this uh this field or this uh this parameter uh and then we need to call Save method and then we need to use our mapper DOT for example Le to payment method and we need to pass our request as an object so since we don't have any of this the first thing that I will do is I will inject a private final payment repository and let's call it repository and then we need also a private final payment mapper and let's call it mapper so let's go ahead and create these classes so we have payment repository let's create it as an inter face in the payment project and now as always extends jpa repository of type payment uh not payment repository just payment and then integre so this is the type and now we need our payment mapper which will be a class so let's add the service annotation then we need simply to create these payment method so let's go ahead and create a payment so this will return a payment builder. build and need all and here all we need to do is to map the attributes so we have ID we have uh also we have custo order ID I guess yes so we have order ID uh we have payment method so this will be my request. payment method what do we have also in the payment uh we have amount and Order ID already mapped so the final one or the final information is amount and this will be my request do amount and that's it so now let's go back to the payment service what we need to do next is to send a notification to our notification microservice so in the same way we need to set up Kafka we need to add the properties we need to do all the required things but we did not yet add the properties for our uh for our payment micros service but we will add it all at once since we know how things work and since we know how we do or like how we add this information so I will close this one I will just uh continue implementing the CFA producer and the topic and all the configurations that we need and finally I will come back to the to the application. yaml and add all the properties and of course externalize them in our configuration server or config server so let me close all this first as we did did before we need to add a new class so let's add it in a config package and let's call it uh for example notification or Kafka payment topic configuration so let's call it Kafka payment topic configuration so config just as a simple name I will make it full screen and for this like we will do in the same way so we need the configuration annotation and then we have a be and of course we need a public new topic object and then let's call it for example payment topic so this will be the topic that we create in Kafka in order to send all uh the payment confirmation or like the payment information generally speaking or payment notifications to our notification service so then return uh topic Builder and then let's give it a name so the name will be for example payment Das topic so you can call it anything you want and finally build all right now we are done with the configuration what we need to do is to implement our notification producer so here I will create uh a new class in a package called notification so notification and then I will create a class called notification producer all right so here let's fix the typo notification Pro producer let's make this one full screen and now we will start implementing our notification producer so this one I want to make it a service and I need the required ARS Constructor and slf4j just for logging now since we are familiar we know how to what to implement and what to do exactly so first I need my private final CFA template so cka temp plate of type string since this is the key and the value it will be of type payment not ification request so we don't have this object we will create it so let's call this one Kafka template so first let's create this payment notification request record we can use record for that or class like both of them are okay so here uh we will have our string order reference so these are the information that we need uh to send to our notification service and then we have a big decimal amount so we need to send the amount we need also our payment method so here we need payment method uh let's call it payment method we need also a string customer name or customer let's call it first name uh we need also customer last name so this one will be a string so make can copy this one so here it will be just last name and finally we need a string customer email so customer all right so we are done with this payment notification request now if we go back to our our notification uh producer all I need to do is to implement a method so this will be a public void send notification and I need my payment notification request so let me call it simply request and now first let's log. info for example uh sending notification uh and here for example we can say with body so here I can do something like this and I can parameterize it uh this way so here request so like this when when we use the open and closing brackets this will include the value or the serialization of this request inside this one so like we will have a log later on sending notification with body and it will display the information of our object so then we need to create an an object of type message as we did before so here let's uh give it a type payment notification request let's call it message again and equals our message Builder and then we will say with payload which is our request and of course we need to set the header so the header it will be uh as always our Kafka headers do topic and then we need to give it the topic name which is payment topic as we defined in the configuration and then do build finally so now we can also import this one statically and finally all we need to do is cfat temp plate. send our message and that's it so now we have our send notification so let's go back now to our order Service uh sorry to the payment service not order service so payment service and now all we need to do is to send our notification to the notification service so here simply uh so okay now we can return payment. get ID and here we need to inject our notification service so private notification producer let's call it notification producer and here just we need to call notification producer. send notification and now all we need to do is to create an object of type notification request so the notification request it will be order. getet uh order. order reference and then we need request. amount then we need the payment method also from the request payment method we need also a request.get uh customer DOT first name and then we need my request do customer do so here request. customer. last name and finally I need my request. customer. email so here why I use this one without checking if the customer is null or not is simply because I have the validation of this customer object right here and also like this object or like this request is validated already in the controller all right so here we just forgot the final keyword so we want it to be automatically injected okay so this is the implementation of our payment microservice so now let's go ahead and finish the configuration for it so let's open the source Main and then application.yml file and let's do what needs to be done so here like if we just externalize the information so we need here spring. application. name so let's call it payment Das service and then what we need to do is just to externalize or like to add the properties or the other properties that we need for our microservice so let's go ahead and add them so like we can also do some copy pasting from uh from other microservices since they are almost the same so here for the payment service we need first let's go to our config service and then main resources and configuration for example uh in the same way as product service we can copy all this data source part and let's paste it in here so we have data source and here we need order instead of product and of course don't forget to create the to create the database all right so here we have product we need to create for example uh first let's check if we are connected yes so here let's create a new database and let's call it order for example so we will call it order and then let's click okay uh oops I guess so here let me let me see all right so this is for the order micros service and now we need another one for the payment so I just made a small mistake so let's call this one payment all right so also let's display this one let's refresh in here and we can also display now the order uh the payment uh database so let's leave it uh in here and now in this one it should be payment sorry not order so here we have payment uh and for the rest everything is almost the same now from the order service we can also copy this information we have right here so like the Kafka configuration so now let's paste it in this way and also in the same level of data source and jpa let's paste this information so I will make make it full screen so the bootstrap server stays the same the key serialization and the key uh the key serializer and the value serializer also they stay the same also we need to add this property which is the Json uh the the spring Json type mapping we need just to change this one so here we don't have uh order confirmation but let's call it just payment payment confirmation and also it comes from the same package uh well not exactly the same package let's double check just to avoid the typos and debug later on Just for nothing so here we have notification and this is our notification request let me copy the package and then I will paste it in here all right and then my class is called payment notification request so here it will be payment notification request and that's it so here I will just take all this so let me select it all so I can also remove this one now all I need to do is in my config server here in the configuration let's create a new file and let's call it payment service. yamu and here all I need to do is to paste this configuration so we have the same configuration that we have there now we need to finalize uh our application. yaml the one that resides in the payment micros service so here of course we need to add config do uh import and we have optional and then config server and then we need to provide the HTTP colon Local Host and then our Port which is 4 * 8 all right so now we are done with the microservice uh payment all we need to do is to go back to the order microservice and finish the and finish the implementation or like calling the payment or initiating or starting the payment process in our order microservice all right now let's go back to our order microservice and let's finalize it so in here I will create uh a new class first uh it will be an interface and I will create it in a package called payment so we will use Fain client in order to uh to initiate uh or to start a payment process so here I would just call it payment client and in here let's also use uh so before that we need to make sure that for the config server let's go to our payment configuration and we need to make sure that we use the correct Port so otherwise like uh we might have few conflicts like or like using the same port uh two times so for the for the that one we can use 8060 for example so here if we go because I think it's the one that we defined in here so here we have payments and now in the payment service I guess we have okay so we did not Define this one so let's say server and then port and let's say for example 8060 for the payment uh for the payment service all right maybe let me do a global search so it's not used so it's the only place okay so now let's go back and let's start implementing our payment micro or our payment client so simply this one it will be a Fain client and as always we need to give it a name so it will be product service and then we need our URL so the URL it will be again uh like we will fetch it from our application. config dopay payment URL the one that we defined already in here so let me remind you so here we defined already a payment URL object or like uh value so then what we need to do we have our post mapping and all we need to do is to return an integer and for example let's say request order payment so let's call the method this way and here we have our request body and we need an object of type payment request so we don't have it and we will create it and this will be our request object and okay so this one should be an interface I already mentioned that it should be an interface but I created as a class so let's go ahead and create a record of type payment uh of type payment request so this will contain the information that we need in here so maybe just to go a bit faster if we go to the payment micros service and then we I guess we can copy the same attributes from here so we have uh this payment request so it will be the same like uh the amount payment method order ID uh the reference and the customer object so let's copy this ones and now we can paste it in here and since okay so let's import the payment method first and here the customer it will be our customer response all right so in instead because this will be the the same object so we need our customer response all right so now we are done with the payment client all we need to do is just to uh include it in our order service so let me reduce this one and go back to our order service so here in the order service what we need to do or like all we need to do is simply to inject our uh our payment client and just initiate or start the payment process all right so here let's a private let's add a private final payment client so payment client and let's call it payment client for example and here just let's replace this to- do with a payment client do request order payment and here we need just to pass an object of type payment request so I will create a payment request object so here let's say VAR payment request equals new payment request all right so here what we need to do is request.get amount and then request. payment method then uh order my order. ID so get ID and then we have order. get reference and finally we have our customer object so now we are done or like we finalized the implementation of our order micro service so like almost all the microservices let's go back here and double check again so if we open diagrams and here in this diagram we are done with the implementation of all the microservices also we have Kafka already set up and uh ready to use and finally all we need to implement like I'm talking about the the functional microservices is the notification micros service and this notification microservice will connect to a mongodb database just to store or like to keep trace of uh of the emails or like all the notifications that we sent or we can also make it stateless so like we don't need to persist any data so it's really up to you so then what we need to do is like this notification microservice will send an email confirmation or like we will send an email go globally speaking to the customer itself and finally in order to finish the implementation which need to implement our API Gateway so now let's move on and implement this one all right now let's create a new project and let's call it uh notification so in the same way I will go to file new and then project so I will call it notification and then it will be Maven project and here in the same way I leave everything as is just I will change this one to Ecommerce so then next so here we need first mail uh since we want to send emails also uh we don't need uh we don't need the web we need uh our mongodb or spring data uh mongodb because we want as I mentioned we want to persist the the emails but it's not mandatory so like we don't uh need so you can make it a stateless server or service uh just you need uh to receive or like to consume the data from the from the kfka topic and then just send it uh send it to uh to the user also I will uh choose th Leaf as a template engine also uh we have we need the web uh sorry I think web we don't need it but uh first we need of course our config server so the config client also we need our Discovery client so from uh urea and we need of course Kafka so Kafka we need spring for apachi Kafka and then we need lbook so as usual so l book and that's it so let's click on Create and in the same way let's import our project so here from Maven or like uh even from the menu but from Maven is also fine so here let's click on notification select the pom.xml file and import the project as a maven module or a maven project so now we have our notification service so as always the first thing let's start with creating a few entities so here in the main Java and then later on we will come back to the configuration so the first thing I will create uh a class in a package called notification and I will create a notification class so this will be my document so the notification class like I will add as always a few annotations so all arcs Constructor no arcs Constructor I need also my Builder to easily build my object and then we need getter and setter and finally let's give it a document annotation so here document the one from DB all right so now let's define few attributes let me reduce this one so first I will have a private string ID and this one I will give it the ID annotation then we need uh a private and that will create a notification type just here to keep Trace uh what is the type of notification so I will create it as Anam so here in the notification in the notification project so I will give it two values or like I will have two possible values so here I will have order confirmation and the second one it will be payment confirmation so because this is the main goal or like this is the main functionality of this notification service so then we go back and we finish the we add other rutes to our documents so here I will have a private local date time just to keep trace of the notification date so notification date and then we need an object of type order confirmation so let me make it private order confirmation so this is an object that we will create so order confirmation and let's call it order confirmation also I will need another object payment confirmation so this will uh will represent the object that we will process into our database since it's uh no SQL database or like nonre relational database so I can just include objects as it is so here let's uh call it payment confirmation and here in the same way all right so for this order confirmation I will create it as a record and I will change the package so from uh from notification I will create a sub package in here so here I will have a package called Kafka inside it I will create two sub packages one for order and and the other for uh for payment so here I will create a record so then it will be under Kafka dot uh and then let's call it order for example and then let's create it so here I think it was created somewhere else yes so okay so this is wrong let me delete it from here and let's create it again okay so let's try again with the IDE so I want to create a a record under uh Kafka and then do order so here let me change to notification and then create okay so now we have it and in the same way I will create my payment confirmation object so I will create a record and again in my Kafka dot now I will create a package called payment so here just make sure that it's selecting uh notification like as as a Target destination directory otherwise as you saw it will be created in the wrong in the wrong project so let's start with the order confirmation and set up or add few properties so first I have a string order reference so these are the information that I want to store or like I want to skip trace and then we have a big decimal total amount and then I want to have my payment method so the payment method I will just create it let's call it payment method and then I will have a customer object so it will be customer and finally my the list of my products so a list of product and then I will call it products so here for the payment method I will create in uh in this package so I will like created within the payment so it's since it belongs to the payment so here I will create an inam in the payment package all right so let's open our payment inam payment method. Java I think we have one already in here so payment method. Java the one from order for example and I just I just need to copy the values and that's it all right so now we have our payment method and then we need to create a customer record or a customer object so we can keep it in the in the order so here for the customer all I need to do is just to include the uh the customer information so for this one maybe let's go a bit faster and we can go to the payment uh main Java and I think here we have in the notification we have customer somewhere so we need this ID first name uh email uh first name last name and email so I will I will delete the validation later on like the validation annotations so let's remove this one this and these two validation annotations so this is my customer object and then finally we need to create an order object so let's create it also as a record in the same package so it will be also under order right here so for the product we will have also few information like the product ID name description price and quantity so let's go ahead and add this so we will have an integer product ID and then a string name and after that we will have a string description and uh a big so big decimal uh price so this is like you can you can customize this objects as as you want and then we will have a double quantity so just to keep trace of what we of what we did all right so let's close this this and this now let's go back to the notification and we can go to the payment confirmation object so for the payment confirmation object it will be just a simple one so here let me make it full screen we will have a string order reference and then a big decimal uh amount so this is about the payment and we have of course our payment method payment method and string customer first name so I guess for that I can paste uh the one I already copied so let me first remove this and here we will have we don't need the ID we just need the customer let's rename it to customer first name and customer last name and here let's say customer email all right so this is my payment confirmation object so here we are done with the with the implementation of this notification document then what we need to do is simply to move on and prepare what we need else so here uh first of all I will just create in this payment package I will create a new interface and I will call it notification repository and of course we need to extend our repository of type payment pent confirmation and then a string as the ID uh sorry wrong package it should not be under the under payment but it should be in notification so let's move it to notification here so we have only two packages CFA and notification and we have here the notification notification repository and notification type so let's close this one then what we need to do we need to create a consumer all right so here under this cfap package I will create a class and I will call it notification consumer so this will be the consumer of my uh of my topics so in this notification consumer I will Define two or I will create two methods so one method to consume the payment notifications and another method to consume the order the order confirmation notifications and both of them what they will do first we need to purist the data so we need to save this notification and then we need to send an email all right so this is what we will Implement right now all right so first I will need to Market as a service so here let's say a service and then I will use uh the required ARS Constructor from lombok and slf forj just for logging all right so here as I mentioned I will need my private final notification repository and let's call it Repository and I will need also uh here let's just say a private final email service it's one that we will Implement in few moments email service and we will create it in few moments but first let's define at least the methods that we want to implement so here we want to have a public void consume payment success notification payment success notification all right and for that we need an object of type payment confirmation so that's why we created the object payment confirmation since it's also the same the same one as we have in our uh or from our producer let's call it payment confirmation so here if we go back to our uh payment yes so here for the notification we have this payment notification request as you can see here we have the same attributes as in this one so here this is so this is so important we need to have the same names in the same way so let me split and move it to right so here as you can see we have order reference amount payment method customer first name last name and customer email written in the same way so if you change it you might face uh issues while deserializing or you need to add the adjacent properties to it okay so I just renamed it differently just to make sure that this is an this is an object or a class depends or like belongs not depends but belongs to our notification service all right so let's continue so the first thing that we need to do is to Define that this method is a Kafka listener so we will use The annotation Kafka listener so we can Define many many listeners but for this one it's just one listener and here we need to define the topic uh not topic partitions but just topics so here we know that our topic is called payment Dash topic all right so then what I need to do first let's log doino and let's say for example here string. format and let's say for example consuming the message from payment topic from payment topic topic like the name of the topic and then just topic and here let's say for example person s s and here I will add my payment confirmation object so I can import this method statically then what we need to do just first of all as mentioned I will save my payment or like my notification payment so here I will create an object of type notification so notification. builder. build Builder and then build so here what I need to do all right so okay so first I need to pass the type so DOT type and the type is payment confirmation so because this is the payment confirmation and let me import it statically then we need to pass the notification date and it will be a local date time. now local date time. now and then we need to pass our payment object or like payment confirmation it will be my payment confirmation all right maybe our payment repository ah okay so it's not of type payment confirmation so it's just of type payment uh of type notification sorry not the payment at all so notification that was the mistake and now the error should be gone all right so first as mentioned we save the notification and then what we want so first let's constract uh so here we will send we will send the email so let's leave this one as a too send email in here and in the same way I will copy paste this method and I will just adjust it so here it will consume our order topic instead of payment topic so it will be order topic and here it will be order confirmation let's rename this one to order confirmation just to be compliant and here consume order confirmation notification and let's call it this way order confirmation notification so here let's keep the message consuming uh topic from order topic and then we need to change the type so here we we will use the order confirmation instead and here let's say in instead of payment confirmation let's call it order confirmation now all we need to do is to send this email so now let's go back to our notification uh so this is payment this is a bit confusing so okay so here we are under notification so let me make it wider so here we are under payment notification project and in here I will create a new class and they we call it email service under the package called email Emil so I will create a new package called email and inside it I will create a class called email service so first of all we need to make this one uh a service and required ARX Constructor to inject our dependencies so for that we need first our private final e Java mail service so Java mail sender sorry not service let's call it mail sender so as mentioned earlier so first later on we will add the configuration ations and the properties for everything like for the mailing for Kafka and so and so forth but just first let's start with the code and we can add the configuration later then I need my private final spring uh spring template engine so this one it's the one from Thim leaf and let's call it template engine so here what I need to do first I will make my Method async All right so because when we receive a notification and we want to send an email we don't want to block the whole process until the email is sent so we can make it async and when we uh when we have an async uh call what we need to do is we need to enable async so here let's go to um notification application and here let's say enable async all right so this this this configuration is done now we can go back and finish the implementation of our Java m Center by the way for for the people who followed already the book social network you know that we implemented something like this and it will be almost in the same way so here I will create method public void send payment success email so I will create one method for the payment and another method for the order so here first we have or we need to pass the destination email so to whom I want to send this email so this Nation email then I need to have a string customer name just this will be the customer name and they will have a big decimal amount so big decimal amount and finally I need the order reference order reference all right so now let's move on to the implementation first as you know I need to create an object of type me uh my message so my message my message equals mail sender. create my message and then I will create my message helper so let's call it message helper equals new my message Helper and then I need to pass two parameters for it so the first one it will be the my message itself so the object that we just created and then we need to uh pass a my message helper message helper do multiart mode mixed related so this value right here so the multiart mode uh mode mixed related and then we need to pass the encoding which is UTF 8core 8. name so let's import this one first so this one comes from by the way okay so let me write it first and then we will import it statically so it comes from the standard uh Char sets do utf8 and then we need the dot name method so now we can import it statically so add static import and now we are done let's also do it for this one so we have at least shorter uh shorter message or I can break it or break break the line so you can see everything so here this my message helper it might throw a messaging exception so let's add the message or like the throws to the message signature so now our message helper the first thing that we need to set is the set from so from whom we are sending this email so let's say for example contact at alibu all right alibu coding.com so this is my uh my email you can use it or like you can send me emails if you want to so then I will create a final string template name equals payment so here I will create just Anam containing the list of uh of the templates that are available for this notification service so let's go ahead and do it so in this email I will create an inam so a class and then select enam and let's call it email templates so email templates so this enam it will be uh it will contain two values first we have a payment underscore SC confirmation so confirmation and here I will add two things so first it will be the template name so I will call the first one payment Dash confirmation HTML so this will be uh the the template name and then I will had uh a subject subject exactly like the email subject it will be payment successfully Pro processed processed so this is the first one I can duplicate it and the second one it will be order confirmation so here let's say order confirmation and here let's say also order confirmation uh. HTML and now let's just give it order confirmation all right so then what I need to do since we have two Properties or two parameters right here I need to declare two things so I will add a getter annotation since we need the get so it will be private final string template and then on the same way I will need also let me add the getter and it will be a private string subject all right then we need of course to add a Constructor with these two parameters so template and subject and that's it so our enam is ready so let's go back in here so for the template name we will select the first one so here it will be payment confirmation or like let's say email templates do payment confirmation. get template so this will be the template name we can also import this one statically and then what we need to do since we have uh now we configured the email we need to pass the parameters so let me add this one to a new line so I will create a map of type string and object so I will call it variables for example equals new hashmap so equals new hashmap and then let's say variables. putut and first of all I need to set the customer name so customer name and then let's pass the customer name as a parameter so I need two other properties or two other variables next I need the amount so we pass amount and finally we need order reference and let's call this one order reference so we will we will prepare the templates later on so this one let's rename it amount after that since we work with them Leaf we need to prepare the context so context the one from uh from them Leaf let's call it context equals new new context and then we can say context. set variables and all we need to do is to pass our variables map then we say message helper. set subject and our template name or just template uh like both of them are fine and here we can say get subject or we can use directly our payment confirmation. getet subject since we are using uh the inam right here then we need to add a TR catch block so first we have a string HTML template so this is the object and we need to call our template engine and ask it to process the template so we need to process the template name and then the context so like the context as I mentioned this is the container uh that will contain or will holds all the variables and the template name is the HTML template that we want to process and then we need to set the message helper. set text and for for the text we need our HTML template and the flag uh HTML to true so as you can see first we have like this first Constructor and the second one is string text with a Boolean HTML then we need our message helper again and set to like to whom we want to send this email and this will be sent to our destination email and finally we have mail sender and then send our my message so finally let's log a few data so it will be log. info uh oops so log okay I did not include my slf for J that's why I didn't have the log so log do info and here let's say for example uh our string. format method and here we say for example this is an info level and email successfully sent to person s s so like this to whom we want to send uh this one with template percent s so here for example um yeah that's it and here we need our destination email and the template name and that's it okay so now we need to catch so what we need to catch we need to catch our messaging exception in case something happened so let's call it e for a simple name and here let's say log. warn it's just it will be just a warning so let's say warning and then cannot send email to and here all I need to do is to pass my destination email all right so let's optimize the Imports and then in the same way we will implement the a method to send order confirmation email so I will duplicate this method just to go or to move faster and then we will I will show you what we need to change so here we will call it uh send order confirmation email so let's rename this one order confirmation email and then we need the destination we need the customer name we need the amount the reference and we need also the list of the products so here I will create list of products and let's call it products so far everything stays the same except here we need our order confirmation inam so let me also paste it in here just once and for all and then we need few parameters so we need the customer name in the same way we need here an amount so let's call this one total amount so this will be the total amount we have the order reference and we need another object which is the products all right so and here it would be products so this part stays also the same so we can also refactor the two methods and make it more generic but this is not so important because uh like the most important one or like the focus of this video is to learn microservices not how to send an email all right so here we have our template engine we have the template name and we have everything almost the same so nothing we need to change and that's it so now we have our email service implemented and ready to be used let's let's go back to our notification consumer and let's bring this one so here it will be email service let's import this class and now instead of this to-do send email all we need to do is just to to send an email to our customer so here first I will start by uh creating or in initializing a customer name object so here I will call it customer name equals payment confirmation. customer first name it's just a simple concatenation like nothing fancy plus and here payment confirmation do customer last name and now all I need to do is to call my email service. send payment success email and here I will pass the parameters so the first one it will be payment confirmation. getet customer email and here the customer name then I need my payment confirmation. amount and finally my payment confirmation. order reference let's remove this one so since our uh send email uh send payment access so let me rename the method so it's send not sent so since this method throws messaging exception so we also need to throw messaging exception or uh surround it with try and catch so let's all just add it to the method right here okay so I will copy this one and now we need to replace this to do in the consume order confirmation notification so here it will be uh instead of payment it will be order confirmation so let me replace it let's paste it in here and now it will be customer DOT first name and here it will be order confirmation. customer. last name and we need parentheses in here all right so here we need need also again our order confirmation. customer. email let's replace with this one the amount is our order confirmation. total amount and here we need our order confirmation do order reference and finally we need our order confirmation do products and this one it's not send payment success email so send order confirmation email and of course we need to rename MIT since we made the typo and also we need to add the exception to the method signature and we are done so now we have our notification service implemented so let's just recap really quick so what we did in the beginning so we created the project we added the dependencies and then we added uh or we created a notification document just a document to contain the information of our notification and then of course we need the repository and this is just an enough to uh differentiate the type of the notification whether it belongs to the order or to the payment then we know that we will consume two types of data so first we have the order so here this is the order confirmation object and as you can see it contains order reference total amount customer and products so we need to create the customer and also we need to create the products in the same way we created a payment confirmation object containing this information within the payment method that we declared in the payment and then we created our notification consumer which is like two simple Kafka listeners one listens for the payment topic and the other one listens to uh to the order topic and here what we did is just to pass the object that we are expecting as a parameter to this method and all we need to do is to process it send the email and do what we need to do with it and finally we implemented our email service all right so now just to finish with this one let's close all and now we need to add the properties for our notification service so I will change this one to yaml representation and I will make it full screen and now we will add the properties to our payment service so here first of all it will be application and then name and notification so here let's call it notification Service as always and now now I will go back to my config service to or my config server to copy few properties instead of just retyping everything I know my customer service uses mongodb so I will copy this part so this is we can start with this one so here spring and then we copy the mongodb properties and then I know also that my order service has the Kafka properties so I will copy and show you what you need to adjust so let's copy all the Kafka part and let's come back in here and paste this Kafka in here all right so now since our notification is the consumer so instead of producer we need to change this one to Consumer all right so for the consumer what we need to do so we need first our bootstrap servers we need to define the group IDs all right so I will move it to the uh up so here I will create two groups so first payment group so like one group for payment and Order Group so order group so these are are my my consumers and then we need to define the offset or like the auto offset reset and let's say earliest so if you are missing uh few information about Kafka please refer or go back to the kafa video that I that I published before in my YouTube channel and here when we talk about consumers we do not talk about serializer but we talk about deserializers and it's the same for the value deserializers and now we need to add properties so the first one or like the one we see in here stays as it is so here we have the spring. json. type. mapping and here we need to map it as I mentioned before in the same way so we have order confirmation which is com. alibu Commerce and like we need to specify or to provide the full package of this one since we consume two types of data so here we need to go to our payment service and we need to copy also this one all right so we need to copy this mapping and be careful of typos since if you have a typo you risk that the application or like the Kafka consumer will not work so here we just separated with a comma so here we add a comma and then payment confirmation uh payment confirmation object with the package or like the full path of the payment confirmation object now we need to add other property so here there is a property so by default Kafka has a security so when we send an object of type order confirmation from a specific package you will you will get an error message saying that this this is coming from an untrusted location or an untrusted package so what you need to do you need to tell Kafka what are the trusted packages so here you need need to add another information it's called spring. json. trusted packages so trusted. packages and then you need to specify the list of The Trusted packages so when you are working in development mode or locally or like in a nonprotected environment so you can accept or you can say it's okay we can accept star otherwise you can say for example I want to accept anything coming from com . alibu Ecommerce dostar for example or you can provide the list of the packages separated with comma in here and to to tell these are my trusted packages all right then what we need to do we need to add the some mail properties so in the same way as we did it before so here we will provide the the properties and then first let's say host and it will be Local Host uh since we will use uh mail Dev and we need to specify the port which is 1025 and you just username uh let's call it alibu so it's you can you can type anything in here so it's not mandatory so and then alibu and let's define some properties properties so the first property will be mail and then let's say SMTP and then let's say trust star so like we want to trust anything since since like also adjust a Dev mail or like uh it will be working locally and here we have we have an authentication and let's set set it to true and start TLS let's say enabled and then true so it's start DLS and then we can also set a connection timeout let's set it to 5 Seconds this is like the basic configuration that I use almost everywhere and here we can also Define a timeout of 3 seconds and write timeout of 5 Seconds so these are the configurations of my notification service so I will select all and then in the config server in the configurations I will say here I want to create a new file and then we call it notification Das service of course yl don't forget the the extension of the file and here all I need to do is to remove this one and finally don't forget to define the server and then Port so for this one let's let's use the 840 for example since we used the 80/50 60 70 and so on so forth so for this one let's use the port 8040 that's great now we have all almost all the microservices implemented so here we just need to finish this one so let's go back to this let's do some cleanup we need need to leave only the spring uh spring application name and also we need spring config do import so config do import and here let's say it's optional and then config server and our config server address or URL so it will be Local Host and then four time uh 4 * 8 so this is what we need to Define for our notification micros service so let's close everything and now let's go back to the diagram so here I cannot use a check mark but we implemented customer product order payment and notification we also have our UA server or Discovery server and we have also our config server so now in order to start uh testing the application all we need to do is to implement our API Gateway but one last thing before moving to the implementation of the API Gateway we forgot to uh to create our email templates so let's go back to notification and then Source main resources and here all I need to do is to create a templates folder so let's create first a a folder and we will call it templates because Tim Leaf will automatically fetch the templates from here so now let me open also the email templates and just copy the names so here I will create a first file and I will call it payment confirmation. HTML and another one order confirmation. HTML meanwhile I will ask chat GPT and I will provide it with uh with a context and as much information as I can and I will ask him to generate two uh two templates one for the payment and one for the order so I will just paste you the code explained quickly and then we will see the output later on when we test the full application all right so now I have here uh this is what CH GPT generated for me so it's simply like it's a simple HTML file with uh payment confirmation title with the customer name as the information that we passed so this is the theme Leaf uh text so this will be automatically um interpolated and mapped so here the same uh for the payment so like this is the amount the order reference and here this is a simple thank you message so in the same way I will paste uh I will paste the the code from the order confirmation so for the order confirmation it will contain the order details as a as a header or a title uh the customer the order ID and here we will have a table containing the product name the quantity and the price and here we are looping over uh the products that we passed as a parameter and finally in a footer we will we will display the total amount and like a simple message and Let's Pretend This is just all rights reserved by my name all right so now we have the templates we have everything up and ready so now let's move on and start implementing the API Gateway micros service now in the same way as we do be always so let's create a new project and let's call it Gateway so it will be Maven Java 17 and let's leave the package also as uh alibu do com. alibu and then e-commerce or for this one we can also leave it as a Gateway so let's leave it as it is and here we need our Gateway so it's not a reactive one but just Gateway we need also our Discovery client and we need of course our config uh config client so here let's search for config and then config client so this is all the dependencies that we need for our API Gateway so let's click on Create and import our project as a maven project project so plus let's select Gateway pom.xml and then open so for the API Gateway really nothing fancy nothing uh like we don't need to write any logic all we need to do is to provide some properties and some configuration for our API Gateway service so like we need to Route all the all the URLs when once we receive them from the API Gateway we need to Route them to the correct micros service using Lo load balancer and using the service name so let's go to our G API Gateway and then Source main resources and application. properties so first I will change it to yaml file and I will make it full screen and let's start adding the properties of our API Gateway so here and let's all call it Gateway service so here first I will Define my server port and I will make it 8 8222 all right so now let's add few properties first we have spring. cloud. Gateway and then we have Discovery so I will just make it manually so we have uh spring Cloud Gateway and then Discovery and we have an attribute called locator let's set it to True uh locator and then enabled and we set it to the value true and now we need to Define few routes so at the same level so here I think we are missing Discovery and then locator and then enabled true so now in the same level of Discovery we will Define our routes so here we have uh an attribute uh called routes or property called routes so for these routes we will Define the different routes that we have so here we will start with the first one so let's give it an ID which is should be the C like the same ID of our service so let's call it the first one we will start with the customer service so then we will have URI so what what should be or what is the URI for our routes or for this specific route so here it will be lb for load balancing and then I want to Route like when when I receive something I want to Route it to uh Local Host HTTP SL SL and then customer-service so this is the service ID in the urea service all right and then we can Define also predicates So based on what based on which predicate I want to route my service or I want to route my uh my URLs so I want it to be based on ath so when I receive something with the pa/ API slv1 SL customers SL star star so like SL customer SL anything I want to redirect and to load balance this uh this request to http uh col customer service so that's why we need to use uh our Discovery service in order to avoid uh managing or like creating many instances or like in case we have many instances we don't need to manage each of them or like where to Route what is the available one and so on so forth so the API Gateway will take care of that so in the same way I will copy this one and I will paste it in here so the second one will be my order service and in here I will use order service and in the same way slash orders slst star star and then let's paste and implement the next one which is our order lines for example order Das lines and here for this order Dash lines I want also to redirect it to the order service okay so here let's rename this one to order service and then the predicates when I receive something with order lines so order lines I want to redirect it to this to this one all right so here I see that you have have uh some warnings let's check if we imported the correct dependencies so in here we have config we have spring boot Cloud starter Gateway MVC okay so it's not the Gateway MVC it's just spring boot starter spring Cloud uh starter Gateway so let's uh refresh the dependencies and now okay all right so now now it looks much better so uh hopefully my ID helped me to uh to figure out what are the uh the missing things so now we have as I mentioned we are defining the routes or the different routes of our application so the next one let's add the product service so here product service and here I want to Route it to product service and the pattern or the predicate is/ products when I receive any request with uh with containing this path SL API slv1 / product/ anything I want to load balance my request to the product service from my Discovery service so here I'm just exposing all um I'm exposing all the microservices but then we need just to filter them and expose only the ones that we see in this diagram so like only the ones connected to um to the API Gateway which is customer product and orders all right so like the payment we don't need it but I will just mention it in case in case you need it all right so here I will just call this one payment service and here I will also call this one payment service and then we have uh we have the path all right also we need this payment because uh because we have or we use internally this payment microservice so for example when we want to send or to start processing a payment from the order we mention that we want to go back to the load balancer and uh and proceed to the payment but we can add later on a security level level just to uh to say or to mention that we cannot proceed or like we cannot process a payment from outside the the private Network so this also can be uh can be done later so for the API Gateway this is this is all what we need so I will select all and then in my config server Source main resources and then configuration I will create a new file and I will call it Gateway service. yam and I will paste everything in here so now I just need to remove this application name and now let's go back here and let's remove all the unnecessary things since we externalize them to uh to our configuration service and here we need to add uh our config do import and then optional from our configuration service and then HTTP colum SL SL Local Host and then 4 * 8 so this is what we need for our API Gateway again let me uh re explain or like uh clarify the properties that we have in here so first here we have our spring Cloud Gateway so these are the properties for our API Gateway and here we have Discovery locator through enabled uh Discovery locator enabled set to true this means that we want to connect to our Discovery service like we have in this diagram right here so we want to connect or like we want that our API Gateway connects to the urea server and fetches all the available all the available instances and microservices from there and then what we need to do is just to define the routes so the routes we Define them in this way so this is like a table representation so the first one it will be the ID so like we need to provide the ID of the route so it's a customer service we can also do that using Java like we can we can implemented using the code but within the properties it's also doable and it's also like personally I prefer using it or like doing it using uh using the properties and then this is the URI so like where we want to uh to transfer or to redirect the request so here we want to redirect when when we get a request for the customer service we want to redirect it and lb is load balancing all right so we want to load balance it to the HTTP customer service and based on what so here we have predicates okay so for the predicates we have one of the properties or one of the predicates we can do it based on the path so when we receive any request containing SL API slv1 customers slash anything we want to redirect or to load balance this request to the customer service all right so also we can add uh we can add other predicates let's say for example headers or or header equals something let's say I don't know like blah blah so if I receive something with the header called Blah Blah with this path or even without the without this path so uh I want also to redirect this request to my customer service so here you can play around or like you can you can uh customize the routing the way you want in the same way we implemented the order service order lines and and and as you can see in here Order and Order lines both of them they will redirect to the same micros service or to the same service and but the only thing that differs is the predicate in the same way we defined the product and also the payment the payment service so now all we need to do is to start all the microservices we need to start the whole architecture and we need just to test it using Postman and let's send my our first request and see if we receive an email if we are able to process all the data but first of all let's go ahead and check this information right here so here we remember that we created uh the database product with a category and with a few products using Flyway and here in the payment we did not start yet the project so we will start it so let's go back to our uh payment service in here and just let's check or recheck the ddl auto so here this one let's say update for example for the for the payment and the same way so here it's create so let's say also validate uh sorry not validate but just update because I don't want to delete the schema when uh when we restart the service and now all we need to do is to start our application and start testing it so let's move on to the test part all right so now we can start the testing phase but before moving forward I just want to highlight something because while copy pasting uh some code I just forgot to change few things so in our notific ation service right here we have our consumer and here we have the key deserializer and the value deserializer so while copy pasting here this one it should be string der deserializer instead of string serializer and the same way for the Json serializer so because we copied it from here and in here as you can see it was string serializer and Json serializer but for the consumer we need to deserialize the values and the objects also here in these properties and mainly in the spring Json type mapping so here we mention that we want to map our order confirmation so this is the object let me re-explain it again so for example when we talk about the order here in the order service we said that we want to send an object called order confirmation and from the producer this is the package or like the full path of our object that we want to send within a key called order confirmation and when we want to dis realize it we we need also to provide the same name or the same key right here but the value should be also the path of our order confirmation in our notification service so here if I go down to our notification service and then Source main Java so here we have it in under com. al. Ecommerce which is this first the first part right here and then it is under Kafka and then order and then order confirmation so like the URL or the path of this CL CL should match exactly the path of the target object where we want to deserialize our order confirmation object and the same goes for the payment confirmation so also payment confirmation it's under the same base package and then Kafka and then we have payment in here and payment confirmation object so this is what we need to change before moving forward and starting our applications and start the pro the testing process so let me close this one once this uh this is clear and now all we need to do is to start the different services so first let's start with our configuration service so I will start with the config since all the microservices they need to pull the configuration from our config server application and here just to make sure so this one we know that it's uh running under the port uh 8888 then we need our Discovery server application so since all the applications or like the other microservices when they start they need to register themselves under the Discovery application so here like you can notice something or like you can uh early debug or see if something is is wrong so for example let's assume that our Discovery server application is not correctly pulling the configuration from our config service so here we have our Discovery server so here we have the server. port and here as you can see we have the discovery application and it's running on the server or on the port 8761 which is the one that we pulled from our config server so here I will just uh for example for the customer application I will just make a change just to show you what I mean exactly so here I will go to resources and I will just I make a typo in here all right so when I start my customer application let's see what will happened in here so now let's start it so the application is up and running which is okay but as you can see the customer application is running and on the port 8080 which is the default one that's string users so this means because we have this optional right here so when we remove the optional the application will fail when when it tries or like when it fails to pull the configuration so this optional has two uh two sides effects so here if we are not uh if we are not able to pull the configuration the application will will still uh will still uh start but with the wrong configuration so as you can see here it's the port 8080 so whether you can remove this option right here or or leave it or just make sure that you have the correct Port of the application so let me restart this one and now you will see that the customer application Port will change to the one that we specified already in the config server which is the 8090 all right so in the same way let's start the other uh the other services so we can start them in the same order as displayed in here it's not a problem so the notification application it's not a web application we decided to not to do it or not to implement it as an web application so that's why we don't see a port right here so again or in the same way let's start the order application payment producer and finally we need to start the API Gateway since the API Gateway need needs to pull all the configurations from this discovery application so well it's a reactive one so like the API Gateway it's a reactive one and it will keep on updating or on checking um like or sending uh a heartbeat or a polling service like you can call it whatever you want uh to our Discovery application and checks every time if we have uh if we have an application or like a new application available with a new port and so on so forth like a new instance so this will be also fine but here just for testing we start everything so we start with the config server and then the discovery so these two are mandatory to be started first and the first one that needs to be up and running is the config server because all the other microservices they need to pull the configuration from our config server otherwise we will fall to the to the scenario that I already explained about the customer application and finally now we have our API Gateway up and running and all we need to do now is to go to postman for example and start testing our application so here as you can see uh by the way so here I just enabled the debug level for uh for the API Gateway and that's why you see that we have this debug and you will see this message even if I clean it and like you will see this meth this message uh like these logs that the API Gateway will keep uh reaching the discovery application or the discovery server application to see if we have new uh services or new instances available for us all right so now we can go to postman and start testing the application so here I prepared two end points the first one is to create a customer reaching the uh the Local Host 88222 which is our API Gateway port and then SL API V1 customers and the other one is to create an order it's supposed to request and in the same way it will reach the the API Gateway and then API slv1 order with the information that we need to pass to our order application but before that I will just duplicate this tab and check if we can reach or like if we can fetch our products so I will try products and this one will be a get request so we don't have a body so I will just click on send so here we see that we have a 200 and this uh this is the list of our products since uh since in our product uh service or product microservice we have already an endpoint that fetches or Returns the list of our products all right so now let's go back to uh to this customer and let's start or like let's try to create a new customer with this information like John do and the email John email.com and this address information so I will click on send okay so here first we see that we have a 404 404 means that we don't have this path or like the API Gateway is not able to find this path so this means that maybe we we made uh a typo in our customer microservice so let's go back in here so let's check the customer so under Java and then customer and the typo should be somewhere in here all right so here when we created the post mapping it should be customers not customer or like we change it also in our Postman but the best way is to follow the the naming uh the naming conventions of a of the apis so let's change this one to customers and all we need to do is to restart our customer application so I will restart it from here and then we can proceed or like we can go back to test our application so the application is trying to restart also we can check uh we can check in the browser that we have all the instances up and running so let's go ahead and check first all right so here if we go to the address Local Host uh 8761 which is our Discovery uh Gateway and all we need to do is just to restart uh or like to refresh our application and as you can see here we have for the customer service we have one down and we have one up so the one up is the one that we just restarted and the one down because like um for the old instance or like for the previously running instance the Discovery Gateway or the discovery server will try to reach out this one so like if if we wait a few times and refresh this uh this view we will see that we will only have this one up and running all right so here we see that we have our customer service API Gateway notification order payment and product service so all the products are registered under our Discovery server so now if we go back to postman and try to create this user so let me click on send and here we have uh we have a 200 response with the customer ID so let's go ahead and check it under um under our X Express so we said that it's running under the the port 8081 and by the way if you get interrupted to provide credentials the credential is admin and pass so like admin for the username and pass like with p as a password so here we see that we have our customer database got created since we uh we inserted a new customer in the database and here we see that we have customer and then we can check the customer information which is we have here the information like the the first name last name email and this is the address object so if we create another one we will also have the same information in here all right so now we can go back to postman and we can proceed or start create of our first order so also here in the same way I prepared the body of our request so the reference it will be something like this so here maybe we can change this one to 2024 uh 1201 or like maybe we can change the date or like we can change the reference and here we have an amount we have a payment method which is PayPal and we have a customer ID so the customer ID we need to get this one so first let's let's try with a perfect scenario or like with with a nominal scenario like providing everything in in a correct way so also for the product IDs since we have our product database or the list of products that we have in here so let me refresh and let's check the product database and in here in the product we have public tables and then product so in the product we see that we have this list of products with the IDS that I provided in here like 1 8 85 uh 851 2 uh 2 51 and so and so forth so now all we need to do is to click on send and see if everything will go fine so here we we send the request but we see our 500 internal server or error so let's go back to our application and let's check the logs so here let's first check our API Gateway so in the API Gateway we see nothing or we don't have any errors so uh only this debug levels and they will remove it just in few moments and then let's go to our order application so in the order application we see that we have an exception so let's go ahead and check it and here among the exception we have a Fain exception not found we have a 404 so this means or like it says like a 404 not found during post like when sending a post request to our payment micros service so I think like or I have uh the feeling that we also made a typo in the payment uh micros service so let's go to payment and then Source main Java and then payment and payment controller so let me make it full screen and yes exactly so this one is like it should be API L not I ipu so here also I will go back to uh to my Gateway since I enabled the the debug level so I will go to back to API Gateway M main resource application and this one like I will I will completely remove it because I just wanted to check few things meanwhile so now I can remove this one and all I need to do is first to restart my payment application so I will stop it and restart it again and in the same way I will restart my API Gateway application just to remove this uh debug level that we saw all together all right so let's restart this one and then we can go back to postman and send the request once again so here we need just to wait few moments until the API Gateway is able to fetch all um all the services from uh from the discovery and now we can go back and let's now click on send all right so here we see that we have 200 and we have the ID of the newly created order so now let's open the browser and check the mail and see if we receive any mail with the information that you specify and the template that you specified before so I will open a new tab and open my Local Host 1080 and here we have two emails so the first one we have an order confirmation so we have order details for the customer joho and this is the order uh the order reference that the one that we created we will create a new one and we will change the customer also and here we see the information or the list of the products which is the product name with the with the quantity and the price and we have here a total amount so like the total amount is not well calculated but it's it's fine because this is just to test the microservice architecture and here we see another email which is the payment successfully Pro processed so payment confirmation so here I think we also have an issue with uh with the mapping of the username uh of the customer first name and last name and here we see the information of our of our order so like we can we can fix this uh this few things in just few seconds now let's go and create another customer so here uh in the customer I will create for example Ali bu Ali and this one I will change it to Ali mail.com we can leave the rest as it is let's create so this is the our new customer ID also if we go back and check the customer database we should see the Ali Ali atmail uh.com all right so now let's go back to postman and here first I will just change something here so like I will put some something that doesn't exist all right so like a customer ID that doesn't exist and let's click on send so here we have our 500 error so this first like we need to uh to handle all the exceptions in the order service so this we can do it uh later on and also let's go back and check our order application so I will just clean and send again and here we see that we have a 404 not found during call uh during fetching the customer with this with this ID which is which is okay and here we see that we have no customer found with a provided ID and this is the log that we provided already in our customer micros service so now let's go back let's take again our customer ID and replace it in here so now let's leave this one to 2022 24 and let's say for example 401 and let's click on send and now we have another issue so let's go ahead and check it so here we have an sufficient stock quantity for product with ID equals 1 so here if we go and check our product uh table so here let's go back and check this one so now here we have the available quantity equals zero so that's why we were not able to purchase this product so maybe let's change this one to 40 manually and this would be also fine like it's not it's not a big problem and now let's go back to post man and send this one again so now we have our 200 and if I open back the browser so here first let's go back to our database and let's check the notification so the notification we see that we have order confirmation order confirmation and this one for example is for John atmail [Music] here this is the one that we just created and for the customer we see that we have the customer information and for the product we see also that we have this three product information all right so let's also check the email so first we have our order confirmation to the correct customer with the correct information that we provided earlier also we have our payment confirmation I think here we just forgot to pass uh the parameter of the customer first name and the customer last name so we can fix that and then then we can proceed to the next part of our implementation while testing the application we saw that any of the services might throw an exception so it might be whether a technical or a business exception so here let's focus on business exceptions for example so when we start an order here we have two uh two scenarios so whether the the customer does not exist or the product uh we have insufficient quantity or the product itself does not exist and so and so forth so also when we try to follow up since we just already know the architecture of our application but imagine that we are working in a new project and we are just on boarding on it and we don't know the architecture and how the different components or the microservices are linked so here what we need so we need to enable or to have a tracing that gives us the all the flow from like uh the entering request until the end of the request so for that we are talking about distributed tracing so for that we will install Zipkin and we will Implement distributed Racing for our application so first let's go ahead and add Zipkin to our Docker compose file so I will close this one and then open my Docker compose file and somewhere here for example let's say Zipkin so we will install Zipkin so whether you can use Docker compose or you can just go to the to the official website zip. AO and download it and use it from there but since here we are using uh Docker compos or Docker infrastructure let's continue using this so I will call it Zipkin uh Zipkin without G and then we have the image so the image is from open Zipkin so open Zipkin SL Zipkin all right so slash Zipkin so this is the image we can also use the latest and here let's expose some ports so by default Zipkin uses the port 9411 over 9411 so like the right hand side is the port name is the container Port uh number and this one is the one that we will use in our case let's also make a Zipkin part of our Network which is our microservices Network so now all we need to do is again to run Docker compose up minus D and we need to check that everything is up and running as you can see in here so the next step is to set up zip for our application all right so now let's start with our API Gateway so here we will just follow uh follow the different microservices that we have here like API Gateway uh customer product order payment and notification microservice all right so now in the API Gateway let's open the pom.xml and here let's click on this edit starters or like I will show you later on also the dependency that we need to add so let's click on edit start starter and all we need to do is to search for Zipkin so the Zipkin is part of the observability group let's hit okay and here we will see that we have the Zipkin uh the Zipkin dependency so here when we when we add Zipkin it automatically will add the spring boot starter activator so the spring boot starter activator it's like a micrometer or like it will expose some um health check end points and like a bunch of other information that are needed and the main dependencies about Zipkin is this one I will just group them here so here we have spring boot activator and here we have the IU spring boot uh Zipkin reporter and spring reporter Brave and we have the tracing Bridge Brave so these are the three dependencies if you have already uh activator it will just add these two dependencies so let's do the same in the for the other microservices we also need it for customer let's go in the same way click on edit search for Zipkin add and then okay so then in the same way you will have uh spring boot activator and spring boot reporter Brave all right let's continue for the other microservices the same for notification so here click edit starter search for Zipkin select it and click okay and then we have order and then let's do the same way let's search for Zipkin select this one and cck click okay so here you see that you are adding the spring activator Brave and The Bridge Brave and finally or like last but not least we have also our payment micros service let's add Zipkin select this one click okay and finally we have our product so here pom.xml and edit starters and let's search for Zipkin and let's click okay all right so I will close all the tabs and here in the maven I will update all the projects so like I will select all of them and click on this on reload all my projects so it will download and add Zipkin to the class path so here before moving forward and adding the configurations for uh for Zipkin for the different applications so here let's check something so let's try for example to add it to the API Gateway and let's start with uh application. yl so since here we can see or like we will have the auto completion so here it uh the this information or like the properties that we need to add is under management so it is under management and then we have like uh Zipkin for example so let me show you we have Zipkin and then under Zipkin we have a bunch of information so we have tracing do endpoint we have trace a connect timeout and read timeout so all these three information they already have a default value so let's check first the Endo so the end point as you can see in here it already has a default value which will point to http Local Host 9411 so like it's uh 941 so this is the default Port that spring will try to use so in case you are using a different port locally or uh for your infrastructure in this case so for example this Docker compos file if you decide to use another Port let's say 22 or something like that just make make sure to add this information right here all right otherwise it will it will be able to automatically get it from from here from the default value the same for the re timeout and the other and the other properties all right so like the same for The Connect timeout which is 1 second and Al also the re timeout which is uh 10 seconds so for that we don't need this all we need to do is to add tracing and then we have something called sampling and then probability so here let's check uh our probability and let's read about it so the probability is simply like the probability in in the range of uh in the range from 0 to one that Trace will be sampled so here in our case we want it to be 100% so let's give it the uh the value 1.0 so like the probability it's between 0 and one so uh 0 means 0% and one means uh 100% all right so this is all we need to do in order to configure our Zipkin or or our distributed tracing so I will cut it and now I will go to our configuration server and then Source main resources and in here we know or we remember that we have our application. yl that all the files they extend from it all right so here all you need to do is to paste this property in here and nothing else is required to do in order to enable distributed tracing with Zipkin so now what we need is just to test the application like to run the application and then to consult Zipkin and see what is going on now in the same way as before I will start the different microservices so I will start with the configuration server and then the discovery and then I can start all these services in the correct order so I will select all of them except the API Gateway and start all of them so like the will be starting one after the other and once they are all up and running I will start my API Gateway and perform the first request or like one request and see if we have everything or like if we can see the tracing so now we can start our API Gateway and meanwhile we can go to the browser and have a look on the Zipkin UI so here let's navigate to Local Host and then 9411 and here we have our Zipkin interface so here we will see see the list of of all the requests all the traces and here we can perform a search we can see the dependencies and bunch we can also run some queries and so and so forth so now let's go back to our Postman and let's perform our request so here let's first start with products so let's try to quate the list of products which is success and now let's go back to Zipkin I will refresh and here when you click on run query you will see this so here what we have we have our Gateway service which is an HTTP get and here it was uh it was reaching the API Gateway service and then the product service and here we see that we have three spans right or like three stops so here if we if we open this one so we have our API Gateway and then we have our product service so here for example the product service it took uh one 109 milliseconds and for the Gateway service it took 215 and for all the request it took 279 milliseconds to complete now if we go back again and try so first let's check if we have a customer already so I will refresh this one okay database not found all right so we need to create a new customer so let's create the customer so let's keep the same information and click Send so here we have the customer ID and again if we go back to our Zipkin and let's go back to the homepage and and run query we see that we have another another one so like this this was the first one which is an HTTP get and this one we see we have an HTTP post so we see that we have Gateway service and then we have our customer service again we have three spun so now let's perform or let's purchase some products and see what will change in there so first I need to copy my customer ID and use it in here so like for the rest I can keep the information as it is and click on send so now we have a 200 and here we can go back click on run query and now we see that we have many things so first I will order them by uh by start time just to see always the latest ones so here we know that this one was uh to fetch the list of the products this one is to create a customer and now let's see so here we have Gateway and then payment service we have now Gateway product service Gateway customer and finally have Gateway order service so why we have that so here when we uh let's go back to our diagram let me open it here and I will explain few things all right so now when we first uh started or like purchase an order we hit the API Gateway and then we went to the order micros service and then the order microservice will perform two checks one is uh regarding the customer and the other one is to purchase some products and finally we have we have payment so here when we we configured our application let me remind you in here in our config server and then when we go to our order uh service. file we see here that we Define these three URLs so we have customer URL payment and then product and all of them they reach the API Gateway instead of reaching the the API itself directly using the customers or like the API customers boort or the payment microservice and so on so forth so we we decided that every time the order microservice needs to check something or like to to check the customer we need to send the request again to the API Gateway and then we need to load balance it so here like this is one approach another approach is to use since for example for the customer or for the product you are using open fan open fan also supports load balancing so we can we can use the load balancer or like the load balancing functionality of open fan in order like to redirect and communicate with the microservices internally without the need to go up to go back to the API Gateway so here we can for example uh for the customer microservice we can change the ports and see how how this will be uh impacted or like how this will impact our tracing so just a test so let's go ahead and do it so for the customer application it's 8090 and the payment microservice it's 8060 and finally we have have product which is running on the port 50 all right so now since we have only one instance running all I need to do is first to restart my configuration server since I just uh changed the config and then I need to change my customer I need to change uh I think um yeah I think I need only to change the order application uh not change but just to restart the order application since we changed the configuration for the order service so we don't need to restart all the other applications and also in here like we can enable the auto uh the auto reload so if we change something the order uh the order application will automatically refetch everything from here so now let's go back to Zipkin and let's see if we can clear uh everything or uh I think it's fine so we can keep it this way we will always uh filter or order it by by the start time and also we can change a little bit the limit uh whether the limit or like the time so we can fetch for example the last 2 minutes or 3 minutes just to to check that all right so now I already have everything like I have my customer I have everything so here maybe let's change this one to 600 just to CH to see the difference and let's click on send so now we have our new ID and if we go back here and just rerun a query we will see that we have another one all right so here we will order it with uh we we'll sort it not order it with start time and let's go ahead and check so here we have our API Gateway going to the order service and then we have uh all right so let me just go back all right so now we see different different logs so here we have our payment service which is which was reached or like uh we used it from the order service and then we have also our API gateway to the orders uh again I need to okay all right so product service and then we have uh our customer service and then we have our order service from the API Gateway all right so this is how the tracing looks like now so let's go back to anti J and bring back our configuration as it was before so we can keep it consistent let me restart this back and now we have our distributed tracing using Zipkin you can go and explore more and more Zipkin with and and check the functionalities and what Zipkin is capable of also um in the future we will build uh another dashboard or like another distributed system with using the elk stack so like the elastic search L stash and kibana and I will show you how to build few dashboards how to uh how to improve the logging and how to improve like our application generally speaking so now we will move to one topic which is one of the most important topics when we are implementing an application when we talk about designing and implementing uh a solution security plays a crucial role in our application or in our architecture so for that in our microservice architecture we will set up kick loock to secure our ecosystem and here in order to secure our application we know that all the requests they go through the API Gateway so for that we need to set up Ki loock and link it or like um validate each request coming to our ecosystem on the API Gateway level then for example if uh for some or like for for example let's say for the product service or for the order service we have some end points that require some um some extended roles or uh or authorities to uh to do this action so we can also set up the security in this in this level and Link it to the same kick loock instance to validate the to validate the user and to validate all the information and if the user has the roles to uh to connect or like to perform the required action but for now we will Implement our security on the API Gateway level and that's it that will be or like that should be enough to secure our ecosystem but as I mentioned if you want extra security you can also set up or like use the same way or use it in the same way on the different microservices and for that also if you are new to kick loock I would like to invite you first to check the two videos that I have on my YouTube channel which is uh the kick lock uh the kick lock videos and also the one that we used to integrate it with the book social network in order to have a complete Vision or uh to uh to move or like to understand how kickl works and how we can configure everything so for now we will not be focusing on kick loock or like how how kick loock Works how to configure it how the flow is but we will just uh assume that you already know this information and we will proceed from that so the first thing we need to start by setting up kick lock in our Docker compose so here after Zipkin I just copied the configuration from the book social network um Docker compost file I will just perform few changes and here I will just call it uh kick lock for microservice I will use the 242 or like any other recent version and I will expose locally the port 9098 or 9099 and here for the environment we have our uh kick lock admin and kick loock admin password it will be admin admin and and for the network let's assign it to the same network and of course we need the command start Dev in order to start our our server all right so now we have key loock set up and ready to be used now let's move to the services and then API Gateway so in the API Gateway here here we can add uh we can add the dependency from here like using the starter and all we need to do is to to search for our resource server which is our O2 resource server so let's select this one click on okay and let's check the dependency which is this one so it it is the spring boot starter o of2 resource server then let's go and add some properties so here in the same way we will externalize it to the config server but first as we do always here all we need to do is to add the following properties which is spring. security and then we have O2 and then we have resource server and then all we need to do is to specify the JWT URI and then we need our issuer URI and it will be uh HTTP colum SL slash Local Host and then 909 8 and then of course we need Realms let me make it full screen so Realms and then for example let's say micros service or like uh let's let's call it micro service so we we did not create the realm yet but we will create it just after that so we have uh our realm will be called micro service or micro Services all right so now we can start our kick loock instance and go and and start and create our realm and create our client for that now we can create our security configuration so I will create here a new class in a package called security and I will call it security config so here we have few differences from the classic security implementation even with kick loock since here we are we have a microservice architecture and on the API Gateway it's a web flux or it's a reactive one so here let's let me show you what I mean so here when we go to the spring Cloud starter Gateway dependency and click on it so here you see that you have this dependency called Spring boot starter web flag so this means that we have a reactive web in here so let's first add our configuration in here and then we have enable web flax security instead of enabling just web security we need to enable web flag security so now what we need to do we need to create a be and it will be a public security web filter chain so instead of just security filter chain this one will be security web filter chain so let's call it security uh filter chain and here we need to pass uh an object of type server HTTP so let me fix the typo server HTTP security so let's call it server HTTP security and now let's add the configurations so first what we need to do is our server HTTP security. csrf so we first we want to disable the the cross uh the cross site resource forgery so to do that it's server HTTP security and then we have csrf uh spec and then we have a disabled property all right so then we need to authorize few exchanges so here instead of authorized requests when we talk about reactive web we talk about exchanges so here we have exchange and then we will use Lambda expression so it will be an exchange and then I will add few properties so first I want to uh for this path matcher which is so here like we are talking about UA all right so we want to authorize all the requests for our Discovery server so it will be /u/ star star this one where I want to permit all and then any exchange I wanted to be authenticated so here authenticated and then we need to Define our oo resource server so here I will add oo to Resource server and for this one we need to customize uh to customize it for our JWT so it will be for example let's create a variable it's called o of2 and then we will use our o to object do JWT and then we can use our customizer and then with defaults so we will use the default implementation or default configuration from Spring and finally all we need to do is to return our server HTTP security. build so now we have the configuration or the security configuration for our API Gateway that will filter all the requests except the UA so this one will be permitted and all the other requests should be authenticated now we can move on to kick loock create a realm create a client and then we can start or like we can do uh or perform the testing process so let's open the browser and let's go to Local Host and then 9098 so this is our kick lock but first we need to do a Docker compose app since we Docker compose app minus D to have all the all the instances or all the containers up and running now if we refresh this page so we will have our our kick loock interface all right so here let's log in with our admin admin and here all we need to do is first to create realm so let me close this one so here let's create a new realm and let's call it in the same way as we did in here so let me close all this and then we go back here and this is our realm name so we will move this configuration then to the config server uh but now like let's finish implementing this one so here I will call call this one micros service and I will set it to enabled true and then in the clients all I need to do is to create a new client so let's leave it open ID connect and here let's call it microservice API or client or whatever you want so here we can also keep the same name as a display name the same for the description we can also enable this one to see it on the UI which is totally fine so here I will enable authentication uh client authentication and authorization and I disable this two so like I don't want to authorize any flows except client authentication and authorization and I will show you what is the impact of these two buttons so here uh the root URL and the home URL so let's leave this one as it is and now we have our configuration or our client what we have in plus is this credentials tab so in this credentials we have our client ID which is this one and also we have our client secret which which is this one so in order to authenticate a user so for this one like we can go back in here and disable this client authentication and authorization and and enable with the standard flow and the direct access so in that case or like in this way we can enable the user registration and then the user login we can we can uh authorize the user login within the grand type password but for this time we will use the grand type uh client ID and client Secrets all right so like we we can play with this one so let's click on save to save all the changes and then we will need later on when we go to postman we need to uh to pass this client ID and client secret all right so now we have everything up and running so let's go back to our IDE and start all the microservices so as always we need first to start our config server application and then the discovery server and finally we need to to start our API Gateway so I did not yet move the configuration to the config server we can also like keep it in here so it's not a problem and then we will move it to our uh to our configuration server and do like a final check so now I will select all this uh these services or like servers and start them at once and finally I will start the API Gateway and we will see if Postman will allow us to uh to reach for example the list of products or to perform an order or create a customer and so and so forth so now let's make sure that that our API Gateway starts correctly which is the case now we can go to postman and perform the first request and let's try to fetch for example the list of products so here we have products and if I click on send we see that we have 41 unauthorized so now in order to do this or like or in order to authorize our user we can go to authorization and then we have oo 2 and then in here what we need to do is to configure a new token so here here we can for example specify token name and here we have the gr type so the gr type is not an authorization code but client credentials so for this client credentials we need to specify few information so first we need the access token URL which is the end point for the authorization server this is used to get the access token and then we need the client ID the one that we created which is I guess microservices API and then we need to copy the client Secrets all right so then uh and then like we can leave the rest as it is and we can test or like try to get the access token so now the question where to get this access token URL so let's go back to our um to our UI or like to our kick loock UI and here in the realm settings if you scroll down you can see the open ID uh the open ID end point configuration so in here or among this uh this information you have something it's called token end point so let's copy this one so it's like Local Host and then the kick loock Port slrm SL the realm name and then protocol open ID connect/ token so let's paste this one in Postman so this will be our access token URL so the client ID we already have it we need now to get our client secret from our client so here we have microservices API and then credentials and let's copy this this client secret so now we can paste this one in here and for the the Scopes we can leave it empty or like we can I think we can specify the open ID and offline access so let's try without it and now all we need to do is to click on get accent access so here we have authentication complete let's click on proceed and this is our our token so let's click on use token and now when I send the request I expect the list of products so as you can see here we have now the list of products from our API Gateway so in this the same way if I try to create a new customer so let's click on send or maybe let's change few information first and if I click on send I get a 401 unauthorized so now in the same way let's go back to authorization and let's click O2 and here we will uh like Postman will will uh will conserve all the configurations and also this token which is like which should be valid and now if I click on send I should get 200 with this customer ID all right so that was it for today's video I hope you enjoyed it and I'm happy that you reached the end of this video so before we end this video I would like first to invite you to subscribe to my channel if you are not already subscribed give me a thumbs up and leave a comment what you want to see next and let me give you a heads up about what's coming in this in the context of micro services so in the in the coming videos we will explore more and more about distributed patterns like we will see this how to implement circuit breaker how to imple implement the Saga pattern and more and more of the distributed patterns also we will I will show you how to set up or implement the elk stack which is the elastic search look stach kibana and so and so forth so now thank you so much for watching and don't forget to share this video hit the thumbs up and also subscribe to my channel thank you so much and see you in the next one