Home > Mobile >  What is the best approach to seperate entities in microservices architecture (spring boot)?
What is the best approach to seperate entities in microservices architecture (spring boot)?

Time:08-21

I'm designing a new project with microservices, the first principal which was already impleneted is that each microservice has its own DB schema. I have simple question about architecture. I'll explain with simple example.

I've created a Location service. Here is some code from the controller:

@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RestController
@RequestMapping("/locations")
@Slf4j
public class LocationController {

    @Autowired
    LocationService  locationService;
    
    @GetMapping("/Cntry")   
    public List<Country> getCountries() {
        return locationService.getdCountries();
    }
        
    @GetMapping("/States/{id}") 
    public List<State> getStatesForCountry(@PathVariable("id") String countryId) {      
        List<State> states = locationService.getStatesForCountry(Integer.valueOf(countryId));
        return states;
    }
    
    @GetMapping("/Cntry/{code}")    
    public Country getCountry(@PathVariable("code") String code) {          
        return locationService.getCountry(code);
    }   

As you can see above, the Location service which has local DB hold all the countries and states. The location service hold more entities related to the project such as Location, so it is multi purpose microservice.

The problem I'm facing is that each microservice can have entities with country_id for example, but when running it almost gurantee that it will need the country name which mean a service call (web client). Here is sample of such service call:

@JsonIgnore
    public String getCountryString() {
        String url = MySpringBootServiceApplication.LOCATION_BASE_URL   "locations/CntryStr/"   countryId;
        WebClient client = WebClient.create(url);
        ResponseEntity<String> response = client.get()        
              .retrieve()
              .toEntity(String.class)
              .block();
        String countryStr = response.getBody();
        return countryStr;                  
    }

I have two problems here that I need to solve:

  1. Is there a solution (Architecture) to avoid calling to get the country string every time and from each micro service ?
  2. A DTO in another service has country_id, but the user is looking for the name so, is there better way instead of make a webclient call inside DTO (doens't make sense).

Thanks for your help.

CodePudding user response:

You can solve both problems by denormalizing: have each service maintain its own local mapping of country codes to names.

You can still have the location service govern updating country codes to names; it then publishes (in the rare case when a code-to-name mapping changes) events when they change for consumption by the other services to signal that they should update their respective mappings. Because the responsibility for updating this mapping is in one service while (many) other services have a responsibility for presenting the mapping, this is an example of the Command/Query Responsibility Segregation pattern (CQRS).

In general taking a normalized relational schema and turning it into a microservice architecture leads to the issue you're facing. Denormalization can avoid the problem, but then focusing on the operations (the verbs) rather than the data (the nouns) lead to a much more effective and easier to work with architecture.

  • Related