20- Microservices communicating via RestTemplate- Important (Theory and coding Part)

 
Microservices communicating via RestTemplate 

Before we start writing code for user-service-A . We need to understand that in user service we have parameters like userId ,firstName, lastName ,email and departmentId.

-->  userId ,firstName, lastName ,email are parameters of user microservice 

--> departmentId is  id that corresponds to a particular department from department-microservice-A.

And with the help of departmentId  and  RestTemplate  a request will be send from user service to department service and a response will be recieved from department-service.

Basically

 Microservice1(user-service-A) acts as a client that sends a request and waits for a response from Microservice2(department-service-A).

This is also called Synchronous Communication, the client sends a request and waits for a response from the service. 

We can use RestTemplate or WebClient or Spring Cloud Open Feign library to make a Synchronous Communication multiple microservices.


Image 1 -   Communication via RestTemplate


NOTE: 

 Make sure both microservices are not running on same port in my case 


department-microservice-A is running on port 8080 (default port for Tomcat Server) no need to configure in application .properties

user-microservice-A is running on port 8081  need to configure in application .properties of user microservice





------------------------------------------------------------------------------------------------------

Lets understand how we are going to create a microservice that is communicating with other microservice.

1- First create a bean for RestTemplate in main application Method.


src/main/java  --> com.zeek.userserviceA --> UserServiceAApplication.java

package com.zeek.userserviceA;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class UserServiceAApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceAApplication.class, args);
    }
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}



2- Be sure to give the id of another microservice which in this case is departmentId in Entity of our microservice(user).


Entity Class


src/main/java  --> com.zeek.userserviceA.entity --> User.java

package com.zeek.userserviceA.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long userId;
    private String firstName;
    private String lastName;
    private String email;

    private Long departmentId;

   
   
   
   
    //Constructors using SuperClass
    public User() {
        super();
    }
  //Constructors using Fields
    public User(Long userId, String firstName, String lastName, String email, Long departmentId) {
        super();
        this.userId = userId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.departmentId = departmentId;
    }
    //Getters and Setters
    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Long getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentId(Long departmentId) {
        this.departmentId = departmentId;
    }
   
}



3- Write your repository interface(userRepository) for userId only.


Repository Interface


src/main/java  -->com.zeek.userserviceA.repository -> UserRepository.java

package com.zeek.userserviceA.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.zeek.userserviceA.entity.User;

@Repository
public interface UserRepository  extends JpaRepository<User,Long> {
    User findByUserId(Long userId);
}


4- Generate a package Name vo(value object) in which there are classes which we need to generate our desired Response format.

--> In this project we need response for user and department together when we use getUserWithDepartment in service layer.The format generated must be like this 

{
    "user": {
        "userId": 1,
        "firstName": "Zee",
        "lastName": "Khan",
        "email": "zee@gmail.com",
        "departmentId": 1
    },
    "department": {
        "departmentId": 1,
        "departmentName": "English",
        "departmentAddress": "First Cross,1st Street",
        "departmentCode": "EN-006"
    }
}

 So two classes are needed

VO package -  Department.java and ResponseTemplate.java

--> Department Class

- In user service this class will be same as in department service because we will set its value for input id corresponding to the id generated in department service using RestTemplate.

package com.zeek.userserviceA.VO;


public class Department {

    private Long departmentId;
    private String departmentName;
    private String departmentAddress;
    private String departmentCode;
   
   
   //Constructors using superclass
    public Department() {
        super();
    }
     
      //Constructors using fields
    public Department(Long departmentId, String departmentName, String departmentAddress, String departmentCode) {
        super();
        this.departmentId = departmentId;
        this.departmentName = departmentName;
        this.departmentAddress = departmentAddress;
        this.departmentCode = departmentCode;
    }
     
      //Getters and Setters
        public Long getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentId(Long departmentId) {
        this.departmentId = departmentId;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    public String getDepartmentAddress() {
        return departmentAddress;
    }

    public void setDepartmentAddress(String departmentAddress) {
        this.departmentAddress = departmentAddress;
    }

    public String getDepartmentCode() {
        return departmentCode;
    }

    public void setDepartmentCode(String departmentCode) {
        this.departmentCode = departmentCode;
    }
}


-->ResponseTemplateVO Class

- Response format for getUserWithDepartment. getUserWithDepartment gets user and department both for that existing user for that id.

package com.zeek.userserviceA.VO;


import com.zeek.userserviceA.entity.User;


public class ResponseTemplateVO {

 
    private User user;
    private Department department;
   
   
 //Constructors using superclass
      public ResponseTemplateVO() {
            super();
        }
     
