Giter VIP home page Giter VIP logo

mapstruct-examples's Introduction

MapStruct - Java bean mappings, the easy way!

Latest Stable Version Latest Version License

Build Status Coverage Status

What is MapStruct?

MapStruct is a Java annotation processor for the generation of type-safe and performant mappers for Java bean classes. It saves you from writing mapping code by hand, which is a tedious and error-prone task. The generator comes with sensible defaults and many built-in type conversions, but it steps out of your way when it comes to configuring or implementing special behavior.

Compared to mapping frameworks working at runtime, MapStruct offers the following advantages:

  • Fast execution by using plain method invocations instead of reflection
  • Compile-time type safety. Only objects and attributes mapping to each other can be mapped, so there's no accidental mapping of an order entity into a customer DTO, etc.
  • Self-contained code—no runtime dependencies
  • Clear error reports at build time if:
    • mappings are incomplete (not all target properties are mapped)
    • mappings are incorrect (cannot find a proper mapping method or type conversion)
  • Easily debuggable mapping code (or editable by hand—e.g. in case of a bug in the generator)

To create a mapping between two types, declare a mapper interface like this:

@Mapper
public interface CarMapper {

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

    @Mapping(target = "seatCount", source = "numberOfSeats")
    CarDto carToCarDto(Car car);
}

At compile time MapStruct will generate an implementation of this interface. The generated implementation uses plain Java method invocations for mapping between source and target objects, i.e. no reflection is involved. By default, properties are mapped if they have the same name in source and target, but you can control this and many other aspects using @Mapping and a handful of other annotations.

Requirements

MapStruct requires Java 1.8 or later.

Using MapStruct

MapStruct works in command line builds (plain javac, via Maven, Gradle, Ant, etc.) and IDEs.

For Eclipse, a dedicated plug-in is in development (see https://github.com/mapstruct/mapstruct-eclipse). It goes beyond what's possible with an annotation processor, providing content assist for annotation attributes, quick fixes and more.

For IntelliJ the plug-in is available within the IntelliJ marketplace (see https://plugins.jetbrains.com/plugin/10036-mapstruct-support).

Maven

For Maven-based projects, add the following to your POM file in order to use MapStruct (the dependencies are available at Maven Central):

...
<properties>
    <org.mapstruct.version>1.6.0</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.13.0</version>
            <configuration>
                <source>17</source>
                <target>17</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

Gradle

For Gradle, you need something along the following lines:

plugins {
    ...
    id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}

dependencies {
    ...
    implementation 'org.mapstruct:mapstruct:1.6.0'

    annotationProcessor 'org.mapstruct:mapstruct-processor:1.6.0'
    testAnnotationProcessor 'org.mapstruct:mapstruct-processor:1.6.0' // if you are using mapstruct in test code
}
...

If you don't work with a dependency management tool, you can obtain a distribution bundle from Releases page.

Documentation and getting help

To learn more about MapStruct, refer to the project homepage. The reference documentation covers all provided functionality in detail. If you need help please ask it in the Discussions.

Building from Source

MapStruct uses Maven for its build. Java 11 is required for building MapStruct from source. To build the complete project, run

./mvnw clean install

from the root of the project directory. To skip the distribution module, run

./mvnw clean install -DskipDistribution=true

Importing into IDE

MapStruct uses the gem annotation processor to generate mapping gems for its own annotations. Therefore, for seamless integration within an IDE annotation processing needs to be enabled.

IntelliJ

Make sure that you have at least IntelliJ 2018.2.x (needed since support for annotationProcessors from the maven-compiler-plugin is from that version). Enable annotation processing in IntelliJ (Build, Execution, Deployment -> Compiler -> Annotation Processors)

Eclipse

Make sure that you have the m2e_apt plugin installed.

Links

Licensing

MapStruct is licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.

mapstruct-examples's People

Contributors

agudian avatar chris922 avatar dependabot[bot] avatar dgruntz avatar eiswind avatar filiphr avatar gunnarmorling avatar hongji3354 avatar kevcodez avatar nancheung avatar patsancu avatar rahuljoshitaulia avatar sjaakd avatar thst71 avatar torstenwerner avatar xenteros avatar xqdd avatar yishanhe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mapstruct-examples's Issues

kotlin example - java.lang.Long does not have an accessible parameterless constructor

Hi, I'm trying to define a custom mapping methods between different types.

I have adjusted the PersonDto.kt and Person.kt on the mapstruct kotlin-example so that the phonenumber is stored once as a string and once as a long.

This is how my mapper looks like:

@Mapper
interface PersonConverter {

    @Mapping(source = "phoneNumber", target = "phone", qualifiedByName = ["PhoneToLong"])
    fun convertToDto(person: Person): PersonDto

    @Mapping(source = "phone", target = "phoneNumber", qualifiedByName = ["PhoneToString"] )
    fun convertToModel(personDto: PersonDto): Person

    @Named("PhoneToLong")
    fun phoneToLong(obj: String?): Long? {
        return 123L
    }

    @Named("PhoneToString")
    fun phoneToString(obj: Long?): String {
        return "123"
    }
}

I'm not sure if this is a kapt or Mapstruct problem. But the compiler throws this error:
[ERROR] C:\dev\source\workspace\mapstruct-examples\mapstruct-kotlin\target\kaptStubs\compile\org\mapstruct\example\kotlin\converter\PersonConverter.java:21: error: java.lang.Long does not have an accessible parameterless constructor. [ERROR] public abstract java.lang.Long phoneToLong(@org.jetbrains.annotations.Nullable()

Could not find artifact lombok-mapstruct-binding 0.20 in Maven central

Getting this error on mvn clean install after I added lombok-mapstruct-binding to my pom.xml:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project my-service: Resolution of annotationProcessorPath dependencies failed: Missing:
[ERROR] ----------
[ERROR] 1) org.projectlombok:lombok-mapstruct-binding:jar:0.20
[ERROR]
[ERROR]   Try downloading the file manually from the project website.
[ERROR]
[ERROR]   Then, install it using the command: 
[ERROR]       mvn install:install-file -DgroupId=org.projectlombok -DartifactId=lombok-mapstruct-binding -Dversion=0.20 -Dpackaging=jar -Dfile=/path/to/file
[ERROR]
[ERROR]   Alternatively, if you host your own repository you can deploy the file there: 
[ERROR]       mvn deploy:deploy-file -DgroupId=org.projectlombok -DartifactId=lombok-mapstruct-binding -Dversion=0.20 -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
[ERROR]
[ERROR]   Path to dependency: 
[ERROR]         1) org.mapstruct:mapstruct-processor:jar:1.4.1.Final
[ERROR]         2) org.projectlombok:lombok-mapstruct-binding:jar:0.20
[ERROR]
[ERROR] ----------
[ERROR] 1 required artifact is missing.
[ERROR]
[ERROR] for artifact: 
[ERROR]   org.mapstruct:mapstruct-processor:jar:1.4.1.Final
[ERROR]
[ERROR] from the specified remote repositories:
[ERROR]   central (https://repo.maven.apache.org/maven2, releases=true, snapshots=false)
[ERROR] Path to dependency: 
[ERROR]         1) org.mapstruct:mapstruct-processor:jar:1.4.1.Final
[ERROR]
[ERROR]
[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/MojoExecutionException

My pom.xml is as below

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.chunhoong</groupId>
    <artifactId>replica</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>replica</name>
    <description>replica</description>
    <properties>
        <java.version>11</java.version>
        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
        <org.projectlombok.version>1.18.16</org.projectlombok.version>
        <lombok-mapstruct-binding.version>0.20</lombok-mapstruct-binding.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <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>${org.projectlombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>${lombok-mapstruct-binding.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Update mapstruct-lombok example

Hello,

Lombok add a breaking changes with mapstruct since 1.18.16 :

https://projectlombok.org/changelog

BREAKING CHANGE: mapstruct users should now add a dependency to lombok-mapstruct-binding. This solves compiling modules with lombok (and mapstruct).

we should update the project like :

<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <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>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${org.projectlombok.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok-mapstruct-binding</artifactId>
                                <version>${lombok-mapstruct-binding.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

Mapstruct does not map record parameters

Hi,
I have a simple mapping to do (target class is generated from jsonschema, but in another maven module):

public record Codec(String codecString, String privateData) {
    public Codec {
        notBlank(codecString);
        notBlank(privateData);
    }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
    "codecString",
    "privateData"
})
public class CodecJson {

    /**
     * 
     * (Required)
     * 
     */
    @JsonProperty("codecString")
    @NotNull
    private String codecString;
    /**
     * 
     * (Required)
     * 
     */
    @JsonProperty("privateData")
    @NotNull
    private String privateData;
    @JsonIgnore
    @Valid
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     * 
     * (Required)
     * 
     */
    @JsonProperty("codecString")
    public String getCodecString() {
        return codecString;
    }

    /**
     * 
     * (Required)
     * 
     */
    @JsonProperty("codecString")
    public void setCodecString(String codecString) {
        this.codecString = codecString;
    }

    public CodecJson withCodecString(String codecString) {
        this.codecString = codecString;
        return this;
    }
// remaining getters/setters are similar

When I make such mapping:

@Mapper(componentModel = "spring")
public interface PackagerParametersMapper {
    InitSegmentParametersJson map(InitSegmentParameters initSegmentParameters);

    CodecJson map(Codec codec);

I get:

@Override
    public CodecJson map(Codec codec) {
        if ( codec == null ) {
            return null;
        }

        CodecJson codecJson = new CodecJson();

        return codecJson;
    }

Expected behavior is to add both field values to returning codecJson.
Am I correct?
Mapstruct 1.4.2.

Quarkus Gradle example?

I tried converting the mapstruct-quarkus example directly to gradle.

https://github.com/danelowe/mapstruct-quarkus-gradle

Running ./gradlew quarkusDev results in an error when trying to access the server (http://localhost:8080/)

Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.mapstruct.example.quarkus.mapper.PersonMapper and qualifiers [@Default]
        - java member: org.mapstruct.example.quarkus.PersonResource#personMapper
        - declared on CLASS bean [types=[org.mapstruct.example.quarkus.PersonResource, java.lang.Object], qualifiers=[@Default, @Any], target=org.mapstruct.example.quarkus.PersonResource]
        at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:487)
        at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:362)
        at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:226)
        ... 14 more

Similarly cannot build due to same error.

I have no idea if I'm using it wrong, or if there is a bug with Mapstruct, or with Quarkus, or if some workaround is necessary to get it working with Gradle.

I would like to use Mapstruct in a project with Quarkus/Gradle/Kotlin, but kapt seems to break Quarkus CDI, and I can't get mapstruct to run in Quarkus CDI with Gradle

idea : Cannot find implementation for org.mapstruct.example.kotlin.converter.PersonConverter

i use this example, but the idea runtime error :

class PersonConverterTest {

@Test
fun testConvertToDto() {
    val converter = Mappers.getMapper(PersonConverter::class.java)

    val person = Person("Samuel", "Jackson", "0123 334466", LocalDate.of(1948, 12, 21))

    val personDto = converter.convertToDto(person)
    assertThat(personDto).isNotNull()
    assertThat(personDto.firstName).isEqualTo("Samuel")
    assertThat(personDto.lastName).isEqualTo("Jackson")
    assertThat(personDto.phone).isEqualTo("0123 334466")
    assertThat(personDto.birthdate).isEqualTo(LocalDate.of(1948, 12, 21))
}

@Test
fun testConvertToModel() {
    val converter = Mappers.getMapper(PersonConverter::class.java)

    val personDto = PersonDto("Samuel", "Jackson", "0123 334466", LocalDate.of(1948, 12, 21))

    val person = converter.convertToModel(personDto)
    assertThat(person).isNotNull()
    assertThat(person.firstName).isEqualTo("Samuel")
    assertThat(person.lastName).isEqualTo("Jackson")
    assertThat(person.phoneNumber).isEqualTo("0123 334466")
    assertThat(person.birthdate).isEqualTo(LocalDate.of(1948, 12, 21))
}

}

java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for org.mapstruct.example.kotlin.converter.PersonConverter

at org.mapstruct.factory.Mappers.getMapper(Mappers.java:61)
at org.mapstruct.example.kotlin.converter.PersonConverterTest.testConvertToDto(PersonConverterTest.kt:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Caused by: java.lang.ClassNotFoundException: Cannot find implementation for org.mapstruct.example.kotlin.converter.PersonConverter
at org.mapstruct.factory.Mappers.getMapper(Mappers.java:75)
at org.mapstruct.factory.Mappers.getMapper(Mappers.java:58)
... 23 more

mapstruct-mapper-repo example bug

in testMapObjectToObject add:
carDto.setSetCount(7);
and
Assert.assertEquals(5, carDto.getSeatCount());
test will fail

Also, despite the annotation
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
on CarMapper:
in testMapObjectToObject
change
Car car = new Car("Morris", 5, CarType.SPORTS);
to
Car car = new Car("Morris", 5, null);
and add
carDto.setType("anything");
and
Assert.assertEquals("anything", carDto.getType());
test will fail

For the latter, I tried to make sense of your recent change of "don't overwrite target if source is null" pull request, but there was so much discussion on what the annotation should be, I couldn't easily figure out the end result. ;o)

I also can't find a test case in this git repo that covers it. Can you point me to it, if there is one?
Thanks!

Add example for SolrDocument + Mapstruct

It would be nice to have an example that shows how to use SolrDocument with Mapstruct.

I was trying to use MapStruct with SolrDocument and couldn't find a comprehensive example that could guide me . I was facing below issue during compiling:
Can't generate mapping method from iterable type to non-iterable type.
Reason is SolrDocument implements Iterable interface and Target DTOs doesn't .
So i came up with below solution to deal with this.
Source Class
SolrDocument
Here SolrDocument internally has Map<String,Object> _fields;

Destination Class:
`public class ItemDTO {

private String id;
private String displayName;
private String availability;
private String price;

//getter
//setter
}
}`

Error : Can't generate mapping method from iterable type to non-iterable type.

Solution:
Created SolrResponseWrapper around SolrDocument like below:
`public class SolrResponseWrapper {

private SolrDocument document;

public SolrResponseWrapper(SolrDocument document) {
this.document = document;
}

public String get(String key) {
return this.document.get(key).toString();
}
}`

Now Mapper is defined below for SolResponseWrapper to ItemDTO.

`@Mapper
public interface ItemMapper {
ItemMapper INSTANCE = Mappers.getMapper(ItemMapper);

@mappings({
@mapping(expression = "java(record.get("product_id"))", target = "id"),
@mapping(expression = "java(record.get("display_name"))", target = "displayName"),
@mapping(expression = "java(record.get("availability"))", target = "availability"),
@mapping(expression = "java(record.get("price"))", target = "price")
})
ItemDTO convertToItemDTO(SolrResponseWrapper record);
}`

If you think this is a good addition, please let me know. I will raise PR to have it included as an example.

Mapstruct issue on Eclipse (1.4.2.Final)

I have an issue to setup Mapstruct on eclipse (Version: 2021-03 (4.19.0), Build id: 20210312-0638) with following gradle setting:

implementation "org.mapstruct:mapstruct:$mapstructVersion"
annotationProcessor "org.mapstruct:mapstruct-processor:$mapstructVersion"
annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0"
annotationProcessor "org.projectlombok:lombok"
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

It seems it doesn't generate .factorypath when I tried to run gradle tasks: cleanEclipse and eclipse
It works and everything is fine if I add follow gradle plugin:

plugins {
id 'java'
id 'eclipse-wtp'
id 'org.springframework.boot' version '2.3.12.RELEASE'
id 'io.franzbecker.gradle-lombok' version '4.0.0'
id 'net.ltgt.apt-eclipse' version '0.21'
}

But there is a drawback that this net.ltgt.apt-eclipse doesn't work on gradle 7.1.1 and I need to use the older version gradle-6.9
However developers like me prefer to install MapStruct Eclipse Plugin and it's supposed to make things work around without require developers to add net.ltgt.apt-eclipse

I look forward to this potential fix.

Regards.

Mapping annotation field name is different from entity field name

mapstruct version: 1.4.1.Final
jdk version: 8

public class Driver {
    private String sourceName;
    private String pathName;
}

public class DriverDTO {
    private String szName;
    private String pName;
}

@Mapper
public interface DriverMapper {
    @Mapping(source = "sourceName", target = "szName")
    @Mapping(source = "parentName", target = "pName")
    DriverDTO driverToDriverDTO(Driver driver);
}

when I compile these class, I get a compile error.

Error:(26, 12) java: Unknown property "pName" in result type DriverDTO. Did you mean "PName"?

but I make target = "pName" -> target = "PName" , I get a correct result.

Copy Nested list with conditional mapping

I have a list of Address object with ID,Street name,City, PostalCode
and list of Contact object with ID, Street,City and Phone
Can i copy Street name and City alone
from List to List

based on ID matching ?

Address Object already has ID and Postalcode.

Example to map List<MyObject> to MyObject

I am trying to map a list of bean to a single elected bean (first one in the list)

I am following an example where you map List to Integer

class Image {
  private String path;
  private String name;
  ...
}

class dtoImage {
  private String path;
  private String name;
  ...
}

class ProductModel {
   private List<Image> images;
   ...
}

class ProductDto {
  private dtoImage image;
  ...
}

#Mapper class

@Mapper(uses = { ProductDescriptionMapper.class,ImageIterableUtil.class })
public interface ProductMapper {
  
  ProductMapper MAPPER = Mappers.getMapper( ProductMapper.class );

  @Mappings({
    @Mapping(source = "manufacturer.code", target = "manufacturer"),
    @Mapping(source = "sku", target = "uniqueId"),
    @Mapping(source = "images", target = "image", qualifiedBy = FirstElement.class )
  })
  ProductDto toProduct(ProductModel product);

}

Getting this error

[ERROR] /product-simplification/src/main/java/com/shop/mapper/ProductMapper.java:[25,5] Can't map property "java.util.List<com.shop.model.catalog.product.Image> images" to "com.shop.catalog.product.ImageDto image". Consider to declare/implement a mapping method: "com.shop.catalog.product.model.ImageDto map(java.util.List<com.shop.model.catalog.product.Image> value)".

Thanks for your input on this

Add example for Immutables+MapStruct

Would be nice to have an example that shows the usage of MapStruct with Immutables.

I was trying to use MapStruct with Immutables and couldn't find a comprehensive example or guide that could walk users through this set up. Would be nice to have this example.

I created a sample Spring REST service that uses MapStruct and Immutables to post my question on StackOverflow.

If you think this is a good addition, with some help and guidance I am willing to improve this to have it included as an example.

Add example of using Gradle Kotlin DSL

Would it be possible to add an example for Gradle Kotlin DSL to compile Kotlin Interfaces?

I have been trying to get it to work for a couple of hours now, but I don't have enough experience to make sense of all the difference resources I found online.

The most significant resources I found so far:

CycleAvoidingMappingContext uses Lombok Builder instead of TargetType

Hi,

I have a bidirectional mapping Father <--> Children and I decided to try to use this CycleAvoidingMappingContext from the example:
https://github.com/mapstruct/mapstruct-examples/blob/master/mapstruct-mapping-with-cycles/src/main/java/org/mapstruct/example/mapper/CycleAvoidingMappingContext.java

I have a builder class in my Entity and DTO from Lombok but I believe the problem seems to happen also without it.

When the MapperStruct processor created the Mapper Implementation the context object is trying to use the Entity/DTO Builder as the actual targetType which caused compilation error.

I have created a sample project that reproduces the problem. Please have a look.

mapstruct-mapping-with-cycles.zip

I tried to introduce generics to the CycleAvoidingMappingContext to eliminate this problem but it didn't help? When I introduced generics and removed the @TargetType Class<T> targetType from getMappedInstance method the Mapper implementation no longer is added to the Mapper implementation.

public class CycleAvoidingMappingContext<S, T> {
    private final Map<S, T> knownInstances = new IdentityHashMap<S, T>();

    @BeforeMapping
    public T getMappedInstance(S source) {
        return knownInstances.get( source );
    }

    @BeforeMapping
    public void storeMappedInstance(S source, @MappingTarget T target) {
        knownInstances.put( source, target );
    }
}
public class EmployeeMapperImpl implements EmployeeMapper {

    @Override
    public Employee toEmployee(EmployeeDto employeeDto, CycleAvoidingMappingContext<EmployeeDto, Employee> context) {
        if ( employeeDto == null ) {
            return null;
        }

        EmployeeBuilder employee = Employee.builder();

        employee.name( employeeDto.getEmployeeName() );
        employee.reportsTo( toEmployee( employeeDto.getReportsTo(), context ) );
        employee.team( employeeDtoListToEmployeeList( employeeDto.getTeam(), context ) );

        return employee.build();
    }

    @Override
    public EmployeeDto fromEmployee(Employee employee, CycleAvoidingMappingContext<Employee, EmployeeDto> context) {
        if ( employee == null ) {
            return null;
        }

        EmployeeDtoBuilder employeeDto = EmployeeDto.builder();

        employeeDto.employeeName( employee.getName() );
        employeeDto.reportsTo( fromEmployee( employee.getReportsTo(), context ) );
        employeeDto.team( employeeListToEmployeeDtoList( employee.getTeam(), context ) );

        return employeeDto.build();
    }

    protected List<Employee> employeeDtoListToEmployeeList(List<EmployeeDto> list, CycleAvoidingMappingContext<EmployeeDto, Employee> context) {
        if ( list == null ) {
            return null;
        }

        List<Employee> list1 = new ArrayList<Employee>( list.size() );
        for ( EmployeeDto employeeDto : list ) {
            list1.add( toEmployee( employeeDto, context ) );
        }

        return list1;
    }

    protected List<EmployeeDto> employeeListToEmployeeDtoList(List<Employee> list, CycleAvoidingMappingContext<Employee, EmployeeDto> context) {
        if ( list == null ) {
            return null;
        }

        List<EmployeeDto> list1 = new ArrayList<EmployeeDto>( list.size() );
        for ( Employee employee : list ) {
            list1.add( fromEmployee( employee, context ) );
        }

        return list1;
    }
}

Any Ideas?

Regards,

Flávio Oliva

checkstyle fails on mapper generated implementations

I love this mapstruct. I am using the 1.4.0.beta version . So , checkstyle is failing in autogenerated mapper impl

<module name="WhitespaceAfter">

Description: When mapstruct is generating the source code, it doesn't follow the checkstyle rules .

Solution: Although, I have suppressed the error by marking mapper implementation folder checks none but can someone take it on?

Map record from another maven module throw an NPE

  • Context:

I have a domain maven module that holds all my business logic (entities are defined by records) and another maven module for all stuff about infrastructure where I use mapstruct to map record to DTO classes.

  • Problem:

When I clean compile mapstruct processor throw an NPE (cf. the full stacktrace). After some investigations I found the problem location. It's due to RECORD_COMPONENT_ACCESSOR_METHOD.invoke statement above that returns a null value. This method is supposed to return the related accessor of the given record field.

After some tests, mappers compilation succeed (no problem to retrieve accessor for record field) when records belong to the same maven module but, when they belong to another installed maven module in my local repo it's failed as I described.

  • Environment:

OS: macOs v11.2.3
Java: v16 (adopt-openjdk-16)
Mapstruct: tested for v1.5.0.Beta1 & v1.4.2.Final

  • Full stacktrace:
java.lang.NullPointerException: Cannot invoke "com.sun.tools.javac.code.Symbol.getEnclosingElement()" because "sym" is null
	at jdk.compiler/com.sun.tools.javac.model.JavacTypes.asMemberOf(JavacTypes.java:298)
	at org.mapstruct.ap.internal.util.AbstractTypeUtilsDecorator.asMemberOf(AbstractTypeUtilsDecorator.java:129)
	at org.mapstruct.ap.internal.util.Filters.getWithinContext(Filters.java:147)
	at org.mapstruct.ap.internal.util.Filters.getReturnType(Filters.java:118)
	at org.mapstruct.ap.internal.util.Filters.recordAccessorsIn(Filters.java:104)
	at org.mapstruct.ap.internal.model.common.Type.getPropertyReadAccessors(Type.java:593)
	at org.mapstruct.ap.internal.model.BeanMappingMethod$Builder.build(BeanMappingMethod.java:246)
	at org.mapstruct.ap.internal.processor.MapperCreationProcessor.getMappingMethods(MapperCreationProcessor.java:416)
	at org.mapstruct.ap.internal.processor.MapperCreationProcessor.getMapper(MapperCreationProcessor.java:179)
	at org.mapstruct.ap.internal.processor.MapperCreationProcessor.process(MapperCreationProcessor.java:133)
	at org.mapstruct.ap.internal.processor.MapperCreationProcessor.process(MapperCreationProcessor.java:81)
	at org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:338)
	at org.mapstruct.ap.MappingProcessor.processMapperTypeElement(MappingProcessor.java:318)
	at org.mapstruct.ap.MappingProcessor.processMapperElements(MappingProcessor.java:267)
	at org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:166)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1025)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:940)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1269)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1384)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1261)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:935)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
	at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:126)
	at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:174)
	at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:1129)
	at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:188)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
	at org.codehaus.classworlds.Launcher.main(Launcher.java:47)

