MapStruct v1.3.0.Beta1 Release Notes
Release Date: 2018-07-15 // almost 6 years ago-
๐ Features
- ๐ Support for Builders (#782 and #802). Support tested with:
- Lombok - requires having the Lombok classes in a separate module see rzwitserloot/lombok#1538
- AutoValue
- Immutables - see (#1415) for more info for the out of the box support
- FreeBuilder
- It also works for custom builder if the object being build provides a parameterless public static method for instantiating the builder. Otherwise, you would need to write a custom
BuilderProvider
- โ Add a
NoOpBuilderProvider
(#1418) -BuilderProvider
that allows users to disable the using of Builders in MapStruct. You need to enable it explicitly by creating aorg.mapstruct.ap.spi.BuilderProvider
file in theMETA-INF/services
directory withorg.mapstruct.ap.spi.NoOpBuilderProvider
as its content. - ๐ Out of the box support for Immutables (#1415)
- โ Add Constructor Injection for Annotation Based Component Model (#571)
- โ Add support for
unmappedSourcePolicy
(#610) - โ Add support for ignoring source properties (#1317)
- ๐ Allow defaultValue to be an expression (#1363) - A new
defaultExpression
has been added to@Mapping
- ๐ Object factory needs to be considered for builder types as well (#1431)
- ๐ง Ignore mappings by default (#1392) - With
@BeanMapping(ignoreByDefault = true)
one can limit the mapping only to the explicitly defined mappings. This annotation actually applies ignore to all target properties, which means that it can be used in configuration mappings to only map explicit properties in base classes - Access to Builder type in
@BeforeMapping
and@AfterMapping
(#1433) - NB : Lifecycle methods for the type being build are not invoked yet (see #1454)
โจ Enhancements
- Exceptions in nested beanmapping are not declared in generated code (#1332)
@Mapping
arguments should be trimmed (#1353)- โ Add implicit conversion between
String
andjava.util.Currency
(#1355) - Shared configuration not applied when using
InheritInverseConfiguration
(#1367) - aligning@Inherit(Inverse)Configuration
with strategyAUTO_INHERIT_*
- ๐ Extremily low mapstruct-processor performance on Java 9 (#1378) - Use
Types
when searching forTypeElement
(s) instead of getting a newTypeElement
each time - Report error on the
@Mapping
annotation when using invalid@Mapping
values (#1383) - ๐ Improve error message when unknown source parameter is used in
@Mapping
(#1387) - ๐ Possible performance improvement of
constant
/defaultValue
primitive toString
mappings (#1401) - See behavior changes - ๐ Allow using update mappings for types with builders (#1423)
- Lazy load SPIs in annotation processor context (#1473)
@ObjectFactory
not called when on an@Context
object (#1398)- ๐ Allow package-private mapper (#1365)
- โ Add support for Builders with multiple build methods (#1479) - See PR #1498 for more details
๐ Bug fixes
- ๐ป Context annotation on primitive types with
@AfterMapping
throws exception on compile (#1339) - Enum mapper generates mapping method with wrong signature. Wrong amount of parameters (#1340)
- Not generating setter methods for all nested constants (#1320)
- Ignore doesn't work for readonly properties (#1345)
- Invalid mapper is created when there is no read accessor for nested target mappings (#1375)
- Injection strategy Constructor does not generate compilable code (#1395)
- ๐ง Shared configuration not applied when using
@InheritInverseConfiguration
(#1367) - โ Mapping
String
toorg.joda.time.LocalDate
issues compiler error (#1370) - When using date format MapStruct tries to validate it by invoking the Joda formatter. This means that the Joda dependency needs to be on the classpath. If the MapStruct processor is invoked from the processor path, and Joda is not there we can't invoke Joda classes. If this is the case we will now issue a warning saying what the user needs to do (add Joda to the processor path) and consider the format as valid - โก๏ธ MapStruct throws an exception during collection update mapping when target is immutable and there is no target read accessor (#1359)
- โ Adder argument cannot be determined when collection type is not generic (#1338)
- Pass originating elements to the
javax.annotation.processing.Filer
API (#1414) org.joda.time.LocalDate
tojava.time.LocalDate
generated code has compilation error (#1425) - With this fix we have also improved the builtin templates, so something similar should not happen again- 0๏ธโฃ Improper
@BeanMapping(ignoreByDefault=true)
treatment with Immutable target (#1452) - Direct constant assignment causes problems for
byte
andshort
values (#1462) - โ Adder method not working for builders (#1449)
String
toenum
conversion: Compile error in generated mapper (#1460) - Ensures the FQN will be used forSimpleConversion
if required, something like this should not happen again- Compilation error on CollectionMapping. Wrong capture generated (#1453)
- ๐ง
NullPointerException
when using unknown source properties with shared configuration (#1180) ZonedDateTime
toXmlGregorianCalendar
losses time zone information (#1523)- Generic mapping method not selected (#1482)
- โ "Ambiguous mapping methods found" when the same method is found twice (#537) - Fixed in an earlier version, but now we have a test for it.
๐ Documentation
- โ Add IntelliJ Formatter to CONTRIBUTING.md (#1297)
- ๐ Change MapStruct Version in README to latest 1.2.0.Final (#1312)
- ๐ Injection Strategy docs (#1314)
- โ Add since tags for
unmappedSourcePolicy()
(#1333) - โ Add change of behaviour for
constant
anddefaultValue
in@Mapping
(#1459) - ๐ Use constants instead of strings in
@ValueMapping
javadoc (PR #1480) - ๐ Update documentation about the latest gradle apt plugin (#1419)
- Document of sample code is broken (PR #1530)
- โ Add sample of
@Mapping
annotation to@InheritInverseConfiguration
(#1531) - โ Add documentation about the Builders support (#1417)
- โ Add
@since
tag to@Mapping#defaultExpression()
(#1436)
Behavior
0๏ธโฃ With #1401 MapStruct now tries to check if it is possible to assign a
defaultValue
and / or aconstant
directly without doing a conversion. For example for the following mapper:@Mapperpublic interface PersonMapper { @Mapping(target = "price", constant = "10.5") @Mapping(target = "age", defaultValue = "10) Order order(OrderDto source); }
Before the following was generated:
public class PersonMapperImpl implements PersonMapper { @Overridepublic Order order(OrderDto source) { if (source == null) { return null; } Order order = new Order(); order.setConstant(Double.parseDouble("10.5")); if (source.getAge() == null) { order.setAge(Integer.parse("10")); } else { order.setAge(source.getAge()); } return order; } }
And now the following is generated:
public class PersonMapperImpl implements PersonMapper { @Overridepublic Order order(OrderDto source) { if (source == null) { return null; } Order order = new Order(); order.setConstant(10.5)); if (source.getAge() == null) { order.setAge(10); } else { order.setAge(source.getAge()); } return order; } }
๐ On top of that MapStruct the possible values are more and you can use anything that the compiler would consider as a valid integer (for example
10_000
). The parse functions don't accept such strings as valid. - ๐ Support for Builders (#782 and #802). Support tested with: