Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring data rest and business rules validation

I want to seek a best practice for applying business rules when working with spring data rest.

Lets consider following scenario:

  • I have a Customer and Order in @OneToMany relationship.
  • I have a business rule saying that Customer needs to have verified flag set to be able to make orders

So I need to make sure that whenever someone POSTs to /orders the Customer making the call is verified.

I'm considering using beforeSave Validators autowiring other service/repositories into the Validator and check whatever needs to be checked.

Is there better way of achieving the same?

like image 415
Jan Zyka Avatar asked Feb 15 '18 09:02

Jan Zyka


2 Answers

There are several ways to solve this. As far as my knowledge goes:

  1. Usage of spring security annotations like @PreAuthorize. The intended use of these annotations is however for security purposes and you are mentioning business rules. I would use these for user authorization rules Spring data rest security chapter

  2. The use of validators as you mentioned yourself. Spring data rest Validators

  3. Use spring data rest events Spring data rest events. You can create global event handlers, however here you need to determine the entity type. I would go with Annotated event handlers to perform business logic Spring data rest annotated event handler

like image 69
Konstantin Avatar answered Oct 10 '22 17:10

Konstantin


So just for the sake of world piece I'm adding my solution. Went with #2.

The documentation is pretty clear on how to proceed so just sharing few tips which may save you time.

  1. You need to assign validators manually, auto-discovery doesn't work
  2. Manually spelling event type is error prone, some helper Enum could be handy.

Like:

/** 
 * "beforeSave" gets called on PATCH/PUT methods
 * "beforeCreate" on POST
 * "beforeDelete" on DELETE
 */
enum Event {
    ON_CREATE("beforeCreate"), ON_UPDATE("beforeSave"), 
 ON_DELETE("beforeDelete");

    private String name;

    Event(String name) {
        this.name = name;
    }
} 

...

private static void addValidatorForEvents(ValidatingRepositoryEventListener eventListener, Validator validator, Event... events) {
    Arrays.asList(events).forEach(event -> eventListener.addValidator(event.name, validator));
}
like image 29
Jan Zyka Avatar answered Oct 10 '22 17:10

Jan Zyka