You can either add an @AllArgsConstructor annotation, because

@Builder generates an all-args constructor if there are no other constructors defined.

(Quoting @Andrew Tobilko)

Or set an attribute to @Builder : @Builder(toBuilder = true) This give you the functionality of a copy constructor.

@Builder(toBuilder = true)
class Foo {
    // fields, etc
}

Foo foo = getReferenceToFooInstance();
Foo copy = foo.toBuilder().build();
Answer from Gavrilo Adamovic on Stack Overflow
🌐
Project Lombok
projectlombok.org › features › Builder
@Builder
Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself or allowed lombok to create one such as with @NoArgsConstructor.
🌐
Baeldung
baeldung.com › home › java › using lombok’s @builder annotation
Using Lombok's @Builder Annotation | Baeldung
July 25, 2024 - Suppose we’re using an object that we want to construct with a builder, but we can’t modify the source or extend the Class. First, let’s create a quick example using Lombok’s @Value annotation: @Value final class ImmutableClient { private int id; private String name; } Now we have a final Class with two immutable members, getters for them, and an all-arguments constructor.
Discussions

java - Why is Lombok @Builder not compatible with this constructor? - Stack Overflow
First I was using only the @Builder Lombok annotation and everything was fine. But I added the constructor and the code does not compile any more. More on stackoverflow.com
🌐 stackoverflow.com
Spring boot Lombok and Builder, please help a junior
Builder allows you to initialize the variables in your pojo in the same line. Person.builder() .name("Adam Savage") .city("San Francisco") .job("Mythbusters") .job("Unchained Reaction") .build(); More on reddit.com
🌐 r/SpringBoot
14
3
October 14, 2022
java - lombok @Builder vs constructor - Stack Overflow
So for instance if you refactor some code and add a mandatory parameter to the constructor, you won't have compile error on builder callers... but you'll have runtime failures. ... Careful passing half-initialized builders around. They're mutable. A big reason to use Lombok in the first place ... More on stackoverflow.com
🌐 stackoverflow.com
java - Lombok @Builder and JPA Default constructor - Stack Overflow
I'm using project Lombok together with Spring Data JPA. Is there any way to connect Lombok @Builder with JPA default constructor? Code: @Entity @Builder class Person { @Id @GeneratedValue( More on stackoverflow.com
🌐 stackoverflow.com
🌐
Project Lombok
projectlombok.org › api › lombok › Builder
Builder (Lombok)
If a class is annotated, then a package-private constructor is generated with all fields as arguments (as if @AllArgsConstructor(access = AccessLevel.PACKAGE) is present on the class), and it is as if this constructor has been annotated with @Builder instead. Note that this constructor is only generated if you haven't written any constructors and also haven't added any explicit @XArgsConstructor annotations. In those cases, lombok will assume an all-args constructor is present and generate code that uses it; this means you'd get a compiler error if this constructor is not present.
🌐
Java By Examples
javabyexamples.com › delombok-builder
Lombok @Builder
When we want to create a builder for specific fields, we should create a constructor with only those fields. Then when we put the @Builder annotation on the constructor, Lombok creates a builder class containing only the constructor parameters.
🌐
Google Groups
groups.google.com › g › project-lombok › c › e9PzKXRlXXA
@Builder.Default and manual constructors
Having @Builder.Default on a field moves its initializer to a separate method, which is later called only of necessary by the builder's build() method. Lately, lombok significantly improved by also using this initializer method for generated @*ArgsConstructors. However, as discussed at GitHub, this still has the drawback that manually implemented constructors will not set the initial value.
🌐
KapreSoft
kapresoft.com › java › 2021 › 12 › 27 › lombok-builders-and-copy-constructors.html
Lombok • Builders and Copy Constructors | KapreSoft
December 27, 2021 - Lombok’s builder and copy constructor feature using @Builder is a mechanism that allows the implementation of the Builder Pattern and Copy Constructors in Object-Oriented Programming.
Find elsewhere
🌐
Baeldung
baeldung.com › home › java › lombok @builder with inheritance
Lombok @Builder with Inheritance | Baeldung
May 11, 2024 - The constructor that we need to create can become quite large, but our IDE can help us out. As we noted earlier, version 1.18 of Lombok introduced the @SuperBuilder annotation. We can use this to solve our problem in a simpler way. We can make a builder that can see the properties of its ancestors.
🌐
HowToDoInJava
howtodoinjava.com › home › lombok › lombok @builder
Lombok @Builder with Examples- HowToDoInJava
December 15, 2021 - For making fields mandatory, we need to add our own ArticleBuilder class with required fields as constructor parameters. Also, do not forget to add @NonNull annotation if we want to make sure that the client is not passing a null to satisfy the required input validation. @Builder @Getter @ToString public class Article { @NonNull private final Long id; private String title = "Title Placeholder"; @Singular private final List<String> tags; public static ArticleBuilder builder(final Long id) { return new ArticleBuilder().id(id); } }
🌐
Reddit
reddit.com › r/springboot › spring boot lombok and builder, please help a junior
r/SpringBoot on Reddit: Spring boot Lombok and Builder, please help a junior
October 14, 2022 -

