Open In App

How to Share DTO Across Spring Boot Microservices?

Last Updated : 28 May, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A Data Transfer Object(DTO) is an object that encapsulates data and transports it from one subsystem of an application to another. The Services layer in an N-Tier application often uses DTOs to transport data between itself and the UI Microservices have gained popularity over time. They are lighter, more modular, and easier to install and scale. However, Microservice designs present certain issues. Microservices have particular responsibilities. Multiple Microservices can be required to work together on completing an application workflow or activity.

Steps to Share DTO Across Java Microservices

Below are the steps to Share DTO Across Microservices.

Step 1: Connect DTO Across Microservices

The layer connects the two classes and uses a mapper component to transfer data from one side to the other and vice versa.

Java
@RestController
@RequestMapping("/users")
class UserController {

    private UserService myUserService;
    private RoleService myRoleService;
    private Mapper myMapper;

    // Constructor

    @GetMapping
    @ResponseBody
    public List<UserDTO> getUsers() {
        return myUserService.getAll()
          .stream()
          .map(myMapper::toDto)
          .collect(Collectors.toList());
    }


    @PostMapping
    @ResponseBody
    public UserIdDTO createUser(@RequestBody UserCreationDTO userCreationDTO) {
        User user = myMapper.toUser(userCreationDTO);

        userCreationDTO.getRoles()
          .stream()
          .map(role -> myRoleService.getOrCreate(role))
          .forEach(user::addRole);

        myUserService.save(user);

        return new UserIdDTO(user.getId());
    }
}


Step 2: Share DTO Between Microservices

Consider how a consumer orders a product. This procedure is based on the Customer-Order model. Check the process from the perspective of the service architecture.

{
// Order details
"order": {
// Customer ID associated with the order
"customerId": 2,
// Item ID of the product being ordered
"itemId": "F2521"
}
}


Step 3: Use Order Service for communication

The User Service transforms its internal user objects into UserDTO objects and transmits them as payloads when it has to interact with the Order Service.

Java
public class UserService {
    public UserDTO getUserById(String userId) {
     
        User user = userRepository.findById(userId);
        
        // Convert User to UserDTO
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(user.getUserId());
        userDTO.setUsername(user.getUsername());
        userDTO.setEmail(user.getEmail());
        
        return userDTO;
    }
}


Step 4: Receive requests for Order Service

The Order Service expects a UserDTO object and, if required, transforms it back to its internal representation when it gets a request containing user data from the User Service or any other client.

Java
public class OrderService {
    public void placeOrder(UserDTO userDTO, OrderDTO orderDTO) {
        // Convert UserDTO to internal User object if needed
        User user = new User();
        user.setUserId(userDTO.getUserId());
        user.setUsername(userDTO.getUsername());
        user.setEmail(userDTO.getEmail());
        
        // Process order
        // ...
    }
}


Step 5: Add certain information

A microservice needs certain information from other services to complete any request. Assume there is a third microservice that handles order payment requests. All variables have getters and setters specified to offer access to and modify their values. Unlike the Order service, this service needs different consumer information:

Java
public class CustomerDTO {
    private String firstName;
    private String lastName;
    private String cardNumber;

    public CustomerDTO(String firstName, String lastName, String cardNumber) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.cardNumber = cardNumber;
    }

    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 getCardNumber() {
        return cardNumber;
    }

    public void setCardNumber(String cardNumber) {
        this.cardNumber = cardNumber;
    }
}


Step 6: Use the RestTemplate object

The following section of code shows how to invoke a RESTful service during the order-generating process. The variables have been renamed to improve readability and offer a better ownership explanation.

Java
// Original code snippet
String serviceUrl = "http://localhost:8002/order-service";
OrderResponse orderResponse = restTemplate.postForObject(serviceUrl + "/create", 
  request, OrderResponse.class);

// Modified code snippet with explanation
String myServiceUrl = "http://localhost:8002/order-service";
OrderResponse myOrderResponse = restTemplate.postForObject(myServiceUrl + "/create", 
  myRequest, OrderResponse.class);


  • myServiceUrl is the variable that contains the URL for the service endpoint where the request is being submitted. Prefixing it with "my" helps to show that it is particular to this class/method.
  • myOrderResponse variable stores the response that the service provided following a POST request. Prefixing it with "my" indicates that it's tied to this class or function.

Next Article

Similar Reads