Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing additional parameters to MapStruct mapper

Haven't figured out how to pass in additional arguments or an alternative.

Currently I'm mapping an Order and OrderLines. Both objects are different and need @mappings. Example I have an Order and OrderRequest object both are different and need @Mappings annotation to map the values, same with OrderLines.

I've created the following mappers

  • OrderMapper (uses = OrderLineMappers.class)
  • OrderLineMappers (uses = OrderLineMapper.class)
  • OrderLineMapper

So my issue is the OrderLine needs the OrderId from the Order object. However in the OrderLineMapper it's passing in the OrderLine and not the Order. How can I send the OrderId to the OrderLineMapper? Currently I have the OrderMapper doing an @AfterMapper, looping through the orderLines and populating with the OrderId.

Any help would be great.

Class OrderMapper

@Mapper(componentModel = "spring",  uses = {OrderLineMappers.class})
public abstract class OrderMapper {

@AfterMapping
protected void orderRequestFromOrder( Order order, @MappingTarget 
OrderRequest orderRequest ) {

    //Wanting to do this at the OrderLineMapper class and not here
    String orderId = order.getId();
    List<OrderLineRequest> lines = orderRequest.getOrderLines();
    List<OrderLineRequest> updatedLines = new ArrayList<>();
    for (OrderLineRequest line : lines) {
        line.setOrderId(orderId);
        updatedLines.add(line);
    }
    orderRequest.setOrderLines(updatedLines);
}

@Mappings({
    @Mapping( source = "orderId", target = "id" ),
    @Mapping( source = "orderNumber", target = "order_number" ),
    @Mapping( source = "orderLines", target = "orderLines")
})
public abstract Order orderRequestToOrder(OrderRequest orderRequest);

Class OrderLineMappers

@Mapper(componentModel = "spring",  uses = {OrderLineMapper.class})
public interface OrderLineMappers {

    List<OrderLine> orderLines(List<OrderLineRequest> orderLineRequest);

    @InheritInverseConfiguration
    List<OrderLineRequest> orderLineRequests(List<OrderLine> orderLine); 

}

Class OrderLineMapper

@Mapper(componentModel = "spring")
public abstract class OrderLineMapper {
    @Mappings({
        @Mapping( target = "orderId", source = "orderLineId" ),
        @Mapping( target = "order_line_number", source = "orderLineNumber")

    })
    public abstract OrderLine orderLineRequestToOrderLine(OrderLineRequest orderLineRequest);
}

Again just trying to pass in the OrderId to the OrderLineMapper. Not sure how to do this.

like image 513
shadley Avatar asked May 24 '18 20:05

shadley


1 Answers

You can't really do this. What you can do instead is to use the @Context and perform your logic in it. You can have @AfterMapping and @BeforeMapping in your context where you can store the Order id and use that during its execution

e.g.

public class OrderMappingContext {

    protected String currentOrderId;

    @BeforeMapping
    public void startMappingOrder(@MappingTarget Order order, OrderRequest request) {
        this.currentOrderId = request.getId();
    }

    @AfterMapping
    public void finishOrderMapping(@MappingTarget Order order) {
        this.currentOrderId = null;
    }

    @AfterMapping
    public void afterOrderLineMapping(@MappingTarget OrderLine orderLine) {
        orderLine.setOrderId(this.currentOrderId);
    }
}

Your mappers will then look like:

@Mapper(componentModel = "spring",  uses = {OrderLineMappers.class})
public abstract class OrderMapper {



    @Mapping( source = "orderId", target = "id" ),
    @Mapping( source = "orderNumber", target = "order_number" ),
    @Mapping( source = "orderLines", target = "orderLines")
    public abstract Order orderRequestToOrder(OrderRequest orderRequest, @Context OrderMappingContext context);
@Mapper(componentModel = "spring",  uses = {OrderLineMapper.class})
public interface OrderLineMappers {

    List<OrderLine> orderLines(List<OrderLineRequest> orderLineRequest, @Context OrderMappingContext context);

    @InheritInverseConfiguration
    List<OrderLineRequest> orderLineRequests(List<OrderLine> orderLine); 

}
@Mapper(componentModel = "spring")
public abstract class OrderLineMapper {

    @Mapping( target = "orderId", source = "orderLineId" ),
    @Mapping( target = "order_line_number", source = "orderLineNumber")
    public abstract OrderLine orderLineRequestToOrderLine(OrderLineRequest orderLineRequest, @Context OrderMappingContext context);
}

On the invocation side you will do something like

orderMapper.orderRequestToOrder(request, new OrderMappingContext());
like image 109
Filip Avatar answered Nov 09 '22 10:11

Filip