Search code examples
javaspring-bootjava-8lombokdto

Using SuperBuilder to extend parent class using Lombok


I had a DTO that was using Lombok functionaliy as shown below.But now due to some requirement I had to extend my DTO to a parent class which looks like below.How can I do minimal change in my DTO to support that.I tried using @SuperBuilder annotation but it failed.

DTO Before:

@Getter
@ToString
@EqualsAndHashCode
@Builder(toBuilder = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RequestMessage {
private final String name;
 }

Parent Class that needs to be extended

   @Data
   @SuperBuilder(toBuilder = true)
   @JsonDeserialize(builder = MyDTO.Builder.class)
   public abstract class MyDTO implements Serializable {
   @JsonIgnore private final ObjectMapper objectMapper = new ObjectMapper();
   protected String myAccountId;

   protected MyDTO() {}

   public static int hashCode(Object... objects) {
     return Arrays.deepHashCode(objects);
   }

   public static boolean equal(Object o1, Object o2) {
    // implementation of equals method
   }

   public abstract String emitSerializedPayload() throws JsonProcessingException;

   @JsonPOJOBuilder(withPrefix = "")
   protected abstract static class Builder<T extends MyDTO, B extends Builder<T, B>> {
   protected T dtoInstance;
   protected B builderInstance;

   public Builder() {
  dtoInstance = createDtoInstance();
  builderInstance = returnBuilderInstance();
}

protected abstract T createDtoInstance();

protected abstract B returnBuilderInstance();

public B myAccountId(String accountId) {
  dtoInstance.myAccountId = accountId;
  return builderInstance;
}

public T build() {
  return dtoInstance;
}
}
}

I tried to build RequestMessageClass manually and it works fine but there are lot of classes in my application and I dont want to change them manually, how can I change my existing RequestMessage class with annotations or some minimum change to get it working.

This is what I tried but I am getting compilation error when doing this

    RequestMessage.Builder().name(myName).myAccountId(myAcId).build();
     
     

What I tried is like shown below:

 @Getter
 @ToString
 @EqualsAndHashCode(callSuper = true)
 @SuperBuilder(toBuilder = true)
 @AllArgsConstructor(access = AccessLevel.PRIVATE)
 public class RequestMessage extends MyDTO {
 private final String name;

 @Override
 public String emitSerializedPayload() throws JsonProcessingException {
// TODO Auto-generated method stub
return null;
}
} 
 

Solution

  • You shouldn't mix lombok @Builder with static inner Builder class. If it is possible to get rid of Builder class, the next code should work.

    RequestMessage:

    @Getter
    @ToString
    @EqualsAndHashCode(callSuper = true)
    @SuperBuilder(toBuilder = true)
    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    public class RequestMessage extends MyDTO {
        private final String name;
    
        @Override
        public String emitSerializedPayload() throws JsonProcessingException {
        return null;
        }
        public RequestMessage(String myAccountId, String name) {
            super(myAccountId);
            this.name = name;
    }
    }
    

    MyDTO:

    @Data
    @SuperBuilder(toBuilder = true)
    public abstract class MyDTO implements Serializable {
        @JsonIgnore private final ObjectMapper objectMapper = new ObjectMapper();
        protected String myAccountId;
    
        protected MyDTO() {}
    
        public MyDTO(String myAccountId) {
           this.myAccountId = myAccountId;
        }
    
        public static int hashCode(Object... objects) {
            return Arrays.deepHashCode(objects);
        }
    
        public static boolean equal(Object o1, Object o2) {
            // implementation of equals method
            return false;
        }
        public abstract String emitSerializedPayload() throws JsonProcessingException;
    }
    

    Test:

    @Test
    void name() {
        String myName = "myName";
        String myAccountId = "myAccountId";
        var request = RequestMessage.builder().name(myName).myAccountId(myAccountId).build();
        System.out.println("request = " + request);
        RequestMessage requestMessage = new RequestMessage(myAccountId, myName);
    }