ModelMapper: mapping an xs:IDREF which is a List of JAXBElement of Object

18 views Asked by At

I am using ModelMapper (3.2.0) to map JAXB Beans to my domain beans.

The schema which is used to generate the JAXB Beans contains xs:IDREF elements, which are represented as List<JAXBElement<Object>> in the JAXB Bean.

But ModelMapper doesn't understand how to map the source bean to my target bean - rather it maps the unmapped source bean into the target. In other words, the List<JAXBElement<Object>> in the source - which is a List<JAXBElement<Dokument>> at runtime - ends up in the target as-is.

(Thexs:IDREF is a feature of XML: one can refer to XML Elements elsewhere in the XML document by means of an XML id that is unique in the document.)

Excerpt of the xsd schema:

<xs:complexType name="IdentitaetUndAufenthaltsstatus">
  <xs:sequence>
     <xs:element name="ausweisart" type="xs:string"/>
     <xs:element name="aufenthaltsstatus" minOccurs="0" type="xeb:Aufenthaltsstatus"/>
     <xs:element name="dokumentIDReferenz"
                 minOccurs="0"
                 maxOccurs="unbounded"
                 type="xs:IDREF"/>
  </xs:sequence>
</xs:complexType>

Here is the generated JAXB bean which matches the schema. Note the type of the attribute dokumentIDReferenz:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "IdentitaetUndAufenthaltsstatus", propOrder = {
    "ausweisart",
    "aufenthaltsstatus",
    "dokumentIDReferenz"
})
public class IdentitaetUndAufenthaltsstatus
    implements Serializable
{

    private final static long serialVersionUID = 100L;
    @XmlElement(required = true)
    @NotNull
    @Valid
    protected CodeAusweisart ausweisart;
    @Valid
    protected Aufenthaltsstatus aufenthaltsstatus;
    @XmlElementRef(name = "dokumentIDReferenz", namespace = "https://portalverbund.d-nrw.de/efa/XEinbuergerung/Version_1_4_0", type = JAXBElement.class, required = false)
    protected List<JAXBElement<Object>> dokumentIDReferenz;

    // ... getters and setters ...
}

What I would like in the target is the following:

public class IdentitaetUndAufenthaltsstatus {
    protected String ausweisart;
    protected Aufenthaltsstatus aufenthaltsstatus;
    protected List<DokumentDto>> dokumentIDReferenz;
    // ...
}

ModelMapper is unhappy with that:

1) Unmapped destination properties found in TypeMap[JAXBElement -> DokumentDto]:

    de.example.commons.xeinbuergerung.domain.DokumentDto.setDokumentnummer()
    de.example.commons.xeinbuergerung.domain.DokumentDto.setAktuelleVersion()
    de.example.commons.xeinbuergerung.domain.DokumentDto.setLetzteVersion()
    de.example.commons.xeinbuergerung.domain.DokumentDto.setDokumentID()
    de.example.commons.xeinbuergerung.domain.DokumentDto.setDokumentTyp()
      
de.example.commons.xeinbuergerung.domain.Dokument.setDokumentRepraesentation()

I am unable to tell ModelMapper how it should map a JAXBElement<Dokument> into a DokumentDTO.

If I rewrite my target bean so that it expects a List<JAXBElement<DokumentDto>>, ModelMapper does map the field, but it fills in the original List<JAXBElement<Dokument>> instead of List<JAXBElement<Dokument>>.

I have tried to apply a Converter, hoping I could use the ModelMapper engine to map inside the converter:

jaxbElementDokumentConverter = new Converter<JAXBElement<Dokument>,
            de.example.commons.xeinbuergerung.domain.DokumentDto>() {
            @Override
            public de.example.commons.xeinbuergerung.domain.DokumentDto convert(MappingContext<JAXBElement<Dokument>,
                de.example.commons.xeinbuergerung.domain.DokumentDto> context) {
                return context.getTypeMap().map(context.getSource());
            }
        };

But it gives me this weird error:

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
Disconnected from the target VM, address: '127.0.0.1:56236', transport: 'socket'

org.modelmapper.MappingException: ModelMapper mapping errors:

1 error

    at org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:386)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:80)
    at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:589)
    at org.modelmapper.ModelMapper.map(ModelMapper.java:422)
    at de.example.xeinbuergerung.v140.business.XEinbuergerungService.getVorgangTransportieren2010(XEinbuergerungService.java:102)
    at de.example.xeinbuergerung.v140.business.XEinbuergerungServiceTest.mapToEingangsnachrichtAndGetDigitalerEinbuergerungsAntrag(XEinbuergerungServiceTest.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit<...>org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:137)
    at org.modelmapper.internal.TypeMapImpl.map(TypeMapImpl.java:186)
    at de.example.xeinbuergerung.v140.mapper.XEinbuergerungModule$3.convert(XEinbuergerungModule.java:54)
    at de.example.xeinbuergerung.v140.mapper.XEinbuergerungModule$3.convert(XEinbuergerungModule.java:50)
    at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:306)
    at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:137)
    at org.modelmapper.internal.TypeMapImpl.map(TypeMapImpl.java:186)
    at de.example.xeinbuergerung.v140.mapper.XEinbuergerungModule$3.convert(XEinbuergerungModule.java:54)
    at de.example.xeinbuergerung.v140.mapper.XEinbuergerungModule$3.convert(XEinbuergerungModule.java:50)
    at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:306)
    at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:137)

I suppose ModelMapper fails to unwrap the JAXBelement automatically. But how to tell it to call JAXBElement.getValue() and then map the result?

0

There are 0 answers