MapStruct - Cannot find implementation
Asked Answered
M

17

23

Using latest Springboot and MapStruct versions and building with Maven, I am trying to implement the "Start Here" example given in the official MapStruct site

My code is even simpler:

pom.xml

<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>

(...)

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>

(...)

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <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>

Car.java

public class Car {

    private String model;

    // Constructors, setters and getters...

}

CarDto.java

public class CarDto {

    private String theModel;

    // Constructors, setters and getters...

}

CarMapper.java interface

@Mapper
public interface CarMapper {

    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    @Mapping(source = "model", target = "theModel")
    CarDto carToCarDto(Car car);
}

Main application

@SpringBootApplication
public class MappertestApplication {

    public static void main(String[] args) {
        SpringApplication.run(MappertestApplication.class, args);

        Car c = new Car("Volkswagen");

        CarDto cdto = CarMapper.INSTANCE.carToCarDto(c);

    }

}

All the code is in this public repo: https://github.com/pgbonino/mappertest

When running, I am getting this error:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.gallelloit.mappertest.MappertestApplication.main(MappertestApplication.java:14)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for com.gallelloit.mappertest.CarMapper
    at org.mapstruct.factory.Mappers.getMapper(Mappers.java:61)
    at com.gallelloit.mappertest.CarMapper.<clinit>(CarMapper.java:10)
    ... 1 more
Caused by: java.lang.ClassNotFoundException: Cannot find implementation for com.gallelloit.mappertest.CarMapper
    at org.mapstruct.factory.Mappers.getMapper(Mappers.java:75)
    at org.mapstruct.factory.Mappers.getMapper(Mappers.java:58)
    ... 2 more

I found this issue in the official MapStruct project, which seems to describe the same issue. However, in that case some custom configuration was being performed (custom name of the implementation). In my case everything is left as default.

Any idea?

Muzzle answered 10/5, 2020 at 10:31 Comment(1)
Did you find any solution?Sn
G
27

I added mapstruct processor dependency and it worked for me

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.3.1.Final</version>
</dependency>
Granicus answered 5/4, 2021 at 18:7 Comment(2)
This is in addition to the mapstruct class one imports.Jackscrew
This suggestion works also in the case when deploying over server env where you are not able to run mvn clean install before running the application.Sedimentary
N
23

Although my scenario is not the same as yours, it did result in the same error - hence I am posting this answer to help others that made the same mistake as I did and end up here looking for a solution.

I was importing the maven dependency:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>

But forgot to add the annotation processor path in the maven compiler plugin:

    <annotationProcessorPaths>
        <path>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
        </path>
    </annotationProcessorPaths>
Neuberger answered 25/10, 2020 at 12:44 Comment(0)
S
7

My issue was resolved when I run the given command on my project -

mvn clean install

And then I noticed implementation files being generated. I guess generating implementation required execution of maven command.

Sn answered 23/9, 2021 at 9:8 Comment(2)
this answer works for me. when i add a new dependency in POM.xml, should i mvn clean install every time?Biographical
mvn clean install tells Maven to do the clean phase in each module before running the install phase for each module. What this does is clear any compiled files you have, making sure that you're really compiling each module from scratch. But POM changes are regarding dependencies, so I don't think it is necessary.Sn
M
6

I also faced similar issue when I was using lombok with mapstruct, Its a known issue. What worked for me was to add the lombok dependency in the annotationProcessorPaths.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
    <source>${java.version}</source>
    <target>${java.version}</target>
    <annotationProcessorPaths>
        <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
        </path>
        <!-- This is needed when using Lombok 1.18.16 and above -->
        <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>0.2.0</version>
        </path>
        <!-- Mapstruct should follow the lombok path(s) -->
        <path>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
        </path>
    </annotationProcessorPaths>
</configuration>

please refer this answer for complete detail.

Marsh answered 6/5, 2022 at 9:3 Comment(0)
N
4

I was reproducing the exact same error because I forgot to add @Mapper to the mapper interface:

@Mapper // <-- missing
public interface MyMapper {

It's a trivial mistake but it is easy to miss

Neuberger answered 4/2, 2022 at 17:29 Comment(1)
It is indeed trivial but you helped at least one person... me! Thanks for posting.Sombrero
S
3

You will need to make sure that your IDE is properly configured to invoke the annotation processors. Have a look at the IDE Setup.

Looking at the project you provided the code should not even compile. The MapStruct processor will emit compilation errors due to:

