Java 自定义验证器消息:在 ConstraintValidator 的实现中引发异常导致 UnexpectedException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19825563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 20:30:33  来源:igfitidea点击:

Custom validator message: Throwing exception in implementation of ConstraintValidator cause UnexpectedException

javaspringvalidation

提问by pbaranski

So I have custom validator and when I set returnvalue to falsethen it works -

所以我有自定义验证器,当我设置return值时,false它就可以工作了 -

import com.vhealth.api.service.UserService;
import com.vhealth.api.utils.exceptions.InvalidPayloadException;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;


public class UserNameUniqueValidator implements ConstraintValidator<UserNameUnique, String> {
    @Autowired
    UserService userService;

    @Override
    public void initialize(UserNameUnique constraintAnnotation) {
    }

    @Override
    public boolean isValid(String userName, ConstraintValidatorContext context) {
        if (userService.findByUserName(userName) != null) {
            throw new InvalidPayloadException("Creating user requires unique userName new");
            //return false;
        }
        return true;
    }
}

But when I try throw exception in that section I get error that problem is caused by my custom exception:

但是当我在该部分尝试抛出异常时,我收到错误消息,该问题是由我的自定义异常引起的:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ValidationException: Unexpected exception during isValid call
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:932)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:66)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:168)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:136)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:136)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:134)
    at com.vhealth.api.controller.ApiUserControllerTest.shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName(ApiUserControllerTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access
    @ExceptionHandler(InvalidPayloadException.class)
public ResponseEntity handleEmptyFieldException(InvalidPayloadException ex) {
    return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
0(ParentRunner.java:50) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Caused by: javax.validation.ValidationException: Unexpected exception during isValid call at org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:281) at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:153) at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:117) at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:84) at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:452) at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:397) at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:361) at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:313) at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139) at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:102) at org.springframework.validation.DataBinder.validate(DataBinder.java:772) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.validate(RequestResponseBodyMethodProcessor.java:115) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:101) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920) ... 68 more Caused by: com.vhealth.api.utils.exceptions.InvalidPayloadException: Creating user requires unique userName new at com.vhealth.api.utils.validators.UserNameUniqueValidator.isValid(UserNameUniqueValidator.java:22) at com.vhealth.api.utils.validators.UserNameUniqueValidator.isValid(UserNameUniqueValidator.java:11) at org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:278) ... 90 more

Exception is placed in @Controller ExceptionResolover

异常被放置在 @Controller ExceptionResolover

@Override
public boolean isValid(String userName, ConstraintValidatorContext context) {
    if (userService.findByUserName(userName) != null) {
        context.disableDefaultConstraintViolation();
        context
            .buildConstraintViolationWithTemplate("User " + userName + "already exists!")
            .addConstraintViolation();
        return false;
    }
    return true;
}

Edit: Throwing InvalidPayloadExceptionexception in UserNameUniqueValidatorreturns custom message so I avoid to use BindingResultin main controller for extraction default message from validaor

编辑:InvalidPayloadExceptionUserNameUniqueValidator返回自定义消息中抛出异常,因此我避免BindingResult在主控制器中使用以从中提取默认消息validaor

采纳答案by mchrobok

If you want to display custom message try this piece of code.

如果您想显示自定义消息,请尝试这段代码。

Caused by: com.vhealth.api.utils.exceptions.InvalidPayloadException: Creating user requires unique userName new
    at com.vhealth.api.utils.validators.UserNameUniqueValidator.isValid(UserNameUniqueValidator.java:22)
    at com.vhealth.api.utils.validators.UserNameUniqueValidator.isValid(UserNameUniqueValidator.java:11)
at org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:278)
... 90 more

回答by Acewin

Are you getting any compiler error. Please check the error thrown is

您是否收到任何编译器错误。请检查抛出的错误是

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ValidationException: Unexpected exception during isValid call
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:932)

I think it only means that exception you have thrown is a Nested exception

我认为这仅意味着您抛出的异常是嵌套异常

Also check the stacktrace at com.vhealth.api.controller.ApiUserControllerTest.shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName(ApiUserControllerTest.java:53)

还要检查 com.vhealth.api.controller.ApiUserControllerTest.shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName(ApiUserControllerTest.java:53) 上的堆栈跟踪

@Override
public boolean isValid(String userName, ConstraintValidatorContext context) {
    if (userService !=null && userService.findByUserName(userName) != null) {
        context.disableDefaultConstraintViolation();
        context
            .buildConstraintViolationWithTemplate("User " + userName + "already exists!")
            .addConstraintViolation();
        return false;
    }
    return true;
}

回答by Dan

You can add not null check! You can still follow [mchrobok] answer I think better will be:

您可以添加非空检查!您仍然可以按照 [mchrobok] 回答我认为更好的是:

##代码##