Releases: mapstruct/mapstruct
1.6.3
Bugs
- Redundant if condition in Java record mapping with
RETURN_DEFAULTstrategy (#3747) - Stackoverflow with Immutables custom builder (#3370)
- Unused import of
java.time.LocalDatewhen mapping sourceLocalDateTimeto targetLocalDate(#3732)
Documentation
- Add section to README.md comparing mapstruct with Java Records (#3751)
1.6.2
1.6.1
Enhancements
- Use Java
LinkedHashSetandLinkedHashMapnew factory method with known capacity when on Java 19 or later (#3113)
Bugs
- Inverse Inheritance Strategy not working for ignored mappings only with target (#3652)
- Inconsistent ambiguous mapping method error when using
SubclassMapping: generic vs raw types (#3668) - Fix regression when using
InheritInverseConfigurationwith nested target properties and reversingtarget = "."(#3670) - Deep mapping with multiple mappings broken in 1.6.0 (#3667)
- Two different constants are ignored in 1.6.0 (#3673)
- Inconsistent ambiguous mapping method error: generic vs raw types in 1.6.0 (#3668)
- Fix cross module records with interfaces not recognizing accessors (#3661)
@AfterMappingmethods are called twice when using target with builder (#3678)- Compile error when using
@AfterMappingmethod with Builder and TargetObject (#3703)
Behaviour change
Inverse Inheritance Strategy not working for ignored mappings only with target
Prior to this fix @Mapping(target = "myProperty", ignore = true) was being ignored when using @InheritInverseConfiguration.
e.g.
@Mapper
public interface ModelMapper {
@Mapping(target = "creationDate", ignore = true)
Entity toEntity(Model model);
@InheritInverseConfiguration
Model toModel(Entity entity);
}In the example above prior 1.6.1 the Model toModel(Entity entity) was going to map the id property. In order to keep that behavior you'll need to explicitly do the mapping for it.
@Mapper
public interface ModelMappe {
@Mapping(target = "creationDate", ignore = true) // NOTE: Handled by JPA.
Entity toEntity(Model model);
@InheritInverseConfiguration
@Mapping(target = "creationDate", source = "creationDate") // Allow reading from Entity
Model toModel(Entity entity);
}1.6.0
Previous Release Notes
1.6.0.RC1
Enhancements
- Breaking change: (#3574) -
This reverts #2560, because we've decided that@BeanMapping(ignoreByDefault = true)should only be applied to target properties and not to source properties.
Source properties are ignored anyway, theBeanMapping#unmappedSourcePolicyshould be used to control what should happen with unmapped source policy
Bugs
- Breaking change: Presence check method used only once when multiple source parameters are provided (#3601)
- Fix
@SubclassMappingnot working with@BeanMapping#ignoreUnmappedSourceProperties(#3609) - Fix duplicate method generation with recursive auto mapping (#3591)
Documentation
- Fix documentation of
unmappedSourcePolicydefault value (#3635) - Fix documentation link of before and after mapping when using builders (#3639)
- Fix typo in experimental note (#3634)
- Add example classes for the passing target type documentation (#3504)
Build
- Enforce whitespaces around the for colon with CheckStyle (#3642)
Breaking changes
Presence checks for source parameters
In 1.6, support for presence checks on source parameters has been added.
This means that even if you want to map a source parameter directly to some target property the new @SourceParameterCondition or @Condition(appliesTo = ConditionStrategy.SOURCE_PARAMETERS) should be used.
e.g.
If we had the following in 1.5:
@Mapper
public interface OrderMapper {
@Mapping(source = "dto", target = "customer", conditionQualifiedByName = "mapCustomerFromOrder")
Order map(OrderDTO dto);
@Condition
@Named("mapCustomerFromOrder")
default boolean mapCustomerFromOrder(OrderDTO dto) {
return dto != null && dto.getCustomerName() != null;
}
}Then MapStruct would generate
public class OrderMapperImpl implements OrderMapper {
@Override
public Order map(OrderDTO dto) {
if ( dto == null ) {
return null;
}
Order order = new Order();
if ( mapCustomerFromOrder( dto ) ) {
order.setCustomer( orderDtoToCustomer( orderDTO ) );
}
return order;
}
}In order for the same to be generated in 1.6, the mapper needs to look like this:
@Mapper
public interface OrderMapper {
@Mapping(source = "dto", target = "customer", conditionQualifiedByName = "mapCustomerFromOrder")
Order map(OrderDTO dto);
@SourceParameterCondition
@Named("mapCustomerFromOrder")
default boolean mapCustomerFromOrder(OrderDTO dto) {
return dto != null && dto.getCustomerName() != null;
}
}1.6.0.Beta2
Features
- Support conditional mapping for source parameters (#2610, #3459, #3270)
- Add
@SourcePropertyNameto handle a property name of the source object (#3323) - Currently only applicable for@Conditionmethods
Enhancements
- Improve error message for mapping to
target = "."using expression (#3485) - Improve error messages for auto generated mappings (#2788)
- Remove unnecessary casts to long (#3400)
Bugs
@Conditioncannot be used only with@Contextparameters (#3561)@Conditiontreated as ambiguous mapping for methods returning Boolean/boolean (#3565)- Subclass mapping warns about unmapped property that is mapped in referenced mapper (#3360)
- Interface inherited build method is not found (#3463)
- Bean with getter returning Stream is treating the Stream as an alternative setter (#3462)
- Using
Mapping#expressionandMapping#conditionalQualifiedBy(Name)should lead to compile error (#3413) - Defined mappings for subclass mappings with runtime exception subclass exhaustive strategy not working if result type is abstract class (#3331)
Documentation
- Clarify that
Mapping#ignoreByDefaultis inherited in nested mappings in documentation (#3577)
Build
1.6.0.Beta1
Features
- Access to target property name (#2688) -
@TargetPropertyNamecan be used to access the target property name to conditional and mapping methods - Support passing annotations to generated code (#1574, #2773, #2895, #2983) - Using
@AnnotateWith. If a method is annotated with@Deprecatedit is automatically copied into the generated code. - Support for globally defining
nullValueIterableMappingStrategyandnullValueMapMappingStrategy(#2953) - The different strategies can be configured usingmapstruct.nullValueIterableMappingStrategyandmapstruct.nullValueMapMappingStrategyrespectively - Support qualifiers for
SubclassMappingannotated methods (#3119) - Support defining custom processor options for custom SPI (#3071) - There is also
AdditionalSupportedOptionsProviderthat can be used to defined the supported options for a custom SPI. The additional options cannot start withmapstruct. - Support for defining Javadoc on the generated mapper (#2987) - Using
@Javadoc
Enhancements
- Support for converting between
EnumandInteger(#2963) - Support for converting between
LocaleandString(#3172) - Support for implicit conversion between
java.time.LocalDateandjava.time.LocalDateTime(#3199) - Support custom name in Spring annotations (#1427) - Can be done using
@AnnotateWith(value = Service.class, elements = @AnnotateWith.Element(strings = "cakeMapperV2")) - Support meta annotations for
@ValueMapping(#3037) - Ambiguous mapping method but there is a more specific mapping (#1216)
- Do not treat getter as an alternative write accessor when using
CollectionMappingStrategy#TARGET_IMMUTABLE(#2952) - Improve line location report for invalid qualifier for
SubclassMapping(#3202) - Support
@InheritConfigurationfor@SubclassMappingin methods with identical signature (#3125) - Do not require
subclassExhaustiveStrategywhen source is a sealed class and all subtypes are specified (#3054) - Add validation of
Stringtype for@TargetPropertyName(#2863) - Support for all lifecycle methods on type being build with builders (#1454)
@BeforeMappingwith@TargetTypethe type being build@AfterMappingwith@TargetTypethe type being build@AfterMappingwith@MappingTargetthe type being build
- Redundant null checks for nested properties (#3245)
@Defaulton Java Record's constructor isn't respected (#3231)- Add
InjectionStrategy.SETTER(#3229) - Add
BeanMapping#unmappedSourcePolicy(#3309) - Improve support for Map attributes for immutables (#3089)
- Support mapping
IterabletoCollection(#3376)
Bugs
- Breaking change: Mapping from Map to Bean (#3144)
- Condition with
@TargetTypeonCollectionfails to compile (#2901) - Annotations are automatically passed in forged methods (#3015)
- Mapping Composition does not work for
@SubclassMapping(#3174) - Mapping control disabling conversions does not disable them in 2 step mappings (#3186)
@BeanMapping(ignoreByDefault = true)does not work for constructor properties (#3158)@ValueMappingstrips spaces from source (#3153)defaultExpressiondoes not work when mapping a collection of custom types (#3159)- Arrays cannot be mapped to collection / iterable using an adder method (#3165)
- Unmapped source properties error when source is mapped to a nested field of the target object (#2781)
NullPointerExceptionwhen ignoring target '.' (#3238) - There is now a compilation error instead of an error in the processorNullValuePropertyMappingStrategy.IGNOREdoes not ignore target collection even when source one is null (only whencollectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE) (#3104)@SubclassMappingnot working with@Mappingnested properties and target all (#3126)- Compile error when using
defaultandstaticmethods in@MapperConfig(#3296) - Generic class with adder method and
CollectionMappingStrategy.ADDER_PREFERREDfails (#3310) - MapStruct can not map only primitives (#3317)
- 2-step mapping with generics does not work correctly (#2663)
- MapStruct no longer handles generic mapping methods (in conjunction with immutables) after upgrading from 1.4.x to version 1.5.x (#3163)
- Ignored mappings when using
@InheritConfiguration(#3361)
Documentation
- Use GitHub new Issue Form Templates (#3008)
- Mapping composition is no longer experimental (#3239)
- Improve Lombok integration documentation (#3374)
Build / Refactoring
- Try to stabilise some date conversion tests (#2806)
- Avoid unnecessary unboxing of Boolean (#3003)
- Update FreeMarker to 2.3.32
- Refactor method selection and use a context to be able to more easily access information (#3280)
- Update tarLongFileMode to use POSIX (#3340)
- Simplified some expressions, redundant expressions removed (#3292)
- Refactor to use presence check for mapping methods (#3347) - Still only internal and custom presence checks methods are not supported for source parameters (see #2610 for that)
- Update github actions (#3397)
- Add Java 21 to test matrix
- Add Java EA to test matrix
- Removing java 13 and 18 from test matrict
Breaking Changes
Map to Bean
In 1.5 we added support for mapping a map to a bean by implicitly mapping all the properties from the target bean by accessing them from the map. However, this lead to some problems in multi mapping methods. Therefore, in this release we tightened up a bit and in multi source mapping methods the Map will not be considered when doing implicit mappings.
e.g.
@Mapper
public interface CarMapper {
// This method is going to implicitly map all the target properties from the map
Target map(Map<String, Object> map);
// This method is not going to use the map for implicit mappings.
// Only the name will be mapped from the map (since it has been defined like that
@Mapping(target = "name", source = "map.name")
Target map(Source source, Map<String, Object> map)
}
@BeanMapping inheritance
All, except resultType and ignoredUnmappedSourceProperties attributes of @BeanMapping have been made to consistently be passed down to the generated nested methods. This means that if you were relying on some buggy behavior it might no longer work.
e.g. BeanMapping#ignoreByDefault was not being passed down properly, i.e. implicit mapping was being done for nested properties. This has been fixed. If you want to implicitly map nested mappings then you'll have to define your own mapper appropriatelly.
@Mapper
interface MyMapper {
@BeanMapping( ignoreByDefault = true )
@Mapping( source = "sub", target = "target" )
Target map( Source source );
}needs to be replaced with
@Mapper
interface MyMapper {
@BeanMapping( ignoreByDefault = true )
@Mapping( source = "sub", target = "target" )
Target map( Source source );
// this is the mapping `source = "sub"` and `target = "target"`
// redefined to get rid of the `ignoreByDefault=true`, because this property is inherited
SubTarget subSourceToSubTarget( SubSource subSource );
}Sponsoring
After the request from the community we have enabled sponsoring for the project. See #2340 for how you can sponsor us if you want to.
Contributors
1.5.5.Final
1.5.4.Final
Enhancements
- Support for Jakarta
@ApplicationScopedis missing (#2950)
Bugs
- Exceptions declared to be thrown by a mapping method, are not declared in generated mapping methods for nested types (#3142)
- DeepClone mapping control not generating third tier functions to clone (#3135)
- missing
throwsclauses when mapping enum with checked exceptions (#3110) - Version 1.5.3 doesn't consider
Mappingannotations for nested objects (worked with 1.5.2) (#3057) - Cannot use only
BeanMapping#mappingControl(#3040)
Documentation
- Document
<THROW_EXCEPTION>in the reference guide (#3112)
1.5.3.Final
Bugs
- Generic
@AfterMappingdoes not consider@MappingTargetproperly in 1.5 (#3036) - Method annotated with
@AfterMappingis not called (#2955) - Ignored unknown source property error, but property exist (#2743)
SubclassMappingdoesn't honourmappingControl(#3018)- Upgrade from 1.4.1 to 1.5.2 broke primitive to wrapper classes mapping (#2921)
- Conversion of
BigDecimalto primitivedoublewrong with 1.5.2 (#2913) - Ambiguous mapping methods when upgrading to MapStruct 1.5.0.RC1 (#2840)
SubclassMappingstackoverflow exception (#2825)Optionalwrapping pattern broken in 1.5.2.Final (#2925)- Missing import in generated mapper when referencing a nested enum from an unrelated class (#2945)
- Unused import warning of nested classes (#2907)
- Compilation error in generated code for
@Conditionaland collection (#2937) - Missing import of nested class (#2897)
- Ignoring unmapped source properties in inverse inheritance (#2949)
- Compilation error when mapping fields with the same type due to not wrapping in a
try-catchblock (#2839) - Using
@TargetTypeas a parameter for@Conditioncauses NPE during compiling (#2882) - Cannot map from a covariant (extends) generic type (#2677)
Documentation
- Add IntelliJ and Eclipse plugin to the documentation (#2928)
- Fix typos in documentation (#2974, #2982, #2989)
- Update Typos in javadoc (#2958)
- Polish comments, javadoc and documentation (#3026)
- Improve documentation for
BeanMapping#ignoreByDefault(#2929)
Build
- Build fails when running mvn test on an M1 Mac (#2922)