Search code examples
javamapstruct

mapstruct - target payload is subclass, no cast to real type?


While using mapstruct we've got the following (sample) scenario:

Our target class "Zoo" holds some reference of "Animal". An animal can be a "Lion" or an "Elephant". Now we want to set the lion's teethLength or the elephant's trunk lenght depending on some source class's ("ZooMaker") property.

class Zoo {
 Animal animal;
...
class Animal {
 long size;
...
class Lion extends Animal {
 long teethLength;
...
class Elephant extends Animal{
 long trunkLength;
...
class ZooMaker {
String animal;
long lenght;

What we wanna do is to create the Animal in Zoo dynamically using mapstruct. But, if we use a FactoryClass

public class PayloadFactory {

    public Animal createAnimal() {
      return new Lion();    
    }
}

for this Mapper class:

@Mapper
public abstract class AnimalMapper {

    @Mapping(target = "animal.teethLength", source = "length")
    public abstract Zoo toZoo(ZooMaker zooMaker);
...

we get an error like: Error:(10, 9) java: Unknown property "teethLength" in type Animal for target name "animal.teethLength". Did you mean "animal.size"?

Even using Lion as Factory's return type or using an ObjectFactory like

@ObjectFactory
    public Lion createLion() {
        return new Lion();
    }

causes the same problem? Any ideas how to solve that type conversion issue?


Solution

  • MapStruct is an annotation processor. This means that it uses only information available at compile time and not runtime.

    In your example Zoo has the property animal of type Animal, so MapStruct can only map to properties known about Animal during compilation time. You'll have to do something else to map the type specific properties.

    You can use @AfterMapping where you can do instanceOf checks, etc.