web-dev-qa-db-fra.com

MapStruct nécessite la classe Impl

J'ai cours suivants:

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);
}

Entité:

@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;
    }
}

Et méthode de service de printemps classe où j'utilise ce mappage:

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

    return DeviceTokensMapper.INSTANCE.toDeviceTokensDTO(newDevice);
}

Lorsque je lance la méthode ci-dessus, je vois l'exception suivante:

ERREUR [dispatcherServlet] :? - Servlet.service () pour servlet [dispatcherServlet] dans le contexte du chemin [] a levé une exception [Handler le traitement a échoué; exception imbriquée est Java.lang.ExceptionInInitializerError] avec la cause première Java.lang.ClassNotFoundException: dto.DeviceTokensMapperImpl

Alors pourquoi le mappeur nécessite une classe d'implémentation? Pourriez-vous s'il vous plaît conseiller quelqu'un? Merci.

9
Iurii

MapStruct génère du code au moment de la compilation et l'appel à Mappers.getMapper(DeviceTokensMapper.class); cherchera l'implémentation générée de l'interface du mappeur. Pour une raison quelconque, il semble manquer à votre unité de déploiement (WAR, etc.).

Btw. lorsque vous utilisez Spring comme conteneur DI, vous pouvez utiliser @Mapper(componentModel="spring") et vous pourrez obtenir des instances de mappeur via l'injection de dépendance au lieu d'utiliser la fabrique Mappers.

11
Gunnar

Avez-vous les deux bibliothèques mapstruct-processeur-xx et mapstruct-xx incluses dans votre projet?

J'ai eu le même problème et j'ai réalisé que j'avais oublié d'inclure mapstruct-processeur-xx.

9
dplavcic

si vous utilisez maven, vous devez ajouter la dépendance mapstruct-processeur comme suit:

<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>
7
Lê văn Huy

Utilisez-vous Maven? Si oui, alors vous avez probablement manqué la configuration de mapstruct-processeur sous le plugin maven compiler.

La configuration correcte est la suivante:

<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>
2
Omtara

Dans mon cas, j'avais enveloppé <plugin> dans les balises <pluginManagement> pour contourner un bogue Eclipse (Mars) comme suit

<pluginManagement>
 <plugin> ... </plugin> 
</pluginManagement>

Supprimer les balises <pluginManagement> a corrigé le problème.

1
sh87

J'ai rencontré le même problème dans mon projet avec Gradle. Et je remplace le build.gradel De

compile 'org.mapstruct:mapstruct:1.2.0.CR2'

à

compile 'org.mapstruct:mapstruct-jdk8:1.1.0.Final'
compile 'org.mapstruct:mapstruct-processor:1.1.0.Final'

Ensuite, sh construire propre et construire. Ça fonctionne maintenant!

1
Wentao Wan

Si vous utilisez Project lombok avec mapstruct, vous devrez configurer les deux sous le plug-in maven compiler, car ils génèrent tous deux le code source au moment de la compilation.

        <plugins>
            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${Java.version}</source>
                    <target>${Java.version}</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>
                </configuration>
            </plugin>
0
Rahul Bhooteshwar

Dans votre build.gradle ajouter 

compile group: 'org.mapstruct',name: 'mapstruct-jdk8',version: 1.2.0.Final



annotationProcessor group: 'org.mapstruct',name: 'mapstruct-processor',version: 1.2.0.Final

Activer le traitement des annotations dans vos paramètres

Bonus: ajout du plugin intellij pour mapstruct

0
FBH

J'ai rencontré ce problème car je n'avais pas exécuté ./gradlew clean build (gradlew.bat pour Windows) après avoir créé/modifié la classe de mappeur ou les classes associées.

En outre, quelque chose que j'ai trouvé utile était que ./gradlew clean build -x test fonctionnait, mais n'exécutait pas tous vos tests, ce qui était beaucoup dans mon cas.

0
James