Exception running mapstruct-examples-lombok

I'm trying to run the lombok example using the unit test class SourceTargetMapperTest but I get the following exception:

`java.lang.ExceptionInInitializerError
at com.mycompany.mapper.SourceTargetMapperTest.testMapping(SourceTargetMapperTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for com.mycompany.mapper.SourceTargetMapper
at org.mapstruct.factory.Mappers.getMapper(Mappers.java:79)
at com.mycompany.mapper.SourceTargetMapper.(SourceTargetMapper.java:31)
... 24 more
Caused by: java.lang.ClassNotFoundException: Cannot find implementation for com.mycompany.mapper.SourceTargetMapper
at org.mapstruct.factory.Mappers.getMapper(Mappers.java:93)
at org.mapstruct.factory.Mappers.getMapper(Mappers.java:76)
... 25 more

`

I'm using Eclipse STS 3.8.3.

Mapper array to List example

Hi,

Would be nice to have an example that shows the usage of MapStruct with array (like int[] ) to immutable list with specific add and addAll (like in protobuf).

example:
proto file

    message UserDTO {
        string id = 1;
        string email = 2;
        repeated PermissionDTO permissions = 3;
        repeated DepartmentDTO main_departments  = 4;
        repeated DepartmentDTO departments  = 5;
    }

