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.
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
.
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.
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>
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>
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.
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!
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>
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
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.