1

I found a lot of topics to this but all solutions went into a wrong direction in my eyes.

So... How do i use MapStruct mapping for this case?

abstract class Person:

public abstract class Person implements Serializable{

     private String name;
     private String somethingToIgnore

     //Getter and Setter

}

The normal Mapper doesn´t work:

@Mapper(componentModel = 'cdi')
public interface PersonMapper{

    @Mapping(target = 'somethingToIgnore', ignore = 'true')
    Person toPerson(PersonDTO source);

    @InheritInverseConfiguration
    PersonDTO toPersonDtO(Person source);

}

I am not allowed to map an abstract class. I should use the a factory method. I tried but i simply have no clue how this factoy method should look like...

My attempt:

@Mapper
public interface PersonMapper {

    PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );

    Person toPerson(PersonDTO source);

    PersonDTO toPersonDtO(Person source);
}

@Mapper
public abstract class PersonMapper {

    public static final PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );

    Person toPerson(PersonDTO source);

    PersonDTO toPersonDtO(Person source);
}

What am i missing and doing wrong ? Thanks in advance.

albert
  • 163
  • 2
  • 3
  • 12

1 Answers1

6

MapStruct doesn't know how to map to abstract class, because it cannot instantiate it. I expect that you have some implementation of Person. You need to provide method which will create object of a Person like this:

@Mapper
public interface PersonMapper {

    Person toPerson(PersonDTO source);

    PersonDTO toPersonDtO(Person source);

    default Person createPerson() {
        return new PersonImpl();
    }
}

This way MapStruct will use this method to create Person instance and than map the properties like usual. You can find more about object factories in the documentation.

Tuom
  • 596
  • 5
  • 19
  • I did another horrible mistake. Your Answer is already helping me. I will test it next week and report. ty – albert Mar 27 '20 at 14:28
  • 1
    I had another mistake.. my question wasn really correct but anyway i will mark you answer right cause it is right. – albert Apr 02 '20 at 09:58
  • @Tuom Is there any chance I can have a dto as an argument for the method createPerson() ? – Julien Jul 22 '20 at 08:39
  • 1
    @Julien, one way which comes to my mind is using [`@Context`](https://mapstruct.org/documentation/stable/reference/html/#passing-context). Something like this: `Person toPerson(PersonDTO source, @Context PersonDTO context);`, `default Person createPerson(@Context PersonDTO context)`. – Tuom Jul 22 '20 at 09:04
  • 1
    @Julien, and if you don't want to put the same object as an argument two times, you can overload `toPerson` method like this: `default Person toPerson(PersonDTO source) { return toPerson(source, source); }` – Tuom Jul 22 '20 at 09:06
  • 1
    @Tuom Thank you. I just found a solution by upgrading the mapstruct version and then use \@ObjectFactory default Person toPerson(PersonDTO source) {...} – Julien Jul 22 '20 at 11:17
  • @Julien Nice. I didn't know that it works this way. Good to know. – Tuom Jul 22 '20 at 11:38
  • @Julien Could you put the solution in a comment, please? – Blarzek Sep 13 '21 at 11:33
  • And when you have different subClasses? It's a mapper to json which is a dynamic format and it's widely popularized, it should be able to know it. ModelMapper could do it. – html_programmer Apr 23 '23 at 22:43