    //Constructors using fields
    public ResponseTemplateVO(User user, Department department) {
        super();
        this.user = user;
        this.department = department;
    }
    //Getters and Setters
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public Department getDepartment() {
        return department;
    }
    public void setDepartment(Department department) {
        this.department = department;
    }
   

}


Service Class


src/main/java  -->com.zeek.userserviceA.service -> UserService.java

package com.zeek.userserviceA.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.zeek.userserviceA.VO.Department;
import com.zeek.userserviceA.VO.ResponseTemplateVO;
import com.zeek.userserviceA.entity.User;
import com.zeek.userserviceA.repository.UserRepository;

@Service
public class UserService {
     @Autowired
        private UserRepository userRepository;

        @Autowired
        private RestTemplate restTemplate;

        public User saveUser(User user) {

            return userRepository.save(user);
        }

        public ResponseTemplateVO getUserWithDepartment(Long userId) {
            ResponseTemplateVO vo = new ResponseTemplateVO();
            User user = userRepository.findByUserId(userId);

            Department department =
                    restTemplate.getForObject("http://localhost:8080/departments/" + user.getDepartmentId()
                            ,Department.class);

            vo.setUser(user);
            vo.setDepartment(department);

            return  vo;
        }
    }




5-Write the controller class and Run the program


Controller Class

src/main/java --> com.zeek.userserviceA.controller  -->UserController.java

package com.zeek.userserviceA.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zeek.userserviceA.VO.ResponseTemplateVO;
import com.zeek.userserviceA.entity.User;
import com.zeek.userserviceA.service.UserService;
@RestController
@RequestMapping("/users")
    public class UserController {
        @Autowired
        private UserService userService;
        @PostMapping("/")
        public User saveUser(@RequestBody User user) {
            return userService.saveUser(user);
        }

        @GetMapping("/{id}")
        public ResponseTemplateVO getUserWithDepartment(@PathVariable("id") Long userId) {
            return userService.getUserWithDepartment(userId);
        }

}



application.properties


src/main/resources --> application.properties

server.port=8081

spring.datasource.url=jdbc:mysql://localhost:3306/user?useSSL=false
spring.datasource.username=root
spring.datasource.password=root

# Hibernate properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

#create,create-drop
spring.jpa.hibernate.ddl-auto=update


CONSOLE



  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.4)

2023-05-31 21:42:15.143  INFO 25784 --- [           main] c.z.u.UserServiceAApplication            : Starting UserServiceAApplication using Java 18.0.1 on Zeeshan with PID 25784 (C:\Users\zeesh\eclipse-workspace\A_workspace\user-service-A\target\classes started by ZeeK in C:\Users\zeesh\eclipse-workspace\A_workspace\user-service-A)
2023-05-31 21:42:15.145  INFO 25784 --- [           main] c.z.u.UserServiceAApplication            : No active profile set, falling back to 1 default profile: "default"
2023-05-31 21:42:15.702  INFO 25784 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-05-31 21:42:15.755  INFO 25784 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 46 ms. Found 1 JPA repository interfaces.
2023-05-31 21:42:16.304  INFO 25784 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2023-05-31 21:42:16.314  INFO 25784 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-05-31 21:42:16.315  INFO 25784 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.58]
2023-05-31 21:42:16.391  INFO 25784 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-05-31 21:42:16.391  INFO 25784 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1199 ms
2023-05-31 21:42:16.579  INFO 25784 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-05-31 21:42:16.623  INFO 25784 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.5.Final
2023-05-31 21:42:16.763  INFO 25784 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-05-31 21:42:16.846  INFO 25784 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-05-31 21:42:16.975  INFO 25784 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-05-31 21:42:16.988  INFO 25784 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
2023-05-31 21:42:17.528  INFO 25784 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-05-31 21:42:17.534  INFO 25784 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-05-31 21:42:17.890  WARN 25784 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-05-31 21:42:18.170  INFO 25784 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2023-05-31 21:42:18.178  INFO 25784 --- [           main] c.z.u.UserServiceAApplication            : Started UserServiceAApplication in 3.429 seconds (JVM running for 3.86)
2023-05-31 21:43:52.334  INFO 25784 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-05-31 21:43:52.335  INFO 25784 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-05-31 21:43:52.336  INFO 25784 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms






Comments

Popular posts from this blog

INDEX OF JAVA 8 and MICROSERVICES BLOG