Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapStruct requires Impl class

I have next classes:

Mapper

public interface DeviceTokensMapper {

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

    @Mappings({
            @Mapping(source = "tokenName", target = "tokenName"),
            @Mapping(source = "userOsType", target = "osType"),
    })

    DeviceTokensDTO toDeviceTokensDTO(DeviceTokens deviceTokens);
}

Entity:

@Entity
public class DeviceTokens {

    @Id
    @Column(name="token_name", nullable = false)
    private String tokenName;

    @Column(name = "os", nullable = false)
    @Enumerated
    private UserOSType userOsType;

    public DeviceTokens() {}

    public DeviceTokens(String tokenName, UserOSType userOSType) {
        this.tokenName = tokenName;
        this.userOsType = userOSType;
    }

    public String getTokenName() {
        return tokenName;
    }

    public void setTokenName(String tokenName) {
        this.tokenName = tokenName;
    }

    public UserOSType getUserOsType() {
        return userOsType;
    }

    public void setUserOsType(UserOSType userOsType) {
        this.userOsType = userOsType;
    }
}

DTO:

public class DeviceTokensDTO {

    private String tokenName;

    private UserOSType osType;

    public DeviceTokensDTO() {}

    public DeviceTokensDTO(String tokenName, UserOSType osType) {
        this.tokenName = tokenName;
        this.osType = osType;
    }

    public UserOSType getOsType() {
        return osType;
    }

    public void setOsType(UserOSType osType) {
        this.osType = osType;
    }

    public String getTokenName() {
        return tokenName;
    }

    public void setTokenName(String tokenName) {
        this.tokenName = tokenName;
    }
}

And method from spring service class where I use this mapping:

@Transactional
public DeviceTokensDTO storeToken(String tokenId, UserOSType userOsType) {
    DeviceTokens deviceTokens = new DeviceTokens(tokenId, userOsType);
    DeviceTokens newDevice = deviceTokensRepository.save(deviceTokens);

    return DeviceTokensMapper.INSTANCE.toDeviceTokensDTO(newDevice);
}

When I run above method I see next exception:

ERROR [dispatcherServlet]:? - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.ExceptionInInitializerError] with root cause java.lang.ClassNotFoundException: dto.DeviceTokensMapperImpl

So why mapper require implementation class? Could please someone advise? Thanks.

like image 835
Iurii Avatar asked Aug 10 '15 13:08

Iurii


People also ask

How does MapStruct generate implementation?

MapStruct is an open-source Java-based code generator which creates code for mapping implementations. It uses annotation-processing to generate mapper class implementations during compilation and greatly reduces the amount of boilerplate code which would regularly be written by hand.

Does MapStruct work with Java 11?

Yes, it works on a Java 11 / Spring Boot 2 project at work, and we use Mapstruct without issues.

How does MapStruct work in spring boot?

Mapstruct is an annotation-based code generator that simplifies the mapping implementations between the java beans. The code is generated via the plain method invocation and thus it is fast, type-safe, and easy to understand.

What is MapStruct in Java?

What is MapStruct? MapStruct is a code generator tool that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach. The generated mapping code uses plain method invocations and thus is fast, type-safe, and easy to understand.


4 Answers

if you use maven, you need to add mapstruct-processor dependency as follows:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.2.0.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.2.0.Final</version>
</dependency>
like image 82
Lê văn Huy Avatar answered Oct 12 '22 20:10

Lê văn Huy


MapStruct generates code at compile time, and the call to Mappers.getMapper(DeviceTokensMapper.class); will look for the generated implementation of the mapper interface. For some reason it seems to be missing in your deployment unit (WAR etc.).

Btw. when working with Spring as your DI container, you can use @Mapper(componentModel="spring") and you will be able to obtain mapper instances via dependency injection instead of using the Mappers factory.

like image 39
Gunnar Avatar answered Oct 12 '22 19:10

Gunnar


Do you have both mapstruct-processor-xx and mapstruct-xx libraries included in your project?

I had the same problem and I realized that I forgot to include mapstruct-processor-xx.

like image 13
daliborp Avatar answered Oct 12 '22 18:10

daliborp


Are you using Maven? If yes, then most probably you have missed the mapstruct-processor configuration under the maven compiler plugin.

The proper configuration is as follows:

<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.6</source> <!-- or higher, depending on your project -->
                <target>1.6</target> <!-- or higher, depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
like image 6
Omtara Avatar answered Oct 12 '22 19:10

Omtara