Reputation: 593
I downloaded application from this source https://github.com/springframeworkguru/spring5-mvc-rest/tree/vendor-api And I have a problem with MapStruct.
@Mapper
public interface CategoryMapper {
CategoryMapper INSTANCE = Mappers.getMapper(CategoryMapper.class);
CategoryDTO categoryToCategoryDTO(Category category);
}
@Data
public class CategoryDTO {
private Long id;
private String name;
}
domain class:
@Data
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Service class:
@Service
public class CategoryServiceImpl implements CategoryService {
private final CategoryMapper categoryMapper;
private final CategoryRepository categoryRepository;
public CategoryServiceImpl(CategoryMapper categoryMapper, CategoryRepository categoryRepository) {
this.categoryMapper = categoryMapper;
this.categoryRepository = categoryRepository;
}
}
And in pom.xml dependency, I paste only two::
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<org.mapstruct.version>1.2.0.CR2</org.mapstruct.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
And plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
Description:
Parameter 0 of constructor in
guru.springfamework.services.CategoryServiceImpl required a bean of type 'guru.springfamework.api.v1.mapper.CategoryMapper' that could not be found.
Action:
Consider defining a bean of type 'guru.springfamework.api.v1.mapper.CategoryMapper' in your configuration.
I think that in my Intellij annotation @Mapper don't create a bean for mapper. I didn't change code from John GitHub. Any idea? I tried to change path generated source to target but this doesn't help Thanks for help.
Upvotes: 38
Views: 76404
Reputation: 91
Please, add in your mapper class.
@Mapper(componentModel = "spring")
So, instead of @Mapper
add @Mapper(componentModel = "spring")
Upvotes: 0
Reputation: 21
Use this annotation on the mapper class and do not add a plugin as this annotation will create a bean.
@Mapper(componentModel = "spring")
Upvotes: 1
Reputation: 29
@ComponentScan("guru.springfamework.api.v1.mapper")
Add this under a config class or MainClass
Upvotes: 0
Reputation: 59
I resolved this by first installing MAVEN_HOME in environment variables then do a mvn clean install. I've found out that I was running my project in eclipse and then Intellij without installing maven.
Upvotes: 2
Reputation: 10560
For me it was the missing componentModel
in the @Mapper
annotation on the interface / abstract class.
So this didn't work:
@Mapper
But this worked:
@Mapper(componentModel = "spring")
Upvotes: 1
Reputation: 817
It worked for me when I added the annotationProcessor for both dependencies.
annotationProcessor group: 'org.mapstruct', name: 'mapstruct', version: '1.4.2.Final'
implementation group: 'org.mapstruct', name: 'mapstruct', version: '1.4.2.Final'
annotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.4.2.Final'
implementation group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.4.2.Final'
Also, made sure using
@Mapper(componentModel = "spring")
public interface MyMapper {
Upvotes: 3
Reputation: 1060
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
Added these both dependencies solved my problem, processor needed for creating beans (https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor), if the red line on the constructor bothers you (it does not bother compiler) @Autowired(required = false)
add this.
Upvotes: 7
Reputation: 748
In your Mapper class, use @Mapper(componentModel = "spring")
instead of just @Mapper
and run mvn clean install
, that's it! you're done!
and the alternative to it, is to define compiler arguments in plugin of pom.xml like below!
<plugin>
<configuration>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
Upvotes: 8
Reputation: 352
This was working for me:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
componentModel = "spring"
parameter in @MapStruct
annotation.mvn clean
on your project.I don't think you really need the following compiler argument declaration in your POM, because ``componentModel = "spring"` should be enough.
<plugin>
<configuration>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
I've taken these code snippets from a microservice application project generated by JHipster.
Upvotes: 2
Reputation: 102
You first have to use the Mapper like this
To use mappers as beans and use **@Autowired**,
just declare mappers as @Mapper(componentModel = "spring").
Then just inject it wherever you need this.
Also every time you create a new mapper class always remember to do mvn clean install.
It will create the implementation file of you mapper interface in the target folder and then you can run your Spring project.
Upvotes: 0
Reputation: 580
You have to enable your annotation processor in you IntelliJ from,
Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors and click on checkbox of Enable annotation processing.
Upvotes: 0
Reputation: 937
In order to use mappers as beans and use @Autowired
, just declare mappers as @Mapper(componentModel = "spring")
. Then just inject it wherever you need this.
Upvotes: 13
Reputation: 71
I had the same problem. In Gradle I solved it by adding new dependency:
compileOnly('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
And all necessary dependencies should be as follows:
compile('org.mapstruct:mapstruct:1.3.0.Beta2')
compileOnly('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
annotationProcessor('org.mapstruct:mapstruct-processor:1.3.0.Beta2')
Upvotes: 6
Reputation: 599
I resolved the error by doing
Also add this to your pom
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
Upvotes: 48
Reputation: 2071
The issue is that using the @Mapper
construct will generate a class without
the @Component annotation by default.
You are probably not using Maven to compile your project. Make sure to run a Maven clean
and install
, or pass in the compiler arguments mapstruct.defaultComponentModel=spring
manually.
Since you are using:
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
This will tell MapStruct
to generate a Spring Component
.
If you check your compiled target class, and open it up in a decompiler (if your IDE supports this), there should be a CategoryMapperImpl
that is annotated with @Component.
Upvotes: 13
Reputation: 21461
I presume that this is not working in IntelliJ only. There is a known issue, where IntelliJ actually does not pick up the annotation processors from the maven compiler annotationProcessorPaths
(see IDEA-150621 for more info).
On top of that the examples in the linked repository are against MapStruct best practices. When the spring
componentModel
is used then Mappers.getMapper
should never be used. The reason is that the factory will not be able to construct the mapper correctly as it should be constructed via spring. Also the compiler argument mapstruct.defaultComponentModel
can break integration with IDE, as it is not being picked up (you would need to set it in the IntelliJ settings as well)
Upvotes: 2