Filip
Filip

Reputation: 1058

Mapstruct : Use of context in source argument of @Mapping

When using multiple arguments in a @Mapper, it seems that the @Context arguments is unreachable

public interface MyMapper {  
      @Mapping(target="target1", source="arg1.arg") //works
      @Mapping(target="target2", source="arg2") //works
      @Mapping(target="target3", source="arg2.arg") //works
      @Mapping(target="target2", source="context.arg") //NOT WORKING
      public MyTarget convert(Object arg1, Object arg2, @Context Object context);
      
}

I am trying to use and expression="" to work around it, but I can't get it to work.

Any suggestions?

I can see I am not the only one to ever wish this. https://github.com/mapstruct/mapstruct/issues/1280

Thanks

Upvotes: 21

Views: 41406

Answers (5)

Sjaak
Sjaak

Reputation: 4140

To answer your second question:


public interface MyMapper {

  @Mapping(target="target1", source="arg1.arg")
  @Mapping(target="target2", ignore = true ) // leave to after mapping 
  MyTarget convert(Object arg1, @Context Object context);

  @AfterMapping
  default void convert(Object arg1, @MappingTarget MyTarget target, @Context context) {
        target.setTarget2( convert (context) );
  } 

  // if you have multipe mappings, you could address them here
  @Mapping(target="target2", source="context.arg") 
  MyInnerTarget convert(Object arg1, Object context);
}

Upvotes: 8

Peter Butkovic
Peter Butkovic

Reputation: 12139

Alternative way, is to define additional mapping method:

public interface MyMapper {  
      @Mapping(target="target1", source="arg1.arg") 
      @Mapping(target="target3", source="arg2.arg")
      @Mapping(target="target2", source="arg3.arg") 
      MyTarget convert(Object arg1, Object arg2, Object arg3, @Context Object context);

      default MyTarget convert(Object arg1, Object arg2, Object context) {
         return convert(arg1, arg2, context, context);
      }
      
}

Upvotes: 0

nalapoke
nalapoke

Reputation: 510

I ran into the same scenario as I needed a @Context param to be able to pass to a nested mapping function, but also wanted to use it as a source in a @Mapping. I was able to achieve this using expression as follows:

public interface MyMapper {

  @Mapping(target="target1", source="arg1")
  @Mapping(target="target2", source="arg2")
  @Mapping(target="target3", expression="java( contextArg )")
  public MyTarget convert(Object arg1, Object arg2, @Context Object contextArg);

}

Upvotes: 33

Michael Laffargue
Michael Laffargue

Reputation: 10294

Not really clean, but it seems having the same object as source and context allows to use it both ways.

  @Mapping(target="target1", source="arg1.arg")
  @Mapping(target="target2", source="arg2")
  @Mapping(target="target3", source="arg2.arg")
  @Mapping(target="target4", source="contextAsSource.arg") 
  public MyTarget convert(Object arg1, Object arg2, Object contextAsSource, @Context Object context);

Here contextAsSource and context are the same.

Upvotes: 2

Sjaak
Sjaak

Reputation: 4140

By definition a @Context annotated object is not a source. It is context So you can't use it as source in the @Mapping(target="target2", source="context.arg")

Here is a related github issue with official answer: github issue

Upvotes: 5

Related Questions