javaquarkusopenapilombok

lombok @SuperBuilder changing one of my field names?


I have a hierarchy of DTO classes created by lombok @SuperBuilder. When using it, one of the fields becomes mysteriously renamed. Why is that and what can I do to maintain the original name ? Is this a lombok problem or feature - but I cannot find any hints in the lombok docs?

@SuperBuilder
@Getter
@NoArgsConstructor
public class ExpenseDto {
    @NonNull
    @Size(max = 30)
    protected String recipient;

    @NonNull
    @Size(max = 30)
    protected String purpose;
    
    // ...

    protected boolean isInvoiced;  // this somehow is changed
}

@Data
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class ExpenseEntityDto extends ExpenseDto {
    @Size(max = 16)
    long expenseId;

    @Size(max = 16)
    @NonNull
    protected String accountNo;

    // ...
}

I use it like so:

public ExpenseEntityDto domainToEntityDto(Expense domain) {
   return ExpenseEntityDto.builder()
                .expenseId(domain.getExpenseId())
                .accountNo(domain.getAccountNo())
                .recipient(domain.getRecipient())
                .purpose(domain.getPurpose())
                .isInvoiced(domain.isInvoiced())  // produces a field 'invoiced' !?
                .build();
}

In flight, the DTO JSON looks like this:

{
    "recipient": "Mobsters Inc.",
    "purpose": "protection services rendered",
    "expenseId": 1,
    "accountNo": "1234",
    "invoiced": false     // Huh !? expected 'isInvoiced' instead
}

Even better, the openapi spec (generated from smallrye-openapi extension in quarkus) shows BOTH versions in the Schema (same in swagger ui):

ExpenseEntityDto:
      type: object
      properties:
        recipient:
          maxLength: 30
          type: string
        purpose:
          maxLength: 30
          type: string
        isInvoiced:
          type: boolean
        invoiced:
          type: boolean
        expenseId:
          format: int64
          type: integer
        accountNo:
          maxLength: 16
          type: string

Solution

  • You did ofcourse read the documentation?

    For boolean fields that start with is immediately followed by a title-case letter, nothing is prefixed to generate the getter name.

    This is default Lombok behavior (and not sure if that is overridable). Lombok follows the Java Beans spec as close as possible. A boolean field named isInvoiced would get an accessor like isIsInvoiced which is confusing, hence it doesn't generate an additional is.

    Looking at the Java Bean specification all fields will be prefixed with get or set depending on the type. With one exception that is boolean that instead of get will be prefixed with is.

    To get an getIsInvoiced you would need to make the field a Boolean field instead of a boolean.

    Another option is to add Jackson annotations to force the field in JSON to be isInvoiced (adding a @JsonProperty("isInvoiced") to the field should take care of that.