'Dynamic computed properties in Spring

I have a pojo class whose properties needs to be dynamically calculated. Example

public class User{
   
   @Getter
   @Setter
   public String firstName;

   @Getter
   @Setter
   public String lastName;
    
   @Getter
   @Setter
   public String emailId;
}

Here the emailId needs to be computed as

emailId = firstName + lastName +"@domain.com"
//or
emailId = firstName + empId +"@domain.com";
//or
emailId = firstName + "." +lastName +"@domain.com"
// it could be any combination

I have exposed an API which accepts json of name value pair which looks like this:

{
    "firstName" : "Mark",
    "lastName" : "Hazel",
    "empId" : "201",
    "dept" : "IT",
}

notice some of the fields in the json are not present in the pojo class User, but can be indirectly involved in computing the emailId field.

I wanted to externalize this computation into some config file(Each per customer) so that every customer can have their definition of emailId computation expression.

I have checked spring expression language, but the examples I saw was based on static computation in the @Value annotation. Moreover, the fields involved in the computation need to be the fields in the pojo. I have also tried ObjectMapper, but couldn't find a way to do such kind of configuration based computation.

I would like to hear from the experts here what would be the cleanest way to achieve the above. I will be using this same approach for other pojo classes, so want to make it a generic solution.



Solution 1:[1]

If you want to expose variables to external config, you can use Handlebars, even tho its not ment to be used that way, its one of the options. Lets say you have config file with content:

{{firstName}}.{{lastName}}@domain.com

You can load this String or file into Handlebars and pass your DTO into handlebars as Map.

Handlebars handlerBars =  new Handlebars();

// Convert POJO to Map
Map<String, Object> parameterMap = mapper.convertValue(user, new TypeReference<Map<String, Object>>() {});

// Template, can be loaded from file or DB
String template = "{{firstName}}.{{lastName}}@domain.com";

// Compile Template
Template emailIdTemplate = handlerBars.compileInline(template);

// Apply Variables
String emailId = emailIdTemplate(parameterMap);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kirill Vizniuk