enjoey
enjoey

Reputation: 59

MapStruct: error occur when using Target field type as Object

When I tried for MapStruct to convert type to Object, it didn't work well.

Target Class

public static class Filterable implements Name,Disassemble,Note{
    String name;
    String disassemble;
    Object note; // <-- Object type

    ... getter setter
}

Mapping abstract class

@Mappings({
        @Mapping(source = "s",target = "name"),
        @Mapping(source = "s",target = "note"), // <--
        @Mapping(source = "s",target = "disassemble", qualifiedByName = "toDisassemble")
})
public abstract UiDto.Option.Filterable toUiFilterableOption(String s);

Result when I compile

@Override
public Filterable toUiFilterableOption(String s) {
    if ( s == null ) {
        return null;
    }

    Filterable filterable = new Filterable();

    filterable.setName( s );
    filterable.setNote( toUiFilterableOption( s ) ); // <-- hear is problem
    filterable.setDisassemble( Converter.toDisassemble( s ) );

    return filterable;
}

How could I solve this problem?

Upvotes: 1

Views: 1006

Answers (1)

Eugene Khyst
Eugene Khyst

Reputation: 10315

MapStruct tries to find a method that maps from the source class to the target class: Object map(String source).

As far as the target class is Object, the method annotated with @Mapping itself has suitable method signature: Filterable toUiFilterableOption(String s). Because Filterable just like any other class in Java is an Object. And the method argument also is a String.

To solve this issue use qualifiedByName in @Mapping and add a mapping method annotated with @Named:

@Mapper
public abstract class TestMapper {

  public static final TestMapper TEST_MAPPER = Mappers.getMapper(TestMapper.class);

  @Mapping(source = "s", target = "name")
  @Mapping(source = "s", target = "note", qualifiedByName = "toNote")
  @Mapping(source = "s", target = "disassemble", qualifiedByName = "toDisassemble")
  public abstract Filterable toUiFilterableOption(String s);

  @Named("toNote")
  protected Object toNote(String s) {
    return s.toUpperCase(); //just as an example
  }

  //...
}

The generated code looks like this:

public class TestMapperImpl extends TestMapper {

  @Override
  public Filterable toUiFilterableOption(String s) {
    if (s == null) {
      return null;
    }

    Filterable filterable = new Filterable();

    filterable.setName(s);
    filterable.setNote(toNote(s));
    filterable.setDisassemble(toDisassemble(s));

    return filterable;
  }
}

Upvotes: 1

Related Questions