1

I use the Spring Boot 2.0.8.RELEASE.

I have a @RestController method looks like this:

    @PostMapping("/message")
    public PushMessageResponse sendPush(@Validated @RequestBody PushMessageRequest pushMessageRequest) {
        final List<String> sentMessage = pushService.sendMessage(pushMessageRequest);

        return new PushMessageResponse(sentMessage);
    }

And I have a PushMessageRequest class that looks like this:

@RequiredArgsConstructor
@Data
public class PushMessageRequest {

    private final Optional<UUID> clientId;
    private final Optional<String> token;
    private final Optional<String> text;
    private final Optional<PushOptions> pushOptions;
    @NotBlank
    private final String appName;

}

And If I send a request to this method with a body that doesn't contain some property I see that that kind of property(those that I didn't pass in the JSON request) is null.

I've already tried to add such configuration:

@Configuration
public class JacksonConfiguration {

    @Bean
    public Module jdk8Module() {
        return new Jdk8Module();
    }
}

I have expected to see that the Optional property of my DTO isn't null but such property has a value of Optional.empty().

  • Never use `Optional` for field declarations. What you are doing is wrong in the first place. – Ravindra Ranwala Aug 08 '19 at 08:40
  • @RavindraRanwala why so? These fields could be null, I want to force developers to check such fields for nullability. – Alexey Vinogradov Aug 08 '19 at 09:13
  • you can use normal field and make you getter return Optional –  Aug 08 '19 at 09:25
  • you can do something like this: public class PushMessageRequest { private final UUID clientId; public Optional getClientId(){ Optional.ofNullable(clientId); } } –  Aug 08 '19 at 09:27
  • @AmanGarg sure, I do this as a workaround. But I think there is a deserialization problem in the Spring MVC because `@RequestParam` works with Optional as expected. Or I didn't configure Spring properly. – Alexey Vinogradov Aug 08 '19 at 09:29

2 Answers2

1

Why do you want to use Optional here. You can simply use regular classes, and use Optional.ofNullable() to create Optional objects inside your controller class.

The Optional API was primarily intended to be used for methods that return a value that may be null, rather than transmitting data. For example, you can write your message class as:

public class PushMessageRequest {
    private UUID clientId;
    ...
}

and in your controller class, you can call:

@PostMapping("/message")
public PushMessageResponse sendPush(@Validated @RequestBody PushMessageRequest pushMessageRequest) {
    Optional<UUID> uuidOptional = Optional.ofNullable(pushMessageRequest.getUUID());
    ...
}

For a more detailed explanation of why you should not use Optional in a class that is serialized, refer to: Why java.util.Optional is not Serializable, how to serialize the object with such fields. Although this refers specifically to standard Java serialization, the reasoning applies to JSON serialization as well.

cameron1024
  • 9,083
  • 2
  • 16
  • 36
  • I want to use Optional in the fields because I want to implicitly force developers to check that field for nullability. – Alexey Vinogradov Aug 08 '19 at 09:12
  • This doesn't force them to check for null. A lazy developer using optionals will simply call `optional.get()`. A lazy developer using regular classes will just call it without checking null. – cameron1024 Aug 08 '19 at 09:25
  • This is a misuse of the API, and you should change them to regular fields – cameron1024 Aug 08 '19 at 09:25
  • public class PushMessageRequest { private final UUID clientId; public Optional getClientId(){ Optional.ofNullable(clientId); } } –  Aug 08 '19 at 09:27
  • @cameron1024 Sure, a lazy developer can do this, but this code doesn't pass a review. – Alexey Vinogradov Aug 08 '19 at 09:32
  • Perhaps Brian Goetz's (Java language designer) opinion may help you see this more clearly: https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555 – cameron1024 Aug 08 '19 at 09:41
  • @cameron1024 Yes, sounds that I misuse Optional. – Alexey Vinogradov Aug 08 '19 at 10:04
1

According to @cameron1024, @AmanGarg, @RavindraRanwala I shouldn't use Optional as a field, because it is not intended to.

I choose the solution of creating methods that return Optional#ofNullable() of the field.