I have a domain object class User (it is a JPA entity):
@Entity
public class User {
   private String name;
   private boolean enabled = true;
   // getters/setters
}
And I am trying to offer a REST API to allow clients to create new users, using Spring 3 MVC:
@Controller
public class UserController {
    @RequestMapping(value="/user", method=RequestMethod.POST)
    @ResponseBody
    public String createRealm(@RequestBody User user) {
            user.setEnabled(true); // client is not allowed to modify this field
            userService.createUser(user);
            ...
    }
}
It works great, but I do not know if it is a good idea to use the domain objects as @RequestBody, because I have to protect some fields that should not be directly modified by the client (i.e. "enabled" in this case).
What are the pros/cons of these alternatives:
The second alternative looks like this:
@Entity
public class User {
   private String name;
   private boolean enabled = true;
   // getters/setters
}
public class UserRequest {
   private String name;
   // enabled is removed
   // getters/setters
}
@Controller
public class UserController {
    @RequestMapping(value="/user", method=RequestMethod.POST)
    @ResponseBody
    public String createRealm(@RequestBody UserRequest userRequest) {
            User user = ... // map UserRequest -> User
            userService.createUser(user);
            ...
    }
}
Is there any other way that avoids code duplication and is easier to maintain?
There is another option - you can disallow the submission of a given set of properties, using the DataBinder.setDisallowedFields(..) (or using .setAllowedFields(..))
@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields(..);
}
This is fine if you have one or two properties that differ.
Otherwise, having a special object (like ProfileDetails or UserRequest) makes more sense. I am using such a DTO-like object for this scenario and then transfer the fields with BeanUtils.copyProperties(..) from commons-beanutils
A third, perhaps better option, is to put all profile-related fields into a separate entity (mapped with @OneToOne with user) or to an @Embeddable object, and use it instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With