java file

 public class User {

     private String id;
     private String email;
     private Permission[] permissions = new Permission[0];
     private List<Department> mainDepartments = new ArrayList<>();
     private List<Department> departments = new ArrayList<>();

     public String getId() {
         return id;
     }

     public void setId(String id) {
         this.id = id;
     }

     public String getEmail() {
         return email;
     }

     public void setEmail(String email) {
         this.email = email;
     }

     public Permission[] getPermissions() {
         return permissions;
     }

     public void setPermissions(Permission[] permissions) {
         this.permissions = permissions;
     }

public List<Department> getDepartments() {
	return departments;
}

public void setDepartments(List<Department> departments) {
	this.departments = departments;
}

public List<Department> getMainDepartments() {
	return mainDepartments;
}

public void setMainDepartments(List<Department> mainDepartments) {
	this.mainDepartments = mainDepartments;
}
 }

Mapper

 @Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
         nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
 public interface UserMapper {

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


     @Mapping(source = "permissions", target = "permissionsList")
     @Mapping(source = "mainDepartments", target = "mainDepartmentsList")
     @Mapping(source = "departments", target = "departmentsList")
     UserDTO map(User user);
 }

Error:
Can't map property "Permission[] permissions" to "PermissionDTO permissionsList".

### Desired solution:

 public class UserMapperImpl implements UserMapper {

     @Override
     public UserDTO map(User user) {
         if ( user == null ) {
             return null;
         }

         Builder userDTO = UserDTO.newBuilder();

         if ( user.getPermissions() != null ) {
             for ( Permission permission : user.getPermissions() ) {
                 userDTO.addPermissions( map( permission ) );
             }
         }
    
        ...

         return userDTO.build();
     }
 }