  • No default constructor in CarDto
  • Property model does not exist in Car (there is only marca)
  • Property theModel does not exist in CarDto (there is only laMarca)
Socialization answered 10/5, 2020 at 13:48 Comment(4)
Thanks for your answer. In some moment yesterday I pushed some changes just to translate marca to model (Spanish to English). But I don't think there was a compile error for that reason. There wasn't either for the absence of default constructor. Anyway, I'll add it. What I finally did was to give a Spring strategy configuring the Mapper as a bean in the context and injecting it in the client. I wonder what do I do in stackoverflow when I made a question that does not make sense any more to me. Thank you very much for your answer and help, anyway :)Muzzle
Your answer does no help as it is not giving any proper reason for the issue. The error states that Cannot find implementation, which according to me I guess means that the Interface was not implemented by MapStruct. Why did MapStruct not implement the provided interface even after providing proper annotation?Sn
@Chetan, the answer didn't help the user since there was another problem. However, that problem is usually manifested when the annotation processor did not run, i.e. the IDE has not been configured correctly.Socialization
I clicked on the link provided by you for the IDE setup. I followed all the steps required for Eclipse IDE. Yet it did not help me. I'm still getting the error stating Cannot find implementation.Sn
R
1

I encountered the exact same issue today with the error "ClassNotFoundException: Cannot find implementation ..... "

I was able to add the mapstruct dependency...

<dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
</dependency>

as well as the annotationProcessorPaths in the pom.xml plugins...

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

but forgot to add the mapstruct processor as a dependency, which fixed the issue for me.

    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
Ruin answered 24/2, 2024 at 5:54 Comment(0)
E
0

It's proper to use @Mapper(componentModel = "spring")

over your Mapper class, so you will be able to insatiate in using injection, Like this:

@Autowired
private CarMapper carMapper;

for checking whether everything is ok or not, you can check your mapper implementation after compile. It should have @component on it. Like this

@Component
public class CarMapperImpl implements CarMapper {
Elenaelenchus answered 21/12, 2021 at 15:50 Comment(0)
M
0

I checked my plugin version and app (both source and target) version and set them equally. and it's worked

Mima answered 1/1, 2023 at 13:7 Comment(0)
3
0

the INSTANCE variable that you have created on CarMapper interface, cannot be there, try to move that instance variable into the class where you are converting the objects (in you example the INSTANCE should be placed to MappertestApplication class) like so: private static final CarMapper carMapper = Mappers.getMapper(CarMapper.class); , for me this worked fine

3d answered 9/2, 2023 at 18:8 Comment(0)
V
0

Try enabling annotation processing in your IDE.

Vesical answered 24/5, 2023 at 9:51 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Kaciekacy
A
0

I resolved my problem changing verision library

    <dependency>
        <groupId>org.modelmapper</groupId>
        <artifactId>modelmapper</artifactId>
        <version>3.1.1</version>
    </dependency>
Ardel answered 25/8, 2023 at 12:52 Comment(1)
That's not MapStruct, it's an entirely different library.Microseism
A
0

Had the same issue, worked for me by adding the (componentModel = "spring") with @Model while creating the Mapper interface. It creates the implementation class with @Component annotation without which it could not detect the implement class.

Affiliate answered 28/9, 2023 at 20:45 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Kaciekacy
K
0

While using MapStruct in your Maven project, you need to enable annotation processors specific to your IDE so that it can recognize and process the annotations. For example, in Eclipse, if you press ctrl+shift+t and your Impl class of the mapper does not show up ( in your case, CarMapperImpl ) it means that it was not properly processed. Basically, if the annotation was interpreted correctly the implementation version of the code will show up in your build/temp folder of sorts.

For example:

import javax.annotation.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-10-19T11:00:00-0600",
    comments = "version: 1.5.5.Final, compiler: Eclipse JDT (IDE) 1.4.100.v20220318-0906, environment: Java 17.0.3 (Eclipse Adoptium)"
)
public class CarMapperImpl implements CarMapper {

    @Override
    public CarDto carToCarDto(Car car) {
        if ( car == null ) {
            return null;
        }

        CarDto carDto = new CarDto();

        carDto.setManufacturer( car.getMake() );
        carDto.setSeatCount( car.getNumberOfSeats() );

        return carDto;
    }

    @Override
    public PersonDto personToPersonDto(Person person) {
        if ( person == null ) {
            return null;
        }

        PersonDto personDto = new PersonDto();

        personDto.setFullName( person.getName() );

        return personDto;
    }
}

This shows up in my project’s folder: C:\...\project-name\.apt_generated\com\project\configuration\service

Here’s documentation from the Mapstruct website, depending on which IDE you are using, there are a few options:

Eclipse

If you are working with a Maven project, then make sure you have the latest version of the m2e-apt plugin installed, which picks up and applies the annotation processor settings automatically.

For best results, add the following to the pom.xml:

<properties>  
   <!-- automatically run annotation processors within the incremental compilation -->  
   <m2e.apt.activation>jdt_apt</m2e.apt.activation>
</properties>

https://mapstruct.org/documentation/ide-support/#maven-integration

IntelliJ

For example, if you use the way of Maven configuration that is proposed in our documentation using annotationProcessorPaths in the maven-compiler-plugin, then you need to configure IntelliJ manually until the feature request IDEA-150621 is implemented. An alternative is to add the mapstruct-processor as a project dependency with <optional>true</optional> in your pom.xml, which should then be picked up automatically again.****

https://mapstruct.org/documentation/ide-support/#maven-integration-1

Kiel answered 23/10, 2023 at 15:17 Comment(1)
using spring 3.2.3 , adding mapstruct-processor solved it for me. the annotationProcessorPaths was not allowedEvanesce
O
0

The same issue. Added the mapstruct into dependency but didn't add the annotation processor path.

Solution for Gradle:

implementation 'org.mapstruct:mapstruct:1.5.5.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
Outland answered 19/7, 2024 at 7:24 Comment(0)
A
0

After updating the maven , runing maven clean install solved the issue for me

Algo answered 30/7, 2024 at 16:55 Comment(0)
S
-1

Try configuring the MapStruct Eclipse Plugin in the eclipse IDE to resolve the issue.

Soosoochow answered 12/7, 2021 at 14:13 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.