Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ModelAttribute for complex objects

I have a user entity that has many attributes (some fields not shown here):

@Entity
public class User {

    @OneToOne(cascade = ALL, orphanRemoval = true)
    private File avatar; // File is a custom class I have created

    @NotEmpty
    @NaturalId
    private String name;

    @Size(min = 6)
    private String password;

    @Enumerated(EnumType.STRING)
    private Role role;
}

In my thymeleaf template I have a form that submits username, password and avatar (MultipartFile). Now in my controller instead of these parameters...

@PostMapping("/register")
public String register(@RequestParam String username,
                       @RequestParam String password,
                       @RequestParam MultipartFile avatar) { ...

...I want to use @ModelAttribute @Valid User user. My problem is that:

  1. password first should be encrypted then passed to the user entity,
  2. bytes[] from MultipartFile should be extracted then stored in user entity (as a custom File object),
  3. some other fields such as Role should be set manually in the service class.

How can I take advantage of @ModelAttribute?

like image 369
Mahozad Avatar asked Jun 16 '18 20:06

Mahozad


People also ask

What is the use of @ModelAttribute annotation?

@ModelAttribute is an annotation that binds a method parameter or method return value to a named model attribute, and then exposes it to a web view. In this tutorial, we'll demonstrate the usability and functionality of this annotation through a common concept, a form submitted from a company's employee.

Which one of the given options @ModelAttribute annotation can be declared?

The @ModelAttribute annotation can be used at the parameter level or the method level. The use of this annotation at the parameter level is to accept the request form values while at the method level is to assign the default values to a model.

Why do we use @ModelAttribute?

The @ModelAttribute annotation is used as part of a Spring MVC web app and can be used in two scenarios. Firstly, it can be used to inject data objects in the model before a JSP loads. This makes it particularly useful by ensuring that a JSP has all the data it needs to display itself.

What is ModelAttribute in spring example?

In Spring MVC, the @ModelAttribute annotation binds a method parameter or method return value to a named model attribute and then exposes it to a web view. It refers to the property of the Model object.


1 Answers

Instead of trying to shoehorn everything into your User class, write a UserDto or UserForm which you can convert from/to a User. The UserForm would be specialized for the web and converted to a User later on.

The conversions you are talking about should be done in your controller (as that is ideally only a conversion layer before actually talking to your business services).

public class UserForm {

    private MultipartFile avatar; 

    @NotEmpty
    private String username;

    @Size(min = 6)
    @NotEmpty
    private String password;

    public UserForm() {}

    public UserForm(String username) {
         this.username = username;
    }

    static UserForm of(User user) {
        return new UserForm(user.getUsername());
    }

    // getters/setters omitted for brevity
}

Then in your controller do what you intended to do (something like this):

@PostMapping("/register")
public String register(@ModelAttribute("user") UserForm userForm, BindingResult bindingResult) {
    if (!bindingResult.hasErrors()) {
      User user = new User();
      user.setName(userForm.getUsername());
      user.setPassword(encrypt(userForm.getPassword());
      user.setAvataor(createFile(userForm.getAvatar());
      userService.register(user);
      return "success";
    } else {
      return "register";
    }
} 

This way you have a specialized object to fix your web based use cases, whilst keeping your actual User object clean.

like image 160
M. Deinum Avatar answered Oct 05 '22 23:10

M. Deinum