or

 public class UserMapperImpl implements UserMapper {

     @Override
     public UserDTO map(User user) {
         if ( user == null ) {
             return null;
         }

         Builder userDTO = UserDTO.newBuilder();

         if ( user.getPermissions() != null ) {
             userDTO.addAllPermissions( map( user.getPermissions()) );
         }
    
        ...

         return userDTO.build();
     }
 }

Is it possible to do this with actual release?

Using it in tests

Add some tests.

Regarding this problem I had -> tbroyer/gradle-apt-plugin#73

Just notice that if you try to use this combo in tests, you need to use testApt in the build.gradle dependencies instead of apt.

Kotin class java.lang.ClassNotFoundException

I built example project Kotlin Gradle but it showed error "class not found exception"


Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for org.mapstruct.example.kotlin.converter.PersonConverter
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:61)
	at org.mapstruct.example.kotlin.MainKt.main(Main.kt:10)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.ClassNotFoundException: Cannot find implementation for org.mapstruct.example.kotlin.converter.PersonConverter
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:75)
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:58)
	... 6 more

Exception on mapstruct-lombok & mapstruct-on-gradle with gradle plugin net.ltgt.apt

Exception on mapstruct-lombok & mapstruct-on-gradle with gradle plugin net.ltgt.apt

java.lang.ExceptionInInitializerError
	at com.mycompany.mapper.SourceTargetMapperTest.testMapping(SourceTargetMapperTest.java:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for com.mycompany.mapper.SourceTargetMapper
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:79)
	at com.mycompany.mapper.SourceTargetMapper.<clinit>(SourceTargetMapper.java:31)
	... 23 more
