Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use custom setter in Lombok's builder

Tags:

java

lombok

I have a custom setter in my Lombok-based POJO:

@Data @Builder public class User {     private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();      private String password = null;      public void setPassword(String password) {         Assert.notNull(password);         this.password = ENCODER.encode(password);     } 

but when I use the Lombok generated builder:

User user = User.builder()     .password(password)     .build(); 

my custom setter is not invoked, and so the password is not encoded. This makes me sad.

My custom setter is, of course, invoked when I use it directly:

public void changePassword(String password, User user) {     user.setPassword(password); } 

What can I do to have Lombok's builder use my custom setter?

like image 486
Jan Nielsen Avatar asked Feb 21 '17 23:02

Jan Nielsen


People also ask

Does Lombok builder use setter?

We already have a full introduction into Lombok's features. @Data generates all the boilerplate that is normally associated with a simple POJO (Plain Old Java Object): getters for all fields, setters for all non-final fields, and appropriate toString, equals and hashCode implementations, and a constructor.

What is the use of @builder annotation?

The @Builder annotation produces complex builder APIs for your classes. @Builder lets you automatically produce the code required to have your class be instantiable with code such as: Person. builder()

What is the use of @builder in spring boot?

1. @Builder. The @Builder annotation produces complex builder APIs for the annotated POJO classes. For example, if we annotate a class Article annotated with @Builder annotation, we can create Article instances using builder API.

What does builder () do in Java?

The builder pattern simplifies the creation of objects. It also simplifies the code as your do not have to call a complex constructor or call several setter methods on the created object. The builder pattern can be used to create an immutable class.


2 Answers

Per the documentation for @Builder: Just define enough skeleton yourself. In particular, Lombok will generate a class UserBuilder, fields mirroring the User fields, and builder methods, and you can provide any or all of this yourself.

@Builder public class User {     private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();      private String username;      private String password;      public static class UserBuilder {         public UserBuilder password(String password) {             this.password = ENCODER.encode(password);             return this;         }     } } 
like image 89
chrylis -cautiouslyoptimistic- Avatar answered Sep 22 '22 19:09

chrylis -cautiouslyoptimistic-


I've accepted chrylis's answer but for completeness, here's are some ways to minimize customization and duplication.

Custom setter and builder with static helper

A static helper can be used to shares most of the set password functionality across the custom User.UserBuilder::password method and the custom User::setPassword method:

@Data @Builder public class User {     private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();      private String password = null;      public void setPassword(String password) {         this.password = _encodePassword(password);     }      public static class UserBuilder {         public UserBuilder password(String password) {             this.password = _encodePassword(password)             return this;         }     }      private static String _encodePassword(String password) {         Assert.notNull(password);         return ENCODER.encode(password);     } } 

Custom setter and constructor

A custom constructor can use User::setPassword which is invoked by the Lombok generated User.UserBuilder::build():

@Data @Builder public class User {     private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();      private String password = null;      User(String password) {         setPassword(password);     }      public void setPassword(String password) {         Assert.notNull(password);         this.password = ENCODER.encode(password);     } } 

Custom setter and constructor with static helper

Or, a little more elegantly, with a custom constructor and a static helper method:

@Data @Builder public class User {     private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();      private String password = null;      User(String password) {         _encodePassword(password, this);     }      public void setPassword(String password) {         _encodePassword(password, this);     }      private static _encodePassword(String password, User user) {         Assert.notNull(password);         user.password = ENCODER.encode(password);     } } 
like image 41
Jan Nielsen Avatar answered Sep 23 '22 19:09

Jan Nielsen