Lombok extension which generates Presence Checker methods
Tested with the help of GitHub Actions
JDK: 7, 8, 11, 14
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.kokorin.lombok</groupId>
<artifactId>lombok-presence-checker</artifactId>
<version>0.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>com.github.kokorin.lombok</groupId>
<artifactId>lombok-presence-checker</artifactId>
<version>0.0.2</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
You can annotate any field or type with @PresenceChecker
, to let lombok together with lombok-presence-checker
generate presence checker methods (hasFieldName()
) automatically.
This project allows easy implementation of partial update via REST API.
MapStruct is aware of source presence checking and uses presence checker methods by default (if present of course) to verify if a field in a target object should be updated with a value in a source object. Without presence checkers MapStruct by default updates only fields with non-null values.
After incoming request body get parsed in a typed object in a REST controller one can't distinguish absent property from a property with null value.
Several strategies can be applied to partial update:
- Treat any DTO property with null value as absent property and do not set corresponding entity property to null
- Treat any DTO property with null value as property explicitly set to null, thus denying partial update
- Parse request body as JsonObject (or Map), which seems not very suitable for strongly typed languages
- Use JSON mapper for entity partial update with a price of JSON mapper leaking to REST Controller
- For every field in DTO add a flag to mark it as present or not
Lombok-presence-checker aims at the last strategy. Check REST controller example and corresponding tests
@Getter
@Setter
public class User {
private String name;
}
@Getter
@Setter
@PresenceChecker
public class UserUpdateDto {
private String name;
}
//MapStruct Mapper interface declaration
@Mapper
public interface UserMapper {
void updateUser(UserUpdateDto dto, @MappingTarget User user);
}
public class User {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class UserUpdateDto {
private boolean hasName;
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
this.hasName = true;
}
public boolean hasName() {
return this.hasName;
}
}
//MapStruct Mapper implementation
public class UserMapperImpl implements UserMapper {
@Override
public void updateUser(UserUpdateDto dto, User user) {
if ( dto == null ) {
return;
}
if ( dto.hasName() ) {
user.setName( dto.getName() );
}
}
}
Some dependencies have to be installed to local Maven repository before compilation
First initialize everything:
mvn initialize
Then build:
mvn clean install