Caused by: java.lang.ClassNotFoundException: Cannot find implementation for com.mycompany.mapper.SourceTargetMapper
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:93)
	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:76)
	... 24 more


Process finished with exit code 255

Ignore fluent API methods

Hi,
I use mapstruct to replace an very old ugly data model (non generic collections, arrays and so on) with a JAXB generated model.
This work nice, but if I do generate additional fluent API methods (like withXxx) to my pojos I get a warning/error: "Unmapped target properties"
I know I can it ignore with
@mapping(target="xxx", ignore=true)
But if I understand right I have to do this with every property. :(

Is there a possibility to ignore all this methods with a shared config or annotation?
Or ist it possible to use an wildcard on the target field like: target="with*"?

Kotlin data constructors suggestion

Thank you for your mapper. It is very useful for apps.

I am using kotlin data classes with val params:
data class Person (
var id: Int?=null
val name: String
val documentId: String
...
)
I can't use empty constructor due to notNull notation.
I could be wrong, at present time mapper demands empty constructors.

Is it possible to add mapper that uses args constructor?

Thank you,
Irina

MapStruct Map to Bean with reference fields not working

I have a requirement to convert Map to bean using MapStruct

Employee.java
public class Employee{
private String id;
private String name;
private Department department
}

Department.java
public class Employee{
private String id;
private String name;
}

I want to convert below map to Employee instance

Map<String,String> map = new HashMap();
map.put("id", "1234");
map.put("name", "Mark");
map.put("did", "32222"); //Department Id
map.put("dname", "Test");// Depart name

How can we convert above map to Employee. How to set the fields of Department in Employee instance?

Can someone Please hep how to solve the above issue. Is there a support for the above scenario in MapStruct latest versions?

ClassNotFound org.mapstruct.factory.Mappers in Docker Image

I am using Mapstruct (with lombok), and Mapstruct fails when I dockerize the app after calling an endpoint which uses MapStruct to map a DTO to entity.

Caused by: java.lang.ClassNotFoundException: org.mapstruct.factory.Mappers at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:435) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)

Everything works well when I run the app locally, but dockerizing the app makes Mapstruct fail.

