Search code examples
springvalidationdata-bindingspring-securityspring-roo

spring: hook between data binding and validation


I have a Roo generated application and use validation, spring security with a custom PermissionEvaluator and the generated web controllers. My entity has a field like this:

@NotNull
private Date creationDate;

This field is set automatically inside the controller's create method when saving the entity and is not included in the form (render="false").

@RequestMapping(method = RequestMethod.POST, produces = "text/html")
@PreAuthorize("hasPermission(#myEntity, 'create')")
public String create(@Valid MyEntity myEntity,
        BindingResult bindingResult, Model uiModel,
        HttpServletRequest httpServletRequest) {
    // ... check binding result
    myEntity.setCreationDate(new Date());
    myEntity.persist();
    // ...
}

The problem is, that validation always fails because it runs before the field is set. The PermissionEvaluator (called by @PreAuthorize) is also missing the value. How can I place my code somewhere between data binding and validation so that the entity is complete right from the beginning?


Solution

  • To solve the problem of @PreAutorize move the persistence logic to a @Service bean and call it from the controller. This way security check will be after validation. Roo can help you on it with service command.

    Second, you can use validation groups to make different validation on for the same entity. This and this are two howto post.

    An example:

    @RequestMapping("/myEntity")
    public MyEntityController {
       @Autowired
       MyEntityService myEntityService;
    
       @RequestMapping(method = RequestMethod.POST, produces = "text/html")     
       public String create(@Validated({Account.ValidationStepOne.class}) MyEntity myEntity,
            BindingResult bindingResult, Model uiModel,
            HttpServletRequest httpServletRequest) {
    
           // ... check binding result
           myEntityService.save(myEntity);    
           //...
        }
    }
    
    @Service
    public MyEntityService {
    
       @PreAuthorize("hasPermission(#myEntity, 'create')")
       public save(MyEntity myEntity) {
          //...
          myEntity.setCreationDate(new Date());
          myEntity.persist();          
       }
    }
    

    Good luck!