What exactly does @ Builder annotation do? I need to deliver JUnit tests (it's my first contact with tests) of a really small challenge project, but without using Lombok and I'm not finding tutorials that don't use @ Builder to do them. Thanks in advance.

ps: english it's not my first language, sorry

edit: thank you all very much for the help, I managed to solve the problem through the documentation and some videos

🌐
GitHub
github.com › projectlombok › lombok › blob › master › src › core › lombok › Builder.java
lombok/src/core/lombok/Builder.java at master · projectlombok/lombok
* The <code><strong>T</strong>Builder</code> class contains 1 method for each parameter of the annotated · * constructor / method (each field, when annotating a class), which returns the builder itself.
Author   projectlombok
Top answer
1 of 9
132

Updated

Based on the feedback and John's answer I have updated the answer to no longer use @Tolerate or @Data and instead we create accessors and mutators via @Getter and @Setter, create the default constructor via @NoArgsConstructor, and finally we create the all args constructor that the builder requires via @AllArgsConstructor.

Since you want to use the builder pattern I imagine you want to restrict visibility of the constructor and mutators methods. To achieve this we set the visibility to package private via the access attribute on the @NoArgsConstructor and @AllArgsConstructor annotations and the value attribute on the @Setterannotation.

Important

Remember to properly override toString, equals, and hashCode. See the following posts by Vlad Mihalcea for details:

  • the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate
  • how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
  • hibernate-facts-equals-and-hashcode
package com.stackoverflow.SO34299054;

import static org.junit.Assert.*;

import java.util.Random;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.junit.Test;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@SuppressWarnings("javadoc")
public class Answer {

    @Entity
    @Builder(toBuilder = true)
    @AllArgsConstructor(access = AccessLevel.PACKAGE)
    @NoArgsConstructor(access = AccessLevel.PACKAGE)
    @Setter(value = AccessLevel.PACKAGE)
    @Getter
    public static class Person {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;

        /*
         * IMPORTANT:
         * Set toString, equals, and hashCode as described in these
         * documents:
         * - https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
         * - https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
         * - https://vladmihalcea.com/hibernate-facts-equals-and-hashcode/
         */
    }

    /**
     * Test person builder.
     */
    @Test
    public void testPersonBuilder() {

        final Long expectedId = new Random().nextLong();
        final Person fromBuilder = Person.builder()
            .id(expectedId)
            .build();
        assertEquals(expectedId, fromBuilder.getId());

    }

    /**
     * Test person constructor.
     */
    @Test
    public void testPersonConstructor() {

        final Long expectedId = new Random().nextLong();
        final Person fromNoArgConstructor = new Person();
        fromNoArgConstructor.setId(expectedId);
        assertEquals(expectedId, fromNoArgConstructor.getId());
    }
}

Old Version using @Tolerate and @Data:

Using @Tolerate worked to allow adding a noarg constructor.

Since you want to use the builder pattern I imagine you want to control visibility of the setter methods.

The @Data annotation makes the generated setters public, applying @Setter(value = AccessLevel.PROTECTED) to the fields makes them protected.

Remember to properly override toString, equals, and hashCode. See the following posts by Vlad Mihalcea for details:

  • the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate
  • how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
  • hibernate-facts-equals-and-hashcode
package lombok.javac.handlers.stackoverflow;

import static org.junit.Assert.*;

import java.util.Random;

import javax.persistence.GenerationType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.Setter;
import lombok.experimental.Tolerate;

import org.junit.Test;

public class So34241718 {

    @Builder
    @Data
    public static class Person {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Setter(value = AccessLevel.PROTECTED)
        Long id;

        @Tolerate
        Person() {}

       /* IMPORTANT:
          Override toString, equals, and hashCode as described in these 
          documents:
          - https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
          - https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
          - https://vladmihalcea.com/hibernate-facts-equals-and-hashcode/
          */
    }

    @Test
    public void testPersonBuilder() {

        Long expectedId = new Random().nextLong();
        final Person fromBuilder = Person.builder()
            .id(expectedId)
            .build();
        assertEquals(expectedId, fromBuilder.getId());

    }

    @Test
    public void testPersonConstructor() {

        Long expectedId = new Random().nextLong();
        final Person fromNoArgConstructor = new Person();
        fromNoArgConstructor .setId(expectedId);
        assertEquals(expectedId, fromNoArgConstructor.getId());
    }
}
2 of 9
114

You can also solve it explicitly with @Data @Builder @NoArgsConstructor @AllArgsConstructor combined on the class definition.

🌐
Baeldung
baeldung.com › home › java › lombok builder with default value
Lombok Builder with Default Value | Baeldung
May 11, 2024 - On top of these, we want a builder for this class. With Lombok, we can have all this with some simple annotations: @Getter @Builder @NoArgsConstructor @AllArgsConstructor public class Pojo { private String name; private boolean original; }
🌐
KapreSoft
kapresoft.com › java › 2023 › 03 › 30 › how-to-use-constructor-lombok.html
Lombok • How to Use Constructor | KapreSoft
March 30, 2023 - Lombok’s builder and copy constructor feature using @Builder is a mechanism that allows the implementation of the Builder Pattern and Copy Constructors in Object-Oriented Programming.
🌐
Project Lombok
projectlombok.org › features › constructor
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
If set to true, then lombok will add a @java.beans.ConstructorProperties to generated constructors.
🌐
Google Groups
groups.google.com › g › project-lombok › c › eytTxrKa_LY
@Builder and @NoArgsConstructor together
required: no arguments found: java.lang.Long, java.lang.String, java.lang.String, java.lang.Long, java.lang.String, java.lang.Instant It found the all-args constructor, but required the no-args constructor, which exists due to the @NoArgsConstructor annotation. This message might be misleading, but it's not produced by Lombok.
🌐
iO Flood
ioflood.com › blog › lombok-builder
Lombok @Builder | Streamlining Java Object Creation
March 5, 2024 - In this example, the Employee class has many properties, making the constructor quite complex. It’s easy to mix up the order of the parameters, leading to bugs that can be hard to track down. This is where Lombok’s builder pattern shines. It allows you to build up your object property by property, making the code more readable and less prone to errors.
🌐
Javadoc.io
javadoc.io › doc › org.projectlombok › lombok › 1.16.18 › lombok › Builder.html
Builder - lombok 1.16.18 javadoc
Bookmarks · Latest version of org.projectlombok:lombok · https://javadoc.io/doc/org.projectlombok/lombok · Current version 1.16.18 · https://javadoc.io/doc/org.projectlombok/lombok/1.16.18 · package-list path (used for javadoc generation -link option) · https://javadoc.io/doc/org.pro...