Use custom setter in Lombok's builder

后端 未结 4 1052
暖寄归人
暖寄归人 2021-01-01 08:42

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

@Data
@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncod         


        
相关标签:
4条回答
  • 2021-01-01 09:14

    Not really an answer to the question, but an edge case that made me to spend quite some time to find the issue.
    If you have Builder with custom setter on a field with Builder.Default value, the name of the field in the generated builder class is not the same as the original field. In fact you would have two fields instead of one: password$value and password$set.
    Nevertheless you can use them in the custom setter in this way:

    public UserBuilder password(String password) {
      this.password$value = ENCODER.encode(password);
      this.password$set = true;
      return this;
    }
    

    The tricky part is that if you use the origianl field name, Intellij IDEA doesn't warn you about that (as if everything is fine, but of course it won't compile). Already submitted a bug report to the plugin.

    0 讨论(0)
  • 2021-01-01 09:22

    You are using setPassword rather than the builder's set method.

    Here is what worked for me:

    import lombok.Builder;
    import lombok.Data;
    
    @Builder
    @Data
    public class User {
        private String username;
        private String password;
    
        public static class UserBuilder {
            private String password;
            public UserBuilder password(String password ) {
                this.password ="ENCRIYP " +  password;
                return this;
            }
        }
    
        public static void main(String[] args) {
            System.out.println(User.builder().username("This is my username").password("Password").build().toString());
    
        }
    }
    

    The result was: User(username=This is my username, password=ENCRIYP Password)

    0 讨论(0)
  • 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);
        }
    }
    
    0 讨论(0)
  • 2021-01-01 09:26

    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;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题