Bukharov Sergey
Bukharov Sergey

Reputation: 10215

How to suppress lombok warnings

I have an Entity

@Builder
class MyEntity {
   private Set<OtherEntitiy> children = new HashSet<>()
}

And i get a lombok warning.

warning: @Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final. Set = new HashSet<>();

The question is: how can i suppress lombok's warning?

Also. I need to initialize children because i want to avoid NullPointerException. Also i can't mark this filed as final because it is not final really. I cant mark filed @Builder.Default because i wanna create this entity not only with builder and i wanna to save default value for other constructors.

Upvotes: 31

Views: 29861

Answers (2)

Pytry
Pytry

Reputation: 6419

Sometimes you just have to write code, so here are a couple more ways of doing this.

Use @NonNull

@Builder
static class MyEntity {

    @NonNull
    private Set<MyEntity> children;

}
  • all-args constructor is generated.
  • NullPointerException is thrown from both the builder and the generated constructor, but with a better message.
  • developer must pass a value to the builder to avoid the exception.

Use @NonNull and Generated constructors

@NoArgsConstructor
@AllArgsConstructor
@Builder
static class MyEntity {
  @NonNull
  private Set<MyEntity> children;
}
  • You need to explicitly declare @AllArgsConstructor if you use @NoArgsConstructor.
  • A descriptive NullPointerException is thrown from the builder and both constructors.
  • developer must still pass a value to the builder to avoid the exception.

When Using @Singular

@Builder
class MyEntity {

    @Singular
    private Set<OtherEntitiy> children;

    MyEntity(){
        children = new HashSet<>()
    }


    MyEntity(Set<OtherEntity> children){
        this.children = children == null ? new HashSet<> : children;
    }
}
  • @Singular and @Builder.Default are not currently compatible.
    • Using both will cause a pre-compile error.
  • Initializing in an explicit no-args constructor will bypass the pre-compile error.
  • A parameterized constructor is required by the builder.
    • You will need to check for null and set to default value.
  • NullPointerException is still thrown if the developer passes null to the builder.
  • The field is still nullable if the developer explicitly passes null through the parameterized constructor.

Completely Prevent null

@Data
@Builder
class MyEntity {

    @Singular(ignoreNullCollections = true)
    private Set<OtherEntity> children;

    MyEntity(){
        children = new HashSet<>()
    }

    MyEntity(Set<OtherEntity> children){
        setChildren(children)
    }

    void setChildren(Set<OtherEntity> children){
        this.children = children == null ? new HashSet<>() : children;
    }
}
  • Use @Singular(ignoreNullCollections = true) to ignore when developers pass a null reference through the builder.
  • Add null check and set to default value in an explicit setter.
    • Use the explicit setter to set the value in any explicit parameterized constructors.
  • Compatable with @Data, @Getter, and @Setter
  • There aren't any required (final) fields, so the required-args constructor is not generated.

Force use of Builder

@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
static class MyEntity {
  @Singular(ignoreNullCollections = true)
  private Set<MyEntity> children;
}
  • Same results as the previous example, but with less code.
  • Less flexible.
    • May not work for certain libraries that require access to constructors.

Notes:

Quietly setting the value when null is passed instead of throwing a descriptive runtime exception might be more confusing and/or not appropriate for your use cases. Choose the correct approach for your needs.

Upvotes: 0

Daniel Taub
Daniel Taub

Reputation: 5399

Use @Builder.Defaultto add default behavior for your Builder

@Builder
class MyEntity {
   @Builder.Default
   private Set<String> children = new HashSet<>();
}

You use it on the field that has a default value defined an Lombok
will then pick up the value during object creation

@Builder.Default functionality was added in lombok v1.16.16. So if you're using lower version of Lombok you will not be able to use it.

Upvotes: 43

Related Questions