using validators in spring-data-rest returns http

2020-06-03 01:40发布

问题:

I'm trying to get the validation in spring-data-rest to work. From the documentation you only need to make a validator available, and I've got that to work, but when a validation constraint is successfully caught/processed I get a 500 error page with the stack trace.

In the config class, RepositoryRestMvcConfiguration it has a validationExceptionHandler which looks like it should get such validation errors to return as 400 rather than 500. It is also a lazy loaded bean.

Do I have an incorrect setup? or is there another way to get spring-data-rest to return 400 instead of 500?

I'm using spring-data-rest version 2.0.0 Release

Stack trace return by tomcat:

HTTP Status 500 - Request processing failed; nested exception is javax.validation.ConstraintViolationException: Validation failed for classes [test.domain.Account] during persist time for groups [javax.validation.groups.Default, ]

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ConstraintViolationException: Validation failed for classes [test.domain.Account] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='size must be between 0 and 10', propertyPath=login, rootBeanClass=class test.domain.Account, messageTemplate='{javax.validation.constraints.Size.message}'}
]
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

Account Entity:

@Entity
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    @Column(unique = true)
    @Size(max = 10)
    String login;

}

RestMvcConfig:

@Configuration
public class RestExporterRestConfig extends RepositoryRestMvcConfiguration {}

回答1:

Seem to have got it working; i had to override the validatingRepositoryEventListener() and manually add validators to the listener;

@Configuration
public class RestExporterRestConfig extends RepositoryRestMvcConfiguration {

    @Bean
    public Validator validator() {
        return new LocalValidatorFactoryBean();
    }

    @Bean
    @Override
    public ValidatingRepositoryEventListener validatingRepositoryEventListener() {
        ValidatingRepositoryEventListener listener = new ValidatingRepositoryEventListener();
        configureValidatingRepositoryEventListener(listener);
        listener.addValidator("afterCreate", validator());
        listener.addValidator("beforeCreate", validator());
        return listener;
    }

}

I now get a 400 returned as follows;

400 Bad Request
{"errors":
    [{  "entity":"Account",
        "message":"size must be between 0 and 10",
        "invalidValue":"login 0dsfdsfdsfdsfdsfdsfdsfds",
        "property":"login"
    }]
}


回答2:

The previous answers didn't work for me, I think due to changes in Spring Data Rest so here is an updated answer that did work with JPA and MongoDb to save anyone else spending ages on this.

Had to add this to my build.gradle dependencies

    compile('org.hibernate:hibernate-validator:4.2.0.Final')

and this config class

@Configuration
public class CustomRepositoryRestConfigurerAdapter extends RepositoryRestConfigurerAdapter {


   @Bean
   public Validator validator() {
       return new LocalValidatorFactoryBean();
   }

   @Override
   public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
       validatingListener.addValidator("afterCreate", validator());
       validatingListener.addValidator("beforeCreate", validator());
       validatingListener.addValidator("afterSave", validator());
       validatingListener.addValidator("beforeSave", validator());
   }
}