2

Given the following code.

@Getter
@Builder(builderClassName = "Builder", buildMethodName = "build")
public final class BusinessEvent implements BusinessPayload {
  private String action, duration, outcome, provider, trackId, sequence;
  @lombok.Builder.Default private Optional<String> brand, vin, externalTrackId, code = Optional.empty();
  @lombok.Builder.Default private Optional<BusinessEventError> eventError = Optional.empty();

  static class Builder {
    BusinessEvent build() throws MissingRequiredValueException {
      // Custom validation
      return new BusinessEvent(action, duration, outcome, provider, trackId, sequence, brand, vin, externalTrackId, code, eventError);
    }
  }
}

I get the error

java: non-static variable eventError cannot be referenced from a static context

Somehow Optional values are not handled correctly by lombok in this case? I see the same problem in all my builders. This is not shown as an issue by intellij plugin but only when I try to build.

I know you should not use optional as field values but in this case it make the API much clearer and the builder will not get serialized anyways, we have DTOs for that.

user3139545
  • 6,882
  • 13
  • 44
  • 87
  • 2
    Are you sure this is related to Lombok? You have a static inner Builder class. This class does not have an enclosing instance of BusinessEvent. But you are trying to access instance fields of that class. That will not work anyway, no matter if you use Optional or Lombok. – Jochen Reinhardt Dec 05 '19 at 09:24
  • The non optional field does not have this issue. So yes its related to lombok and the optional i would say. – user3139545 Dec 05 '19 at 09:28
  • Have you tried removing the last constructor argument? You might then find that the compiler starts complaining about the variable `code`, meaning that it only gives an error about the last argument. Try putting `action` (the non-Optional one) as the last argument and see what happens. – DodgyCodeException Dec 05 '19 at 09:37
  • 1
    I think you misunderstand how lombok works. The values inside the static class are the one that are referenced (however they are not visible since this is lombok magic) in the constructor and not the values in BusinessEventError. – user3139545 Dec 05 '19 at 09:51

1 Answers1

2

To sum up what you want to do:

  • you want a builder generated by lombok
  • you want default values assigned in the builder using @Default
  • you want custom validation inside the build method

This does not seem to work. Neither with Optional, nor with other objects. Seems to be a limitation in lombok.

The fact that it is not recognized by IntelliJ as an error does not mean that it is supposed to work. But your compilation fails. This is a real issue.

Consider the following code, without the @lombok.Builder.Default annotation:

@Getter
@Builder(builderClassName = "Builder", buildMethodName = "build")
public final class BusinessEvent {
    private String action, duration, outcome, provider, trackId, sequence;
    private Optional<String> brand, vin, externalTrackId, code = Optional.empty();
    private Optional<Object> eventError = Optional.empty();

    static class Builder {
        BusinessEvent build() {
            if (brand == null) {
                throw new RuntimeException("brand not set");
            }
            // Custom validation
            return new BusinessEvent(action, duration, outcome, provider, trackId, sequence, brand, vin, externalTrackId, code, eventError);
        }
    }

    public static void main(String[] args) {
        BusinessEvent eventWithBrand = BusinessEvent.builder().brand(Optional.of("brand")).build();
        // will throw exception
        BusinessEvent event = BusinessEvent.builder().build();
    }
}
Jochen Reinhardt
  • 833
  • 5
  • 14