简体   繁体   中英

How to use MapStruct @Mapping and @Mappings properly?

hi my problem is when i do mvn clean package to build.jar files, i got some error that looked like this:

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /C:/Users/Cactus/Documents/GitHub/Microservice/b2b/b2b-warehouse/src/main/java/com/bit/microservices/b2b/warehouse/mapper/ICategoryBpsjMapper.java:[27,33] No property named "createdDate" exists in source parameter(s). Did you mean "reasonDeleted"?
[ERROR] /C:/Users/Cactus/Documents/GitHub/Microservice/b2b/b2b-warehouse/src/main/java/com/bit/microservices/b2b/warehouse/mapper/ICategoryBpsjMapper.java:[27,33] No property named "createdDate" exists in source parameter(s). Did you mean "reasonDeleted"?
[INFO] 2 errors 
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  16.438 s
[INFO] Finished at: 2020-11-30T10:55:21+07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project b2b-warehouse: Compilation failure: Compilation failure: 
[ERROR] /C:/Users/Cactus/Documents/GitHub/Microservice/b2b/b2b-warehouse/src/main/java/com/bit/microservices/b2b/warehouse/mapper/ICategoryBpsjMapper.java:[27,33] No property named "createdDate" exists in source parameter(s). Did you mean "reasonDeleted"?
[ERROR] /C:/Users/Cactus/Documents/GitHub/Microservice/b2b/b2b-warehouse/src/main/java/com/bit/microservices/b2b/warehouse/mapper/ICategoryBpsjMapper.java:[27,33] No property named "createdDate" exists in source parameter(s). Did you mean "reasonDeleted"?
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

but when i run my project through Boot Dashboard with right click and start my project it run normally. and my api work fine. i do some try.

first trying my code is looked like below, i have mapper file that looked like this:

@Mapper(componentModel = "spring")
public interface ICategoryBpsjMapper {

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

    @Mappings({ 
        @Mapping(target = "createdDate", dateFormat = "dd-MM-yyyy HH:mm:ss"),
        @Mapping(target = "modifiedDate",dateFormat = "dd-MM-yyyy HH:mm:ss")})
    CategoryBpsjResponseDto entityToDto(CategoryBPSJ entity);

    CategoryBPSJ DTOEntity(CategoryBPSJDto dto);
    
    CategoryBPSJ updateEntityFromDto(CategoryBPSJDto dto, @MappingTarget CategoryBPSJ entity);
    
    List<CategoryBpsjResponseDto> entityToDto(List<CategoryBPSJ> entityList);
    
    List<CategoryBPSJ> DTOEnity(List<CategoryBPSJDto> dtoList);

}

and here is my entity:

@Data
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@EqualsAndHashCode(of = "id")
@ToString(of = {"id"})
@Table(name = "msCategoryBPSJ", uniqueConstraints = {
    @UniqueConstraint(name = "uk_categoryBPSJName", columnNames = { "categoryBPSJName" })})
public class CategoryBPSJ extends AuditField implements Serializable {

    private static final long serialVersionUID = 8062436315663828938L;

    @Schema(description = "Id merupakan primary key dan harus disertakan ketika edit, tipe datanya Long", example = "0", required = true)
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Schema(description = "kode kategori pengiriman", example = "BPSJCTH1", required = true)
    @NotBlank(message = "Tidak Boleh Kosong")
    private String categoryBPSCode;

    @Schema(description = "nama kategori pengiriman", example = "Toko/Gudang Tujuan Tutup", required = true)
    @NotBlank(message = "Tidak Boleh Kosong")
    private String categoryBPSJName;
    
}

and here is my extended AuditField class:

@MappedSuperclass
@Data
@Audited
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdDate", "modifiedDate", "isDeleted" }, allowGetters = true, allowSetters = false)
public class AuditField implements Serializable {

    private static final long serialVersionUID = 6025082509703710749L;

    @Schema(description = "Status di hapus", example = "false", required = false)
    public Boolean isDeleted = false;

    @Schema(description = "Alasan di hapus", example = "apa pun alasannya", required = false)
    public String reasonDeleted = "";

    @CreatedDate
    private Date createdDate;
    @LastModifiedDate
    private Date modifiedDate;
    @CreatedBy
    private String createdBy;
    @LastModifiedBy
    private String modifiedBy;

}

and here is my DTO AuditFieldDto class:

@Data
public class CategoryBpsjResponseDto extends AuditFieldDto implements Serializable {

    private static final long serialVersionUID = -422185482845439241L;

    @Schema(description = "Id merupakan primary key dan harus disertakan ketika edit, tipe datanya Long", example = "0", required = true)
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    @Schema(description = "kode kategori pengiriman", example = "BPSJCTH1", required = true)
    @NotBlank(message = "Tidak Boleh Kosong")
    public String categoryBPSCode;

    @Schema(description = "nama kategori pengiriman", example = "Toko/Gudang Tujuan Tutup", required = true)
    @NotBlank(message = "Tidak Boleh Kosong")
    public String categoryBPSJName;

}

and here is my AuditFieldDto class:

@Data
public class AuditFieldDto implements Serializable {

    private static final long serialVersionUID = 3758121148184815303L;

    @Schema(description = "Status di hapus", example = "false", required = false)
    public Boolean isDeleted = false;

    @Schema(description = "Alasan di hapus", example = "apa pun alasannya", required = false)
    public String reasonDeleted = "";

    private String createdDate;
    
    private String modifiedDate;
    
    private String createdBy;
    
    private String modifiedBy;

}

