mapstruct / mapstruct/mapstruct

Determine the builder class for a FreeBuilder type without the need of a static method in the type

Open
#3,314 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Java
Stars
7.7k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

Expected behavior

When I use a FreeBuilder interface/abstract class as a target of a mapper, I expect mapstruct to use the builder to construct the instance of that interface/abstract class.

Actual behavior

At compilation, I get the message

Ambiguous factory methods found for creating Target: Target Builder.build(), Target Builder.buildPartial(). See https://mapstruct.org/faq/#ambiguous for more info.

even though I use @Builder to specify the build method in @Mapper or in @BeanMapping.

Steps to reproduce the problem

I define my source and target class

public class Source {

    private String value1;

    private int value2;

    public String getValue1() {
        return value1;
    }
    public void setValue1(String value1) {
        this.value1 = value1;
    }
    public int getValue2() {
        return value2;
    }
    public void setValue2(int value2) {
        this.value2 = value2;
    }
}
@FreeBuilder
public interface Target {

    String getValue1();

    int getValue2();

    class Builder extends Target_Builder {
    }

}

and the mapper

import org.mapstruct.Mapper;

//@Mapper(uses = Target.Builder.class, builder = @Builder(buildMethod = "buildPartial"))
//@Mapper(uses = Target.Builder.class, builder = @Builder(buildMethod = "build"))
//@Mapper(uses = Target.Builder.class, builder = @Builder)
@Mapper(uses = Target.Builder.class)
public interface ExampleMapper {

    //    @BeanMapping(builder = @Builder(buildMethod = "buildPartial"))
//    @BeanMapping(builder = @Builder(buildMethod = "build"))
//    @BeanMapping(builder = @Builder)
    Target apply(Source source);

}

with POM containing

    <properties>
        <freebuilder.version>2.8.0</freebuilder.version>
        <mapstruct.version>1.5.5.Final</mapstruct.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.inferred</groupId>
            <artifactId>freebuilder</artifactId>
            <version>${freebuilder.version}</version>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <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>${mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.inferred</groupId>
                            <artifactId>freebuilder</artifactId>
                            <version>${freebuilder.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

Then run maven compile.

I attached a minimal project:
mapstruct-freebuilder.zip

MapStruct Version

MapStruct 1.5.5.Final

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attached minimal project, the ExampleMapper, Target.Builder, and the @Builder configuration, then run Maven compile to reproduce the ambiguous factory-method error. Trace how the annotation processor discovers builders for the FreeBuilder Target interface. Done means a mapper can select the configured build or buildPartial method without requiring a static method on the target type.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
devtools
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.