Announcement Announcement Module
Collapse
No announcement yet.
Read Only Fields Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Read Only Fields

    This is a cross post with http://stackoverflow.com/questions/1...spring-web-mvc

    I have what appears to be a common problem within spring-mvc. Several of my domain object have fields that are not updatable so in my view I am not binding these fields. For competeness sake The way these are excluded from the view is by editing the spring-roo scaffolded view setting the render attribute on the parameter to false.

    As spring-mvc creates a new instance of the object rather than updating the existing object these fields are null. This means however that the object fails its validation before the control reaches the controller.

    A lot of my entities will have extra fields that are not updatable in the view so I'd like to be able to come up with a generic solution rather than continually doing the same work over and over again (violating DRY).

    How can one allow validation to occur in a consistent manner if fields are omitted from the view?

    Code:
        @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
    public String UserController.update(@Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
        if (bindingResult.hasErrors()) {
            populateEditForm(uiModel, user);
            return "admin/users/update";
        }
        uiModel.asMap().clear();
        user.merge();
        return "redirect:/admin/users/" + encodeUrlPathSegment(user.getId().toString(), httpServletRequest);
    }
    Possible Solutions:
    Omit @Valid annotation from the controller.

    Pros

    Easy to implement.
    Easy to understand.

    Cons

    Means changing the controller method for every update on every object.
    Validation is not occuring in the same place as all of the rest of the application.
    No easy way to return the binding errors back to the view (need to validate the object afterwards)

    Add Custom Validator for methods that need omitted fields

    Example:

    Code:
    @InitBinder
    public void initBinder(WebDataBinder binder, HttpServletRequest request) {
        if (request.getMethod().equals("PUT")) {
            binder.setDisallowedFields("registrationDate", "password");
            Validator validator = binder.getValidator();
            Validator userUpdateValidator = new UserUpdateValidator();
            binder.setValidator(userUpdateValidator);
        }
    }
    Pros

    Clear flow.

    Cons

    Suffers wildly from DRY problems. This means that If the domain object is altered in any way I need to revalidate.
    Field validation is not the same as Hibernate validation when saving.
    No tangible benefits over omitting validation and manually validating.

    Would consider if?

    Custom validator could delegate to standard JSR-303 validator but just omit fields.

    Remove JSR-303 annotations from the domain object

    Not an option this means that there is no validation on an object before saving. Worse I believe it will affect the DDL that is producted for database, removing constraints from the DB itself. Only put in here for completeness sake
    Lookup domain object before validation occurs

    The idea of this solution is to lookup the existing domain object before updating. Copying any not null fields to the old object from the request. Pros - The validation can go through the normal cycle. - The validation doesn't need to change depending on what method you are implying.

    Cons

    Database access before hitting the controller has a bit of a smell.
    I can't see any way to implement this.
    Won't work for fields that need to be omitted during other stages of the object lifecycle. For example if adding a timestamp during creation.

    I would like to know how to implement either a validator that delegates to the standard JSR-303 validator or alternatively how to lookup the object before modifying it. Or if anyone has any other possible solutions?

    Either of these solutions allow for the treatment to be consistent over multiple objects.

    Hopefully either would allow for added annotations such as. @RooCreateOnly which means the domain object could be annotated as such leaving all the validation definitions in the one place.
Working...
X