0
votes

I'm currently setting up a MapStruct mapper with the Spring componentModel and so far everything works fine, the individual sub-mappers can be autowired and are injected as expected. However, using decorated mappers leads to the following failure when loading the ApplicationContext:

Error creating bean with name 'exampleMapperImpl': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...ExampleMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value="delegate")}

I exactly followed the MapStruct documentation to decorate my mapper, which is why I'm confused as to why the setup is not working.

@Mapper(componentModel = "spring",
        uses = GenericMapper.class,
        injectionStrategy = InjectionStrategy.CONSTRUCTOR)
@DecoratedWith(ExampleMapperDecorator.class)
public interface ExampleMapper {

    ...

}


public abstract class ExampleMapperDecorator implements ExampleMapper {

    @Autowired
    @Qualifier("delegate")
    private ExampleMapper delegate;

    ...

}

This is my test setup, which works fine for all mappers except decorated mappers:

@SpringBootTest(classes = {
        ExampleMapperImpl.class,
        GenericMapperImpl.class
})
class ExampleMapperTest {

    @Autowired
    private ExampleMapper underTest;

    ...

}

It would be greatly appreciated if someone can point me in the right direction as to why the ApplicationContext can not be loaded and how I can fix the setup. The generated implementation looks as follows:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-05-26T15:44:17+0200",
    comments = "version: 1.4.2.Final, compiler: javac, environment: Java 13.0.2 (Oracle Corporation)"
)
@Component
@Primary
public class ExampleMapperImpl extends ExampleMapperDecorator implements OrderingMapper {

    private final ExampleMapper delegate;

    @Autowired
    public ExampleMapperImpl(@Qualifier("delegate") ExampleMapper delegate) {

        this.delegate = delegate;
    }

    ...
}
1
What annotation is @Qualifier, spring? If it is, so spring want ExampleMapper with name delegate - Grigorii Riabov

1 Answers

2
votes

I finally managed to solve the problem. For decorated mappers, additionally to ExampleMapperImpl, an additional class ExampleMapperImpl_ is generated which has to be included in the SpringBootTest annotation as well.

@SpringBootTest(classes = {
        ExampleMapperImpl.class,
        ExampleMapperImpl_.class,
        GenericMapperImpl.class
})