Assume I have a DeliveryAddressDto Java bean, it has three attributes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package albert.practice.mapStruct; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @AllArgsConstructor @NoArgsConstructor @Data @ToString public class DeliveryAddressDto { private String receiver; private String addressString; private String totalString; } |
I have three Java beans, they provide information which DeliveryAddressDto needed.
1. Person bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package albert.practice.mapStruct; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @AllArgsConstructor @NoArgsConstructor @Data @ToString public class Person { private String firstName; private String lastName; } |
2. Address bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package albert.practice.mapStruct; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @AllArgsConstructor @NoArgsConstructor @Data @ToString public class Address { private String addressString; } |
3. ShoppingItems bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package albert.practice.mapStruct; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @AllArgsConstructor @NoArgsConstructor @Data @ToString public class ShoppingItems { private Long total; } |
The three attributes values in DeliveryAddressDto Java bean will copy from Person, Address, and ShoppingItems bean
(1) DeliveryAddressDto.receiver = Person.firstName + " " + Person.lastName
(2) DeliveryAddressDto.addressString = Address.addressString
(3) DeliveryAddressDto.totalString = ShoppingItems.total (Apply format: NT$#,###,###,##0)
How to use decorator to fulfill this requirement?
How-To
1. create a mapper class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package albert.practice.mapStruct.mapper; import org.mapstruct.DecoratedWith; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import albert.practice.mapStruct.Address; import albert.practice.mapStruct.DeliveryAddressDto; import albert.practice.mapStruct.Person; import albert.practice.mapStruct.ShoppingItems; import albert.practice.mapStruct.decorator.AddressDecorator; @Mapper @DecoratedWith(AddressDecorator.class) public interface AddressMapper { // By convention, a mapper interface should define a member called INSTANCE // which holds a single instance of the mapper type: AddressMapper INSTANCE = Mappers.getMapper(AddressMapper.class); @Mapping(target = "totalString", source = "shoppingItems.total") @Mapping(target = "receiver", source = "person.lastName") @Mapping(target = "addressString", source = "address.addressString") DeliveryAddressDto covertPersonAndAddressToDeliveryAddressDto(Person person, Address address, ShoppingItems shoppingItems); } |
2. create a decorator class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package albert.practice.mapStruct.decorator; import java.text.DecimalFormat; import albert.practice.mapStruct.Address; import albert.practice.mapStruct.DeliveryAddressDto; import albert.practice.mapStruct.Person; import albert.practice.mapStruct.ShoppingItems; import albert.practice.mapStruct.mapper.AddressMapper; public class AddressDecorator implements AddressMapper { private final AddressMapper delegate; private DecimalFormat decimalFormat = new DecimalFormat("NT$#,###,###,##0"); public AddressDecorator(AddressMapper delegate) { this.delegate = delegate; } @Override public DeliveryAddressDto covertPersonAndAddressToDeliveryAddressDto(Person person, Address address, ShoppingItems shoppingItems) { DeliveryAddressDto dto = delegate.covertPersonAndAddressToDeliveryAddressDto(person, address, shoppingItems); dto.setReceiver(person.getFirstName() + " " + person.getLastName()); dto.setTotalString(decimalFormat.format(shoppingItems.getTotal())); return dto; } } |