как сопоставить JaxbElement‹X› с JaxbElement‹Y› с помощью MapStruct

Я собирался создать задачу на github, но в шаблоне задачи сказано, что я предпочел бы сначала обсудить ее здесь, так что начнем:

Я пытаюсь использовать Mapstruct для создания сопоставлений из одного набора сущностей, созданного WSDL, в другой. Однако без добавления метода «по умолчанию» (ручное сопоставление) это не работает! Это кажется странным, так как я ожидаю, что такой вид сопоставления не должен быть сложным для Mapstruct. случай репро здесь: https://github.com/62mkv/wsdl-mapstruct-repro-case

суть кода здесь:

@Mapper(uses = {
    org.system.wsdl.legacy.ObjectFactory.class
})
public interface WsMapper {

org.system.wsdl.legacy.SellGarlicRequest fromCloud(org.system.wsdl.cloud.SellGarlicRequest request);

}

этот код выше не скомпилируется с таким сообщением:

Не удается сопоставить свойство «javax.xml.bind.JAXBElement inputParameters» с «javax.xml.bind.JAXBElement inputParameters». Рассмотрите возможность объявить/реализовать метод сопоставления: «javax.xml.bind.JAXBElement map (значение javax.xml.bind.JAXBElement)». org.system.wsdl.legacy.SellGarlicRequest fromCloud (запрос org.system.wsdl.cloud.SellGarlicRequest);

в основном сопоставление будет происходить следующим образом: EntityNew -> JaxbElement -> FieldNew -> FieldOld -> JaxbElement -> EntityOld

как я читал здесь (https://stackoverflow.com/a/46015381/2583044), сопоставление JaxbElement с T тривиален для MapStruct, и для сопоставления T с JaxbElement нужно использовать аннотацию «использует» и предоставить ObjectFactory.class, что я и делаю; однако... кажется, этого недостаточно.

если я добавлю эти два метода, код компилируется хорошо:

org.system.wsdl.legacy.GarlicParameterCollection garlicParameterCollectionToGarlicParameterCollection(org.system.wsdl.cloud.GarlicParameterCollection collection);

default JAXBElement<org.system.wsdl.legacy.GarlicParameterCollection> garlicParameterCollectionToGarlicParameterCollection(JAXBElement<org.system.wsdl.cloud.GarlicParameterCollection> parameterCollectionJAXBElement) {
    return new org.system.wsdl.legacy.ObjectFactory().createSellGarlicRequestInputParameters(
            this.garlicParameterCollectionToGarlicParameterCollection(parameterCollectionJAXBElement.getValue())
    );
}

это потенциальная проблема в mapstruct или я просто не умею его хорошо готовить?


person 62mkv    schedule 02.03.2020    source источник


Ответы (1)


Проблема в том, что MapStruct видит ваш метод фабрики объектов (с аргументом) как метод сопоставления. Таким образом, он доставляет цель, но у него также есть источник. Если вы это осознаете, то отображение вдруг окажется несимметричным (как кажется изначально).

Простое решение состоит в том, чтобы проинструктировать MapStruct, как с этим справиться.

Итак: попробуйте это:


@Mapper(uses = {
        org.system.wsdl.legacy.ObjectFactory.class
})
public interface WsMapper {

    org.system.wsdl.legacy.GarlicParameterCollection garlicParameterCollectionToGarlicParameterCollection(org.system.wsdl.cloud.GarlicParameterCollection collection);

    @Mapping( target = "inputParameters", source = "inputParameters.value") // this instructs MapStruct to use value of the source JAXBElement (for which it has an object factory method) instead of trying to map JAXBElement to JAXBElement.
    org.system.wsdl.legacy.SellGarlicRequest fromCloud(org.system.wsdl.cloud.SellGarlicRequest request);

}

И последнее, но не менее важное: вам нужно определить первый метод garlicParameterCollectionToGarlicParameterCollection, что меня изначально удивило.

Причина: MapStruct либо пытается: 1. найти метод сопоставления (которого нет, если вы опустите этот), либо 2. пытается сгенерировать прямое сопоставление (путем проверки, может ли он найти методы для всех атрибутов в источнике и цель).

Однако MapStruct не может найти прямой случай для этого сопоставления (в принципе, ему нужно применить все другие возможные сопоставления на своем пути (например, все методы в фабрике объектов), а затем попытаться сгенерировать метод сопоставления, как описано в 2, который может быть много комбинаций.Такой функциональности там нет (и, я думаю, это будет интенсивной нагрузкой).

person Sjaak    schedule 03.03.2020
comment
могу подтвердить - работает как шарм! большое спасибо, @Sjaak! - person 62mkv; 04.03.2020