Dockerfile:

FROM openjdk:15-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Dependencies and docker plugin in build.gradle:


docker {
    dependsOn build as Task
    name "${project.group}/${jar.baseName}"
    files bootJar.archivePath
    buildArgs(['JAR_FILE': "${bootJar.archiveName}"])
}

dependencies {
    .....

    compileOnly 'org.mapstruct:mapstruct:1.4.1.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.1.Final'
}

Is there something I am missing or I need to do additionally to have Impl classes in the docker? I am using palantir/gradle-docker for the gradle-docker plugin.

Can't generate mapping method from non-iterable type to iterable type.

Your example shows mapping for a source having a list and target having a simple object, i get a exception as "Can't generate mapping method from non-iterable type to iterable type." where the source is having a simple object and the target contains the list of object.

more details on the mappings:

Can't map property "packagexxx.OrganisationNameType name" to "java.util.List<packageyyy.NameType> name". Consider to declare/implement a mapping method: "java.util.List<packageyyy.NameType> map(packagexxx.OrganisationNameType value)".

Do you have a solution for it?

Not able to map Immutable object to Immutable Object using Builder

I have followed this link to test Builder support.
http://mapstruct.org/documentation/dev/reference/html/#mapping-with-builders

But it's not working as expected
Person.java

public class Person {

  private final String name;

  protected Person(Person.Builder builder) {
    this.name = builder.name;
  }

  public static Person.Builder builder() {
    return new Person.Builder();
  }

  public static class Builder {

    private String name;

    public Builder name(String name) {
      this.name = name;
      return this;
    }

    public Person create() {
      return new Person( this );
    }
  }

  @Override
  public String toString() {
    return "Person [" + "name='" + name + '\'' + ']';
  }
}

PersonDto.java

public class PersonDto {
  
  private final String name;

  protected PersonDto(PersonDto.Builder builder) {
    this.name = builder.name;
  }

  public static PersonDto.Builder builder() {
    return new PersonDto.Builder();
  }

  public static class Builder {

    private String name;

    public Builder name(String name) {
      this.name = name;
      return this;
    }

    public PersonDto create() {
      return new PersonDto( this );
    }
  }

  @Override
  public String toString() {
    return "PersonDto [" + "name='" + name + '\'' + ']';
  }
}

PersonMapper.java

@Mapper
public interface PersonMapper {

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

  PersonDto map(Person person);
}

build.gradle

apply plugin: "net.ltgt.apt"

dependencies {
  implementation "org.mapstruct:mapstruct:1.3.0.Final"

  annotationProcessor "org.mapstruct:mapstruct-processor:1.3.0.Final"
}

gradle Build Output:

warning: [options] bootstrap class path not set in conjunction with -source 1.7
/home/subramaniam/Projects/map-struct-test/src/main/java/com/mapstructtest/model/PersonMapper.java:22: warning: Unmapped target property: "name".
  PersonDto map(Person person);
            ^
1 warning

AutoGenerated Class:

public class PersonMapperImpl implements PersonMapper {
  public PersonMapperImpl() {
  }

  public PersonDto map(Person person) {
    if (person == null) {
      return null;
    } else {
      Builder personDto = PersonDto.builder();
      return personDto.create();
    }
  }
}

Wondering why name field is not mapped???

Issue when data class has multiple constructors

