I like to create immutable classes. When using Lombok we can easily create immutable classes.

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;

@Value
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE) //Hides the constructor to force useage of the Builder.
public final class Person {
    private final String firstName;
    private final String lastName;
}

This class Person with the @Value annotation will create an immutable class with an all args constructor. The @Builder will add a Builder pattern to the Person class, so I can use it like this:

Person person = Person.builder()
    .firstName("Elvis")
    .lastName("Presley")
    .build();

To use this class in Jackson we need to make some slight changes in the way we build our ObjectMapper and compile our Java classes. By default Jackson will use a no args constructor and setters to create the desired instance. We can use a @JsonCreator and @JsonProperty to indicate what constructor Jackson needs to use and how to map properties.

Since we use Lombok to generate a constructor we cannot easily add these annotations to the constructor. We can add some Jackson specific modules to look at the parameter names of the constructor. Together with adding a parameter property as compiler argument to javac command in our gradle, the correct constructor will be used by Jackson. The compiler arguments will instruct the compiler to keep the argument names. In this case we need to keep the argument names in the constructor so Jackson knows which parameters it takes. By default the java compiler drops the parameter names and replaces those by arg1, arg2, etc.

Listing 1. build.gradle
dependencies {
    implementation 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
    implementation "com.fasterxml.jackson.module:jackson-module-jackson-module-parameter-names"
}

We add some instructions for Lombok in the lombok.config in the root of our project. It will be automatically be picked up.

Listing 2. lombok.config
lombok.addLombokGeneratedAnnotation = true
lombok.anyConstructor.addConstructorProperties = true

Now we can configure our ObjectMapper bean to automatically register the modules found on the classpath.

Listing 3. Config.java
@Bean
ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.findAndRegisterModules(); //Registers all modules on classpath
    return mapper;
}

Now Jackson will be using the correct constructor for our immutable class.

shadow-left