16

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?

ElPiter
  • 4,046
  • 9
  • 51
  • 80

12 Answers12

20

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>
João Matos
  • 6,102
  • 5
  • 41
  • 76
18

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>
Damian Szewc
  • 305
  • 2
  • 10
6

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.

Chetan Oswal
  • 430
  • 9
  • 21
  • this answer works for me. when i add a new dependency in POM.xml, should i mvn clean install every time? – Andres Camilo Sierra Hormiga Mar 31 '22 at 03:07
  • 1
    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. – Chetan Oswal Apr 01 '22 at 10:51
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)
Filip
  • 19,269
  • 7
  • 51
  • 60
  • 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 :) – ElPiter May 11 '20 at 07:02
  • 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? – Chetan Oswal Sep 23 '21 at 07:49
  • @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. – Filip Sep 23 '21 at 08:08
  • 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`. – Chetan Oswal Sep 23 '21 at 08:34
3

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

João Matos
  • 6,102
  • 5
  • 41
  • 76
3

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.

Yadav
  • 129
  • 1
  • 11
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 {
João Dias
  • 16,277
  • 6
  • 33
  • 45
0

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

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

Procrastinator
  • 2,526
  • 30
  • 27
  • 36
0

Try enabling annotation processing in your IDE.

  • 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](/help/how-to-answer). – Community May 24 '23 at 10:37
0

I resolved my problem changing verision library

    <dependency>
        <groupId>org.modelmapper</groupId>
        <artifactId>modelmapper</artifactId>
        <version>3.1.1</version>
    </dependency>
Wilson
  • 1
-1

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

b.s
  • 2,409
  • 2
  • 16
  • 26