Total Pageviews

2017/11/08

[MapStruct] How to use Decorator in MapStruct?

Problem
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;
    }

}




No comments: