9

I'm using Optional parameters for my Rest controller, in my case to distinguish which method to call:

@GetMapping("/cars")
@ResponseBody
public List<CarsDTO> getAllCarsByCat(@RequestParam Optional<Integer> cat1,
                                     @RequestParam Optional<Integer> cat2) {
    if (cat1.isPresent() && cat2.isPresent())
        return carsService.getAllCarsByCat1AndCat2(cat1.get(), cat2.get());
    else if (cat1.isPresent())
        return carsService.getAllCarsByCat1(cat1.get());
    else if (cat2.isPresent())
        return carsService.getAllCarsByCat2(cat2.get());
    else
        return carsService.getAllCars();

}

Why does the highest voted response of the thread below propose that "Using Optional parameters causing conditional logic inside the methods is literally contra-productive."?

Why should Java 8's Optional not be used in arguments

I do exactly that and consider it as the most readable and straight forward solution. What is bad with this approach?

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • The answers to this question will be opinion based and this question can be closed. In my opinion, your code without *Optional* would be more readable / understandable if you had plain *Integer* types: all *if* expressions would be compact, but passing parameters to the *carService* would be even compacter than it is now, because *Optional.get()* would not be needed. In your case *Optional* wrappers are created, but I would neglect related memory and performance effects, which would be an additional contra argument for others. – mentallurg Dec 25 '19 at 18:46

1 Answers1

11

The only concern using Optional as @RequestParam is performance and creating Optional wrapper using Optional.OfNullable and unwrapping using Optional.get() or checking using Optional.ifPresent(). As a functional perspective it always looks good using Optional but as a good programmer it is an unnecessary additional operations wrapping and unwrapping. In spring Optional is allowed in @RequestParam to declare param as optional

By default, method parameters that use this annotation are required, but you can specify that a method parameter is optional by setting the @RequestParam annotation’s required flag to false or by declaring the argument with an java.util.Optional wrapper.

So you can simply make those @RequestParam as optional using required==false and follow the same approach using if else, you can also use Objects.nonNull for more readability or you can also use defaultValue

@GetMapping("/cars")
@ResponseBody
 public List<CarsDTO> getAllCarsByCat(@RequestParam(name="cat1", required=false) Integer cat1,
                                 @RequestParam(name="cat2", required=false) Integer cat2) {
     if (cat1!=null && cat2!=null)
         return carsService.getAllCarsByCat1AndCat2(cat1, cat2);
     else if (cat1!=null)
         return carsService.getAllCarsByCat1(cat1);
     else if (cat2!=null)
         return carsService.getAllCarsByCat2(cat2);
     else
         return carsService.getAllCars();

  }
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98