What it is
MapStruct is a Java annotation processor for generating type-safe and performant mappers that automatically convert between Java beans (DTOs and entities).
MapStruct allows developers to define mapper interfaces annotated with `@Mapper`. At compile-time, MapStruct generates the implementation class for converting between source and target objects.
Installation
Add org.mapstruct:mapstruct dependency and mapstruct-processor annotationProcessor in pom.xmlGetting started
The smallest useful thing you can do with it, and what each part means.
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
UserDTO userToUserDTO(User user);
}User user = new User(1, "Alice", "alice@example.com");
UserDTO dto = UserMapper.INSTANCE.userToUserDTO(user);
System.out.println(dto.getName());Advanced usage
Where the library earns its place over a simpler alternative.
List<UserDTO> dtos = UserMapper.INSTANCE.usersToUserDTOs(usersList);@Mapping(source = "email", target = "contactEmail")
UserDTO userToUserDTO(User user);@Mapping(source = "address.street", target = "streetName")
UserDTO userToUserDTO(User user);@Mapping(target = "fullName", expression = "java(user.getFirstName() + ' ' + user.getLastName())")
UserDTO userToUserDTO(User user);Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- UnmappedTargetPropertyException
- Occurs when a target field does not have a corresponding mapping. Add `@Mapping` or `@Mappings` annotations or ignore unmapped fields.
- AnnotationProcessingException
- Occurs if MapStruct annotation processor is not configured correctly. Ensure proper dependencies and annotationProcessor setup.
- IncompatibleTypesException
- Occurs when source and target types cannot be mapped. Use type conversions or custom mapping methods.
Best practices
- Keep mapping interfaces simple and modular.
- Use `@Mapper` with componentModel = 'spring' for Spring Boot integration.
- Prefer compile-time mappings over reflection-based mapping for performance.
- Leverage `@Mapping` for fields with different names or types.
- Validate mapping results in unit tests to ensure correctness.
Background
Why it exists, and what it was reacting to.
MapStruct was created to eliminate the boilerplate code of writing manual mapping logic between Java objects. By generating mapper implementations at compile-time, it ensures type safety, high performance, and easy maintenance.