As you can see the AuditField and AuditFieldDto have the same field, but when i do run mvn clean package it give me COMPILATION ERROR like the top of my question mentioned. in the error message it seems to mapstruct cannot find the field properly. Then i try to remove @Mappings and @Mapping annotation line, the build is success. seems fishy.. because when i run with Boot Dashboard is working fine with those annotation.

here is my pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.bit.microservices</groupId>
        <artifactId>b2b</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>b2b-warehouse</artifactId>
    <groupId>com.bit.microservices.b2b</groupId>
    <name>b2b-warehouse</name>
    <description>B2B Warehouse Service</description>
    <version>0.0.1-SNAPSHOT</version>

    <url>http://projects.spring.io/spring-boot/</url>
    <organization>
        <name>Pivotal Software, Inc.</name>
        <url>http://www.spring.io</url>
    </organization>
    <properties>
        <main.basedir>${basedir}/../..</main.basedir>
        <lombok.version>1.18.16</lombok.version>
        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.bit.microservices</groupId>
            <artifactId>model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-envers</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>com.bit.b2b</groupId>
            <artifactId>security</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.4.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.github.classgraph/classgraph -->
        <dependency>
            <groupId>io.github.classgraph</groupId>
            <artifactId>classgraph</artifactId>
            <version>4.8.90</version>
        </dependency>


        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.modelmapper/modelmapper -->
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>2.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>13</source> <!-- depending on your project -->
                    <target>13</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                            <version>2.3.4.RELEASE</version>
                        </path>
                        <!-- other annotation processors -->
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

What i missed in my project if i want to use @Mappings and @Mapping when i build my project to.jar files with mvn clean package ?

i found the culprit here, but i am not sure why and is this the right things to do, since when i do this code, it worked. okay lets start, you can check my mapstruct version at my question, and here is how i fixed this:

first of all, in my AuditField and AuditFieldDto, as you can see i have 2 field that written in " public " data type, at first i write all of my field in public but then my friend come and refer me to make it private, but i accidentally i don't make all of it private, the two fields named public Boolean isDeleted; and public String reasonDeleted; is public, that's why the error go through them, they work fine and the error go to my another line that written in private.

and i just random miserably changed their data type back into public, as you can see there is 4 field that written in private fields, they are

@CreatedDate
private Date createdDate;
@LastModifiedDate
private Date modifiedDate;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String modifiedBy;

so i changed all of them into public in my AuditFieldDto and AuditField class, the complete of code of my AuditField class is looked like this:

@MappedSuperclass
@Data
@Audited
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdDate", "modifiedDate", "isDeleted" }, allowGetters = true, allowSetters = false)
public class AuditField implements Serializable {

    private static final long serialVersionUID = 6025082509703710749L;

    @Schema(description = "Status di hapus", example = "false", required = false)
    public Boolean isDeleted;

    @Schema(description = "Alasan di hapus", example = "apa pun alasannya", required = false)
    public String reasonDeleted;

    @CreatedDate
    public Date createdDate;
    @LastModifiedDate
    public Date modifiedDate;
    @CreatedBy
    public String createdBy;
    @LastModifiedBy
    public String modifiedBy;

}

it's apply the same for my AuditFieldDto class, which is looked like this:

@Data
public class AuditFieldDto implements Serializable {

    private static final long serialVersionUID = 3758121148184815303L;

    @Schema(description = "Status di hapus", example = "false", required = false)
    public Boolean isDeleted = false;

    @Schema(description = "Alasan di hapus", example = "apa pun alasannya", required = false)
    public String reasonDeleted = "";

    public String createdDate;
    
    public String modifiedDate;
    
    public String createdBy;
    
    public String modifiedBy;

}

and when i do run mvn clean package the build is a success. and i ran the,jar files? it working? i guess why?., i stuck for days because of this. then i try to look into the generated files, you can find the generated files in your project located at target/generated-sources/annotations and fine the mapper class file. And here is mine, i only take one example of the generated code, since the other seems doesn't have any problem.

here is what inside the GENERATED FILE (we shouldn't edit this file, just for view):

@Component
public class ICategoryBpsjMapperImpl implements ICategoryBpsjMapper {

    @Override
    public CategoryBpsjResponseDto entityToDto(CategoryBPSJ entity) {
        if ( entity == null ) {
            return null;
        }

        CategoryBpsjResponseDto categoryBpsjResponseDto = new CategoryBpsjResponseDto();

        if ( entity.createdDate != null ) {
            categoryBpsjResponseDto.createdDate = new SimpleDateFormat( "dd-MM-yyyy HH:mm:ss" ).format( entity.createdDate );
        }
        if ( entity.modifiedDate != null ) {
            categoryBpsjResponseDto.modifiedDate = new SimpleDateFormat( "dd-MM-yyyy HH:mm:ss" ).format( entity.modifiedDate );
        }
        categoryBpsjResponseDto.isDeleted = entity.isDeleted;
        categoryBpsjResponseDto.reasonDeleted = entity.reasonDeleted;
        categoryBpsjResponseDto.createdBy = entity.createdBy;
        categoryBpsjResponseDto.modifiedBy = entity.modifiedBy;

        return categoryBpsjResponseDto;
    }

}

you see they access the property without get and set (i mean getter setter), i think this is the culprit that cause my error since when i marked the field as private, and if the code is written like that, they won't can be accessed. for now this is the way i solved it.

if someone have better answer, i will take their answer as accepted answer, if mine code not right or appropriate, waiting for it.

I think you're missing the lombok-mapstruct-binding .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM