|
| 1 | +--- |
| 2 | +title: "Support for accessing property names, passing annotations to generated code, sponsoring MapStruct and much more: MapStruct 1.6.0.Beta1 is out" |
| 3 | +author: Filip Hrisafov |
| 4 | +date: "2023-11-04" |
| 5 | +tags: [release, news] |
| 6 | +--- |
| 7 | + |
| 8 | +It's my pleasure to announce the first Beta release of MapStruct 1.6. |
| 9 | + |
| 10 | +The new release comes with a lot of new functionality, e.g.: |
| 11 | + |
| 12 | +* Access to target / source property names in conditional and mapping methods |
| 13 | +* Passing annotations to generated code |
| 14 | +* Add javadoc to generated code |
| 15 | +* New built-in conversions |
| 16 | + |
| 17 | +With this release we are also happy to announce that MapStruct has started accepting donations through [Open Collective](https://opencollective.com/mapstruct) or [GitHub](https://github.com/sponsors/mapstruct). |
| 18 | +We'd like to thank to everyone that has already started in supporting us: |
| 19 | + |
| 20 | +* [addesso SE](https://github.com/adessoSE) |
| 21 | +* [Bileto](https://opencollective.com/bileto) |
| 22 | +* [Frederik Hahne](https://opencollective.com/atomfrede) |
| 23 | + |
| 24 | +<!--more--> |
| 25 | + |
| 26 | +Altogether, not less than [63 issues](https://github.com/mapstruct/mapstruct/issues?q=milestone%3A1.6.0.Beta1) were fixed for this release. |
| 27 | + |
| 28 | +This would not have been possible without our fantastic community of contributors: |
| 29 | + |
| 30 | +* [@anton-erofeev](https://github.com/anton-erofeev) |
| 31 | +* [@Blackbaud-JasonBodnar](https://github.com/Blackbaud-JasonBodnar) |
| 32 | +* [@Bragolgirith](https://github.com/Bragolgirith) |
| 33 | +* [@chenzijia12300](https://github.com/chenzijia12300) |
| 34 | +* [@eroznik](https://github.com/eroznik) |
| 35 | +* [@EvaristeGalois11](https://github.com/EvaristeGalois11) |
| 36 | +* [@ivlcic](https://github.com/ivlcic) |
| 37 | +* [@jccampanero](https://github.com/jccampanero) |
| 38 | +* [@kooixh](https://github.com/kooixh) |
| 39 | +* [@MengxingYuan](https://github.com/MengxingYuan) |
| 40 | +* [@MLNW](https://github.com/MLNW) |
| 41 | +* [@Nikolas-Charalambidis](https://github.com/Nikolas-Charalambidis) |
| 42 | +* [@paparadva](https://github.com/paparadva) |
| 43 | +* [@prasanth08](https://github.com/prasanth08) |
| 44 | +* [@ro0sterjam](https://github.com/ro0sterjam) |
| 45 | +* [@rgdoliveira](https://github.com/rgdoliveira) |
| 46 | +* [@venkatesh2090](https://github.com/venkatesh2090) |
| 47 | + |
| 48 | +* our latest MapStruct contributor [Oliver Erhart](https://github.com/thunderhook) |
| 49 | +* and of course seasoned MapStruct hackers [Ben Zegveld](https://github.com/Zegveld), [Sjaak Derksen](https://github.com/sjaakd), [Filip Hrisafov](https://github.com/filiphr). |
| 50 | + |
| 51 | +Thank you everyone for all your hard work! |
| 52 | + |
| 53 | +Slightly more than a year after the first Beta release of 1.6, we are proud to present you with the first Beta of the 1.6 release. |
| 54 | + |
| 55 | +Enough of the pep talk, let's take a closer look at some of the new features and enhancement! |
| 56 | + |
| 57 | +### Access to target / source property names in conditional and mapping methods |
| 58 | + |
| 59 | +It is now possible to get access to the target property name in conditional and mapping methods. |
| 60 | + |
| 61 | +e.g. |
| 62 | + |
| 63 | +{{< prettify java >}} |
| 64 | +public class HibernateUtils { |
| 65 | + |
| 66 | + @Condition |
| 67 | + public static boolean isAccessible(Customer customer, @TargetPropertyName String propertyName) { |
| 68 | + return Hibernate.isPropertyInitialized(customer, propertyName); |
| 69 | + } |
| 70 | + |
| 71 | +} |
| 72 | + |
| 73 | +@Mapper(uses = HibernateUtils.class) |
| 74 | +public interface CustomerMapper { |
| 75 | + |
| 76 | + CustomerDto map(Customer customer); |
| 77 | +} |
| 78 | +{{< /prettify >}} |
| 79 | + |
| 80 | +Will generate something like |
| 81 | + |
| 82 | +{{< prettify java >}} |
| 83 | +// GENERATED CODE |
| 84 | +public class CustomerMapperImpl implements CustomerMapper { |
| 85 | + |
| 86 | + @Override |
| 87 | + public CustomerDto map(Customer customer) { |
| 88 | + // ... |
| 89 | + if ( HiberateUtils.isAccessible( customer, "orders" ) ) { |
| 90 | + customer.setOrders( mapOrders( customer.getOrders() ) ); |
| 91 | + } |
| 92 | + // ... |
| 93 | + } |
| 94 | + |
| 95 | + // ... |
| 96 | +} |
| 97 | +{{< /prettify >}} |
| 98 | + |
| 99 | +### Passing annotations to generate code |
| 100 | + |
| 101 | +Using `@AnnotateWith` custom annotations can be passed to the generated code. |
| 102 | + |
| 103 | +{{< prettify java >}} |
| 104 | +@AnnotateWith( value = Component.class, elements = @AnnotateWith.Element( strings = "customerMapperV1" ) ) |
| 105 | +@Mapper( componentModel = MappingConstants.ComponentModel.SPRING ) |
| 106 | +public interface CustomerMapper { |
| 107 | + // ... |
| 108 | +} |
| 109 | +{{< /prettify >}} |
| 110 | + |
| 111 | +This will generate: |
| 112 | + |
| 113 | +{{< prettify java >}} |
| 114 | +// GENERATED CODE |
| 115 | +@Component("customerMapperV1") |
| 116 | +public class CustomerMapperImpl implements CustomerMapper { |
| 117 | + // ... |
| 118 | +} |
| 119 | +{{< /prettify >}} |
| 120 | + |
| 121 | +This for example can be used to provide a custom name for the Spring `@Component` |
| 122 | + |
| 123 | +### Add Javadoc to generated code |
| 124 | + |
| 125 | +Using `@Javadoc` it is possible to pass custom javadoc to the generated code. |
| 126 | + |
| 127 | +e.g. |
| 128 | + |
| 129 | +{{< prettify java >}} |
| 130 | +@Mapper |
| 131 | +@Javadoc("This is the description\n" |
| 132 | + + "\n" |
| 133 | + + "@author author1\n" |
| 134 | + + "@author author2\n" |
| 135 | + + "\n" |
| 136 | + + "@deprecated Use {@link CustomerV2Mapper} instead\n" |
| 137 | + + "@since 0.1\n") |
| 138 | +@Deprecated |
| 139 | +public interface CustomerMapper { |
| 140 | +} |
| 141 | +{{< /prettify >}} |
| 142 | + |
| 143 | +or |
| 144 | + |
| 145 | + |
| 146 | +{{< prettify java >}} |
| 147 | +@Mapper |
| 148 | +@Javadoc( |
| 149 | + value = "This is the description", |
| 150 | + authors = { "author1", "author2" }, |
| 151 | + deprecated = "Use {@link CustomerV2Mapper} instead", |
| 152 | + since = "0.1" |
| 153 | +) |
| 154 | +@Deprecated |
| 155 | +public interface CustomerMapper { |
| 156 | +} |
| 157 | +{{< /prettify >}} |
| 158 | + |
| 159 | +In both cases the generated code looks like: |
| 160 | + |
| 161 | +{{< prettify java >}} |
| 162 | +/** |
| 163 | +* This is the description |
| 164 | +* |
| 165 | +* @author author1 |
| 166 | +* @author author2 |
| 167 | +* |
| 168 | +* @deprecated Use {@link CustomerV2Mapper} instead |
| 169 | +* @since 0.1 |
| 170 | +*/ |
| 171 | +@Deprecated |
| 172 | +// GENERATED CODE |
| 173 | +public class CustomerMapperImpl implements CustomerMapper { |
| 174 | +} |
| 175 | +{{< /prettify >}} |
| 176 | + |
| 177 | +### New Built-In conversions |
| 178 | + |
| 179 | +We have extensive number of built-in conversions between different types. |
| 180 | +As of this release we have 4 more: |
| 181 | + |
| 182 | +* Between `Enum` and `Integer` - This basically uses `Enum#ordinal` to map to integer and `MyEnum.values()[value]` to map from an integer value |
| 183 | +* Between `Locale` and `String` |
| 184 | +* Between `java.time.LocalDate` and `java.time.LocalDateTime` |
| 185 | +* Between `Iterable` and `Collection` |
| 186 | + |
| 187 | +### Enhancements |
| 188 | + |
| 189 | +* New compiler options have been added for defining `nullValueIterableMappingStrategy` and `nullValueMapMappingStrategy` globally. The options are `mapstruct.nullValueIterableMappingStrategy` and `mapstruct.nullValueMapMappingStrategy` respectively. |
| 190 | +* Subclass mappings now support qualifiers |
| 191 | +* SPI implementations now have the possibility to provide custom compiler options. |
| 192 | + A new SPI (`AdditionalSupportedOptionsProvider`) needs to be implemented to provide the custom options. |
| 193 | + Custom compiler options are not allowed to start with `mapstruct` |
| 194 | +* The most specific mapping will be picked when the return type can be assigned to a simpler type. e.g. |
| 195 | +{{< prettify java >}} |
| 196 | + public static java.util.Date toUtilDate(String strDate); |
| 197 | + public static java.sql.TimeStamp toTimeStamp(String strDate); |
| 198 | + public static java.sql.Date toSqlDate(String strDate); |
| 199 | +{{< /prettify >}} |
| 200 | + Previously mapping from a `String` to `java.util.Date` would fail since any of the 3 methods could be used. |
| 201 | + However, now the `toUtilDate` would be picked |
| 202 | +* Collection getter is not treated as a write accessor when using `CollectionMappingStrategy#TARGET_IMMUTABLE` |
| 203 | +* Error location has been improved for `@SubclassMapping` |
| 204 | +* Support `@InheritConfiguration` for `@SubclassMapping` |
| 205 | +* Do not require `subclassExhaustiveStrategy` when source is a sealed class and all subtypes are specified |
| 206 | +* All lifecycle methods are support for builders |
| 207 | + * `@BeforeMapping` with `@TargetType` the type being build |
| 208 | + * `@AfterMapping` with `@TargetType` the type being build |
| 209 | + * `@AfterMapping` with `@MappingTarget` the type being build |
| 210 | +* Some redundant null checks have been removed for nested properties |
| 211 | +* Support `@Default` for records |
| 212 | +* Add `InjectionStrategy.SETTER` |
| 213 | +* Add `BeanMapping#unmappedSourcePolicy` |
| 214 | +* Improve support for `Map` attributes for Immutables |
| 215 | + |
| 216 | +### Breaking Changes |
| 217 | + |
| 218 | +Map to Bean |
| 219 | +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. |
| 220 | +However, this lead to some problems in multi mapping methods. |
| 221 | +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. |
| 222 | + |
| 223 | +e.g. |
| 224 | + |
| 225 | +{{< prettify java >}} |
| 226 | +@Mapper |
| 227 | +public interface CarMapper { |
| 228 | + |
| 229 | + // This method is going to implicitly map all the target properties from the map |
| 230 | + Target map(Map<String, Object> map); |
| 231 | + |
| 232 | + // This method is not going to use the map for implicit mappings. |
| 233 | + // Only the name will be mapped from the map (since it has been defined like that |
| 234 | + @Mapping(target = "name", source = "map.name") |
| 235 | + Target map(Source source, Map<String, Object> map) |
| 236 | + |
| 237 | +} |
| 238 | +{{< /prettify >}} |
| 239 | + |
| 240 | +### Download |
| 241 | + |
| 242 | +This concludes our tour through MapStruct 1.6 Beta1. |
| 243 | +If you'd like to try out the features described above, you can fetch the new release from Maven Central using the following GAV coordinates: |
| 244 | + |
| 245 | +* Annotation JAR: [org.mapstruct:mapstruct:1.6.0.Beta1](http://search.maven.org/#artifactdetails|org.mapstruct|mapstruct|1.6.0.Beta1|jar) |
| 246 | +* Annotation processor JAR: [org.mapstruct:mapstruct-processor:1.6.0.Beta1](http://search.maven.org/#artifactdetails|org.mapstruct|mapstruct-processor|1.6.0.Beta1|jar) |
| 247 | + |
| 248 | +Alternatively, you can get ZIP and TAR.GZ distribution bundles - containing all the JARs, documentation etc. - [from GitHub](https://github.com/mapstruct/mapstruct/releases/tag/1.6.0.Beta1). |
| 249 | + |
| 250 | +If you run into any trouble or would like to report a bug, feature request or similar, use the following channels to get in touch: |
| 251 | + |
| 252 | +* Get help in our [Gitter room](https://gitter.im/mapstruct/mapstruct-users), the [GitHub Discussion](https://github.com/mapstruct/mapstruct/discussions) or [StackOverflow](https://stackoverflow.com/questions/tagged/mapstruct) |
| 253 | +* Report bugs and feature requests via the [issue tracker](https://github.com/mapstruct/mapstruct/issues) |
| 254 | +* Follow [@GetMapStruct](https://twitter.com/GetMapStruct) on Twitter |
0 commit comments