Omar B.
Omar B.

Reputation: 501

mapstruct using mapper inside another return null in test

I m using mapstruct to generate mappers. when I see in the generated code it is autowired the Mymapper in MainMapper but when debug it is showing that myMapper is null. When I change in the generated code

@Autowired MyMapper myMapper

with :

MyMapper myMapper=Mappers.getMaper(MyMapper.class)

, it is working but this is not what I want. I want it to be auto-generated like expected from the framwork. nb : MainMapper uses MyMapper , and MyMapper uses Mapper2

mainMapper:

@Mapper(componentModel = "spring", 
    unmappedTargetPolicy = ReportingPolicy.IGNORE, 
    uses = MyMapper.class ,
    nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL)
public interface MainMapper {

    @Mappings({ @Mapping(target = "year", source = "Period.year") })
    Resource toResource(MyObject myObject);

    @Mapping(target = "Period.year", source = "year")
    MyObject toModel(Resource resource);
}

MyMapper :

@Mapper(componentModel = "spring", 
    unmappedTargetPolicy = ReportingPolicy.IGNORE,
    uses = Mapper2.class,
    nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL)
public interface MyMapper {

    RequestResource toResource(Request request);

    Request toModel(RequestResource requestResource);
}

any help is appreciated .

Upvotes: 5

Views: 6220

Answers (3)

Philipp Maurer
Philipp Maurer

Reputation: 2505

I also encountered the problem with mappers that use MappingConstants.ComponentModel.SPRING.

To solve it, I removed the componentModel from the @Mapper annotation and added my own Bean definition for the mapper.

@Mapper
public interface MyMapper {
  ...
}

In my config package i added the class MapperConfiguration:

@Configuration
public class MapperConfiguration {
  @Bean
  public MyMapper myMapper() {
    return Mappers.getMapper(MyMapper.class);
  }
}

Like that, the mappers can still be autowired anywhere without changing any additional code, but the mappers themself work in the tests as well.

Upvotes: 1

Sara Lily
Sara Lily

Reputation: 43

I, too, was using the spring component model, and found this SO thread while troubleshooting. What worked for me was that in my test class, I needed to add these fields rather than reference the mapper class directly in my test method.

@Autowired
private final MyCustomMapper pMapper = Mappers.getMapper(MyCustomMapper.class);

Upvotes: 0

Matthew K.
Matthew K.

Reputation: 81

I've encountered this issue myself. I was able to get around it by using the default component model. Here was my situation:

  1. I was using componentModel = "spring".
  2. I was trying to utilize my Mappers in a separate Spring component.
  3. My @Autowired fields referencing the Mappers were giving NullPointerException's when running tests.

If this sounds like what is happening to you, you have to use componentModel = "default". I wanted to use the Spring component model; but, after an hour of banging my head against the wall, I decided to try the default component model.

After changing my Mappers to the default component model and replacing the @Autowired fields, I no longer received that dreaded NullPointerException!!

Working Code:

@Component
public class Mapper implements MapperTranslator<Output, Input> {
    private final MappingVisitor mappingVisitor = Mappers.getMapper(MappingVisitor.class);
    private final MappingDefault mappingDefault = Mappers.getMapper(MappingDefault.class);

    @Override
    public Output translate(Input source) {
        if (source instanceof InputType1) {
            return ((InputType1)source).acceptAndMap(mappingVisitor);
        }
        else if (source instanceof InputType2) {
            return ((InputType2)source).acceptAndMap(mappingVisitor);
        }

        // default
        return mappingDefault.translate(source);
    }
}

Upvotes: 3

Related Questions