MapStruct unable to generate mapper for XJC (JAXB) generated classes

Viewed 71

I'm struggling since a couple of hours trying to get MapStruct generate a valid mapper for JAXB generated classes. The particularity of these classes is that they don't have neither setters nor adders for collections. For example:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "IndividualType", propOrder = {"addressTypes","pensionTypes"})
public class IndividualType 
{
  ...
  @XmlElement(name = "addressType")
  protected List<AddressType> addressTypes;
  @XmlAttribute(name = "firstName", required = true)
  protected String firstName;
  ...
  public List<AddressType> getAddressTypes() 
  {
    if (addressTypes == null) {
        addressTypes = new ArrayList<AddressType>();
    }
    return this.addressTypes;
  }

  public String getFirstName() 
  {
    return firstName;
  }

  public void setFirstName(String value) 
  {
    this.firstName = value;
  }
  ...
}

The class avove have a getter and a setter for attributes (firstName in this example) but for collections (List here) it only has a getter. Hence it's the consumer responsibility to access via getAddressTypes(add (new AddressType(...)).

The MapStruct mapper for such a class is as follows:

@Mapper(collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE, uses = {AddressTypeMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring")
public interface IndividualTypeMapper
{
  IndividualType toIndividualType(IndividualEntity individual);
  @InheritInverseConfiguration
  IndividualEntity fromIndividualType(IndividualType individualType);
}

And the MapStruct generated code is:

@Override
public IndividualEntity fromIndividualType(IndividualType individualType) 
{
  if ( individualType == null )
    return null;
  IndividualEntity individualEntity = new IndividualEntity();
  individualEntity.setFirstName( individualType.getFirstName() );
  ...
  return individualEntity;
}

In the generated code above, only the properties having a setter get initialized despite the usage of the TARGET_IMMUTABLE strategy.

Any suggestions please ? Of course, a simple constructor would perfectly do but, for some reason, people seems to prefer complicated and nonworking solutions to simple working ones and, consequently, I have to use MapStruct :-(

Many thanks in advance.

Marie-France

1 Answers

The reason why it is not working is due to the fact that you are using CollectionMappingStrategy.TARGET_IMMUTABLE. With that you are basically telling MapStruct my collection targets are immutable and will throw an exception if you try to modify the collection returned by the getter.

I would suggest removing the collectionMappingStrategy and see whether it works without it.

Related