'How to inject a value to a MapStruct interface - java

I have a MapStruct interface that receives a List<> as a parameter which is read from a yaml config file

  @Value("${clientType.individual.channelIds}")
  private List<String> validIndividualChannelIds;

I was wondering if there was either a way to retrieve that property from within the MapStruct interace or injected into the interface to avoid having to pass that parameter around to mapClientType() and then to isIndividual()?

@Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = IGNORE)
public interface TransferMapper {

  @Mapping(source = "headers.requestId", target = "requestId")
  @Mapping(source = "headers.callback", target = "callback")
  @Mapping(source = "headers.agentId", target = "agentId")
  @Mapping(source = "headers.partnerId", target = "partnerId")
  @Mapping(source = "messageId", target = "messageId")
  @Mapping(source = "transferRequest.instructedAmount.amount", target = "amountWithCurrency.amount")
  @Mapping(source = "transferRequest.instructedAmount.currency", target = "amountWithCurrency.currency")
  @Mapping(source = "transferRequest.debtor.identification.organisationIdentification.other.identification", target = "clientId")
  Transfer toTransfer(TransferRequest transferRequest, TransferHeaders headers, UUID messageId, List<String> validIndividualChannelIds);

  @AfterMapping
  default void mapClientType(@MappingTarget Transfer transfer, TransferHeaders headers,
                             TransferRequest transferRequest, List<String> validIndividualChannelIds) {
    if (isIndividual(headers, transferRequest, validIndividualChannelIds)) {
      transfer.setClientType(ClientType.INDIVIDUAL);
    } else {
      transfer.setClientType(ClientType.ORGANISATION);
    }
  }

  default boolean isIndividual(TransferHeaders headers, TransferRequest transferRequest, List<String> validIndividualChannelIds) {
    return validIndividualChannelIds.contains(headers.getChannelId()) ||
            (ChannelType.BATCH.getValue().equals(headers.getChannelType()));
  }

}


Solution 1:[1]

Try using an abstract class instead of an interface, and then putting the field inside it. That way your isIndividual method can access the field directly.

For example:

@Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = IGNORE)
public abstract class TransferMapper {

  @Value("${clientType.individual.channelIds}")
  private List<String> validIndividualChannelIds;

  // @Mapping annotations here.
  abstract Transfer toTransfer(TransferRequest transferRequest, TransferHeaders headers, UUID messageId);

  @AfterMapping
  protected void mapClientType(@MappingTarget Transfer transfer, TransferHeaders headers, TransferRequest transferRequest) {
    if (isIndividual(headers, transferRequest)) {
      transfer.setClientType(ClientType.INDIVIDUAL);
    } else {
      transfer.setClientType(ClientType.ORGANISATION);
    }
  }

  private boolean isIndividual(TransferHeaders headers, TransferRequest transferRequest) {
    return validIndividualChannelIds.contains(headers.getChannelId()) ||
            (ChannelType.BATCH.getValue().equals(headers.getChannelType()));
  }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ben Zegveld