Skip to content

Why did you make qualifiedByName more strict with collection mappings in 1.4.1.Final? #2324

Description

@TheMorganHub

I'm talking about this comment here
#2250 (comment)

It feels like this is a bit of a downgrade, because now we're forced to create a @Named method for the Collection mapping and in it, we have to iterate the collection and call the single object mapping method manually.

Consider the following example that worked in 1.3.1.Final:

@Mapper
public abstract class SalesRuleMapper {

    @Autowired
    private SalesRuleRepository salesRuleRepository;

    abstract void updateSalesRuleFromEventBusOrderSalesRuleDTO(@MappingTarget SalesRule salesRule, EventBusOrderSalesRuleDTO eventBusOrderSalesRuleDTO);

    abstract SalesRule mapFromEventBusOrderSalesRuleDTO(EventBusOrderSalesRuleDTO eventBusOrderSalesRuleDTO, @Context OmsContext omsContext);

    @Named("mapFromEventBusOrderSalesRuleDTOWithOmsContext")
    public SalesRule mapFromEventBusSalesRuleDTO(EventBusOrderSalesRuleDTO eventBusOrderSalesRuleDTO, @Context OmsContext omsContext) {
        SalesRule existingSalesRule = salesRuleRepository
                .findByNameAndCouponCodeAndFromDateAndToDateAndStoreId(eventBusOrderSalesRuleDTO.getName(),
                        eventBusOrderSalesRuleDTO.getCouponCode(),
                        eventBusOrderSalesRuleDTO.getFromDate(),
                        eventBusOrderSalesRuleDTO.getToDate(),
                        omsContext.getStore().getId());
        if (existingSalesRule != null) {
            updateSalesRuleFromEventBusOrderSalesRuleDTO(existingSalesRule, eventBusOrderSalesRuleDTO);
            return existingSalesRule;
        }
        SalesRule newSalesRule = mapFromEventBusOrderSalesRuleDTO(eventBusOrderSalesRuleDTO, omsContext);
        return newSalesRule;
    }
}
@Mapper(uses = {
        SalesRuleMapper.class
}, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public abstract class OrderMapper {

    @Autowired
    protected OmsContext omsContext;

    @Mapping(source = "salesRules", target = "salesRules", qualifiedByName = "mapFromEventBusOrderSalesRuleDTOWithOmsContext")
    public abstract Order fromEventBusOrder(EventBusOrderDTO eventBusOrderDTO, @Context OmsContext omsContext);

    public Order fromEventBusOrder(EventBusOrderDTO eventBusOrderDTO) {
        return fromEventBusOrder(eventBusOrderDTO, omsContext);
    }
}

MapStruct would internally generate the method that'd iterate over the collections and map each item:

    protected Set<SalesRule> eventBusOrderSalesRuleDTOArrayToSalesRuleSet(EventBusOrderSalesRuleDTO[] eventBusOrderSalesRuleDTOArray, OmsContext omsContext) {
        if ( eventBusOrderSalesRuleDTOArray == null ) {
            return null;
        }

        Set<SalesRule> set = new HashSet<SalesRule>( Math.max( (int) ( eventBusOrderSalesRuleDTOArray.length / .75f ) + 1, 16 ) );
        for ( EventBusOrderSalesRuleDTO eventBusOrderSalesRuleDTO : eventBusOrderSalesRuleDTOArray ) {
            set.add( salesRuleMapper.mapFromEventBusSalesRuleDTO( eventBusOrderSalesRuleDTO, omsContext ) );
        }

        return set;
    }

But now, in 1.4.1.Final, eventBusOrderSalesRuleDTOArrayToSalesRuleSet doesn't get generated automatically anymore.
And since the @Named annotation now has to go on the Array to Collection method and not the individual object, this presents an inconvenience for the user, because we have to write the Collection mapping method and call the individual mapping method manually. Error prone code like this is something MapStruct intends to avoid.

Is there a reason why the decision has been made to add this limitation?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions