Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing duplication from Spring controllers

I have been looking for a way to somehow reduce the amount of code that is duplicated with subtle variance in my Spring MVC controllers, but searching through the SO questions so far has only yielded some questions without any satisfactory answers.

One example of duplication that I want to remove is this, where the user creation page and the role creation page share similarities:

  @RequestMapping(value = "user/create", method = RequestMethod.GET)
  public String create(@ModelAttribute("user") User user, BindingResult errors) {
    LOG.debug("Displaying user creation page.");
    return "user/create";
  }

  @RequestMapping(value = "role/create", method = RequestMethod.GET)
  public String create(@ModelAttribute("role") Role role, BindingResult errors) {
    LOG.debug("Displaying role creation page.");
    return "role/create";
  }

A slightly more involved variant of duplication that I would like to remove is the one for posting the create form:

  @RequestMapping(value = "user/create", method = RequestMethod.POST)
  public String save(@ModelAttribute("user") User user, BindingResult errors) {
    LOG.debug("Entering save ({})", user);
    validator.validate(user, errors);
    validator.validatePassword(user, errors);
    validator.validateUsernameAvailable(user, errors);
    String encodedPassword = encoder.encode(user.getPassword());
    user.setPassword(encodedPassword);
    if (errors.hasErrors()) {
      return create(user, errors);
    } else {
      service.save(user);
    }
    return "redirect:/user/index/1";
  }

  @RequestMapping(value = "role/create", method = RequestMethod.POST)
  public String save(@ModelAttribute("role") Role role, BindingResult errors) {
    LOG.debug("Entering save({})", role);
    validator.validate(role, errors);
    if (errors.hasErrors()) {
      return create(role, errors);
    } else {
      service.save(role);
    }
    return "redirect:/index";
  }

This example includes a validate then save if correct and a redirect to the error page if things don't go as planned.

How to remove this duplication?

like image 309
vtanase Avatar asked Nov 27 '25 16:11

vtanase


1 Answers

Spring uses your handler method parameter types to create class instances from the request parameters or body. As such, there is no way to create a handler (@RequestMapping) method that could take an Object and check if it is either a Role or a User. (Technically you could have both parameters and just check which one isn't null, but that is terrible design).

Consequently, you need a handler method for each. This makes sense since, even through the logic is similar, it is still specific to the exact type of model object you are trying to create. You perform different validation, call a different service method, and return a different view name.

I say your code is fine.

like image 105
Sotirios Delimanolis Avatar answered Nov 30 '25 06:11

Sotirios Delimanolis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!