@KotlinBuilder
data class Company(
    val id: UUID = UUID.randomUUID(),
    val name: String,
    val source: String,
) {
    lateinit var headquarter: Branch
    lateinit var branches: List<Branch>

    constructor(
        id: UUID,
        name: String,
        source: String,
    ) : this(id, platformId, cnpj, name, source) {
        this.headquarter = headquarter
        this.branches = branches
    }

Generated builder:

public final class CompanyBuilder {
  private UUID id;
  private String name;
  private String source;
  private UUID id;
  private String name;
  private String source;
  private Branch headquarter;
  private List<Branch> branches;

  public CompanyBuilder setId(UUID id) {
    this.id = id;
    return this;
  }
  public CompanyBuilder setName(String name) {
    this.name = name;
    return this;
  }
  public CompanyBuilder setSource(String source) {
    this.source = source;
    return this;
  }
  public CompanyBuilder setId(UUID id) {
    this.id = id;
    return this;
  }
  public CompanyBuilder setName(String name) {
    this.name = name;
    return this;
  }
  public CompanyBuilder setSource(String source) {
    this.source = source;
    return this;
  }
  public CompanyBuilder setHeadquarter(Branch headquarter) {
    this.headquarter = headquarter;
    return this;
  }
  public CompanyBuilder setBranches(List<Branch> branches) {
    this.branches = branches;
    return this;
  }
  public Company create() {
    return new Company(id, name, source, id, name, source, headquarter, branches);
  }

  public static CompanyBuilder builder() {
    return new CompanyBuilder();
  }
}

It duplicates the attributes and fails to build.

JDK11 Couldn't find type java.sql.Date

There is an error when use strict jpms module declaration :
Couldn't find type java.sql.Date.

see issue #69

it is reproduced when strict jpms module (module-info.java) is present in the project

String to List 0th index map

I want to store source string to target list 0th index of object propertie
class A{
B b1
}
class B{
String testString
}
"test" -->A[0].b1.testString

``
@mapping(source = "documentCategory", target = "containerCategory.get(0).document.documentCategoryType")

Add example mapping from Map to property

According to the question from StackOverflow, there is need for example mapping from Map to it's property.

For example, I have a Map<String, Object> and I'd like to map just ip and server from that map into proper fields in my DTO.

Converter Class Not Found

hello, i've been trying to use mapstruct for a really long time, stumbled across your repo but still i am having issues. Impl class is being created but convertor and other classes could not be resolved. i also tried mvn clean install but still nothing. I am using intellij 2021.2.2, here is my pom.xml file, also attaching the directory structure of project and the generated sources.

`

4.0.0

org.springframework.boot
spring-boot-starter-parent
2.5.3


com.hu
fyp-impl-backend
0.0.1-SNAPSHOT
fyp-impl-backend
fyp-impl-backend

<java.version>1.8</java.version>
<kotlin.version>1.5.21</kotlin.version>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>



org.springframework.boot
spring-boot-starter-data-jpa


org.springframework.boot
spring-boot-starter-web


com.fasterxml.jackson.module
jackson-module-kotlin


io.projectreactor.kotlin
reactor-kotlin-extensions


org.jetbrains.kotlin
kotlin-reflect


org.jetbrains.kotlin
kotlin-stdlib-jdk8


org.jetbrains.kotlinx
kotlinx-coroutines-reactor

    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk</artifactId>
        <version>1.12.70</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>jakarta.validation</groupId>
        <artifactId>jakarta.validation-api</artifactId>
        <version>2.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.18.2</version>
    </dependency>

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.5.10</version>
    </dependency>

    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>

<build>
    <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>kapt</id>
                    <goals>
                        <goal>kapt</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>src/main/kotlin</sourceDir>
                            <sourceDir>src/main/java</sourceDir>
                        </sourceDirs>
                        <annotationProcessorPaths>
                            <annotationProcessorPath>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${org.mapstruct.version}</version>
                            </annotationProcessorPath>
                        </annotationProcessorPaths>
                    </configuration>
                </execution>
                <execution>
                    <id>compile</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <phase>test-compile</phase>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <args>
                    <arg>-Xjsr305=strict</arg>
                </args>
                <compilerPlugins>
                    <plugin>spring</plugin>
                    <plugin>jpa</plugin>
                </compilerPlugins>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-maven-allopen</artifactId>
                    <version>${kotlin.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-maven-noarg</artifactId>
                    <version>${kotlin.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.mapstruct</groupId>
                    <artifactId>mapstruct-processor</artifactId>
                    <version>1.3.1.Final</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
`

image
image
image

Add example of configuration arguments using Maven in Kotlin example

Can we get added to the pom.xml file in the kotlin example some configuration arguments?

Right now I have the following and it's not working...because kapt is being used rather than the maven compiler plugin for annotation processing (and after a lot of googling and searching, I can't find anything on how kapt processor args are meant to be formatted when using maven):

...
  <annotationProcessorPaths>
    <path>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct-processor</artifactId>
      <version>${mapstruct.version}</version>
    </path>
  </annotationProcessorPaths>
  <args>
    <arg>-Amapstruct.defaultComponentModel=spring</arg>
    <arg>-Amapstruct.unmappedTargetPolicy=IGNORE</arg>
    <arg>-Amapstruct.suppressGeneratorTimestamp=true</arg>
    <arg>-Amapstruct.suppressGeneratorVersionInfoComment=true</arg>
  </args>
...

file miss??

when I download the ZIP file and import to my IDE , I can not find some files
import org.mapstruct.example.protobuf.UserProtos.DepartmentDTO;
import org.mapstruct.example.protobuf.UserProtos.PermissionDTO;
import org.mapstruct.example.protobuf.UserProtos.UserDTO;
UserMapper.txt

Add example for mapstruct with Gradle 5

The example for Gradle 5 does NOT seem to work with Gradle 5. From the release notes: Release notes Gradle 5 states: Gradle will no longer automatically apply annotation processors that are on the compile classpath — use CompileOptions.annotationProcessorPath instead.
Specifically the "options.compilerArgs = [
'-Amapstruct.suppressGeneratorTimestamp=true" part.

See also my post on StackOverflow: https://stackoverflow.com/questions/56170222/migrating-from-gradle-4-to-5-how-to-get-mapstruct-1-20-final-working-with-it

mapstruct-kotlin example not working in IntelliJ IDEA with JDK 9+

Hi, I can not run the mapstruct-kotlin example on IntelliJ IDEA (and I have the same problem with my development project).

I'm using following setup:
mapstruct-kotlin example project (https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-kotlin)
OpenJDK 12
IntelliJ IDEA 2019.2
MapStruct 1.3.0.Final
Maven

Compiling with maven works. But run using IntelliJ IDEA run configuration "Application" will fail with following error:
Error:(3, 35) java: cannot find symbol
symbol: class Generated
location: package javax.annotation.processing
Error:(7, 2) java: cannot find symbol
symbol: class Generated

When I use MapStruct 1.2.0.Final it works without problem.

I think the problem is that the compilation will use JDK 12 with javax.annotation.processing.Generated but the IntelliJ run configuration uses JRE 8 where javax.annotation.Generated exists instead of javax.annotation.processing.Generated.

But I'm helpless how I can solve this problem. Using JDK 8 will work (because javax.annotation.Generated will be used, which is available on runtime). I would need an option (like mapstruct. suppressGeneratorTimestamp) where I can suppress the complete usage of generated annotation. Or where I can enforce the usage of the old javax.annotation.Generated annotation.

Thanks a lot!
Tobi

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.