16

Situation: A microservices architecture with:

  • Microservices are written in Java with Spring Boot and Hibernate
  • An options-service which provides information about Options via a REST interface
  • Option data which could be modelled as follows e.g. via an enum (representative)
    • Has some attributes like enabled status associated with it. It is unlikely that more attributes belonging to Option will be added in future which have to be directly tied to it.
    • New Options and OptionTypes have to be seldom added. They will never be deleted (just disabled if need be).
    • An Option should have a unique identifier which can be referenced
    • There should be no UNKOWN option if possible
enum OptionType {
   TYPE_A,
   TYPE_B,
   TYPE_C;
}

enum Option {
    TYPE_A_X1(TYPE_A),
    TYPE_A_X2(TYPE_A),

    TYPE_B_Z1(TYPE_B, false),
    TYPE_B_Z2(TYPE_B);

    TYPE_C_U1(TYPE_C);
    TYPE_C_U2(TYPE_C);
    TYPE_C_U3(TYPE_C);

    private final OptionType type;
    private final boolean enabled;

    Option(OptionType type){
        this.type = type;
        this.enabled = true;
    }

    Option(OptionType type, boolean enabled){
        this.type = type;
        this.enabled = enabled;
    }
}

  • Other microservices (currently 3) need to be able to access Option data. They need to know which Options exist and somehow reference an Option e.g. via its name or identifier
    • One of those services (example-service) needs to provide the Option data type as filter settings in its own REST interface to the outside world. The filter object in JSON would look something like this:
{
  "typeA": "TYPE_A_X1",
  "typeB": "TYPE_B_Z2",
  "typeC": [ "TYPE_C_U1", "TYPE_C_U2"]
  // more filter settings
}

Different approaches of storing and sharing this Option data between microservices as I see it:

  • options-service stores Option data in its own database. If I read my data from database into my Hibernate entities Option is only a String everywhere from there on.

    • Pro:
      • Easy to rename, add and remove Options
    • Con:
      • No type safety when working with Option in code e.g. when deserialising a response containing Option
      • example-service cannot easily offer Option data in its OpenAPI doc (just Strings)
      • Microservices need to query and cache Option data from options-service
  • Option data only lives in source code in an enum as e.g. modelled above and is shared between different services via a lib.

    • Pro:
      • Type safety everywhere where Options are needed. Really useful when deserializing reponses containing Options data but also for generating OpenAPI doc
      • Microservices can still reference an Option in its database via its name since it is unique
    • Con:
      • Editing the name of an Option is difficult
      • Removing an Option not possible
      • If a new Option/OptionType is added the order in which the services relying on that lib update their lib version matters. Since we cannot deserialize responses into an UNKNOWN Option type.
  • There is also the possibility of a mixed database and enum solution which comes with the big drawback that one has to maintain both sources of truth.

What is the best way to store and share the Option data between microservices? What is best practice?

2
  • i think grpc protobuf already gives a answer: message contains only values.
    – Lei Yang
    Commented Jul 5, 2021 at 7:41
  • Can you not create a jar dependency and add it to all the projects? Something like a mavenised jar? Commented Jul 5, 2021 at 11:55

3 Answers 3

11
+25

While enums are very helpful in most programming languages, they can become a nightmare in inter-service communication. If you use an enum in your microservice endpoints, it becomes part of the API specification. Changing them on one side will result in problems of serialization/deserialization on the other side. So you should only use enums in your API if

  • you are definitely sure they will never change (e.g. weekdays) or
  • you are the owner of the code of all participating services and are able to orchestrate a big bang redeployment.

In these cases, you may create a shared lib between your services.

If this does not apply, make your life easier and consider most enum-like data (e.g. currency codes, country codes) as simple string values that are subject to change. If you want to have a central management for these values, why don't create a microservice for it that acts as a master? That's what microservice architectures are made for. Offer some endpoints that other services can query from time to time. You don't even need a persistence layer for that.

1

Another option : Use the first option, but with a specialised class.

  • This allow for type safety,
  • but does not require your enums to be known at compile time.
  • Still, if you need to check the validity of your Option instance, you need a service that has cached the list of allowed Options.

Example code:

import com.fasterxml.jackson.annotation.JsonValue;

public class Option {
    @JsonValue
    private String value;
        
    Option(String value) {
        this.value = value;
    }
}
2
  • 1
    StackOverflow answers do not necessarily appear in the order they are written. For example, I see your answer first, so the 3rd option 1st option references make no sense. Commented Jul 5, 2021 at 11:20
  • @SoftwareEngineer changed "3rd" into "Another"
    – unautre
    Commented Jul 5, 2021 at 11:34
0

First Option :

Define or Create new Module / MicroServices / Project that only Contains your CommonMessage , String Message, Enum, Exception or everything that Common and reusable for your multiple microservices that using spring-boot.

But those Enum is not parameterizing so you can not Create Update Or Delete.

And you create your Option ENUM class for multiple purpose and you can inject those class from POM.xml as a dependency.

Second Option : Store it in Database as an Entity Object , so you can manage those data. if you want to use those data on other microservices, dont forget to use this artifact as dependency in POM.xml so other microservices can call your service or repository.

Not the answer you're looking for? Browse other questions tagged or ask your own question.