madhairsilence
madhairsilence

Reputation: 3870

Spring data rest - Handle entity validation

This is the Code

Person.java

@Entity
class Person {
   @Id private Long Id;
   @NotNull private String name;
   //getter setters
}

PersonRepository.java

@RepositoryRestResource(collectionResourceRel = "person", path="person" )
interface PersonRepository extends CrudRepository<Person,Long>{
}

Now, when I send null against name attribute , the validator validates it correctly, but the actual exception that is getting thrown is TransactionRollbackExecption.

Like this

{
    "timestamp": "2018-03-14T09:01:08.533+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction",
    "path": "/peron"
}

How do I get the actual ConstraintViolation exception. I do see the exception in logs. But its not getting thrown.

Upvotes: 4

Views: 1881

Answers (2)

hovanessyan
hovanessyan

Reputation: 31433

The reason for this is that Spring's TransactionInterceptor is overriding your exception.

The idiomatic way of implementing repository entity validation, according to Spring's documentation, is to use Spring Data Rest Events. You probably want to use BeforeSaveEvent or BeforeCreateEvent.

You can create a custom type-safe handler for entities (see the provided link for details), which looks similar to:

@RepositoryEventHandler 
public class PersonEventHandler {

  @HandleBeforeSave
  public void handlePersonSave(Person p) {
    // … you can now deal with Person in a type-safe way
  }
}

Another approach is to register a Repository Listener which extends AbstractRepositoryEventListener, also described in the documentation.

Upvotes: 1

Cepr0
Cepr0

Reputation: 30309

You can add LocalValidatorFactoryBean to ValidatingRepositoryEventListener when configuring RepositoryRestConfigurerAdapter, like this:

@Configuration
public class RepoRestConfig extends RepositoryRestConfigurerAdapter {

    private final LocalValidatorFactoryBean beanValidator;

    public RepoRestConfig(LocalValidatorFactoryBean beanValidator) {
        this.beanValidator = beanValidator;
    }

    @Override
    public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
        v.addValidator("beforeCreate", beanValidator);
        v.addValidator("beforeSave", beanValidator);
        super.configureValidatingRepositoryEventListener(v);
    }
}

Upvotes: 1

Related Questions