问题
I have a ConstraintViolationException
handler class that looks like this:
@Produces
@Singleton
@Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
public class ConstraintsViolationsExceptionHandler
implements ExceptionHandler<ConstraintViolationException, HttpResponse> {
@Override
public HttpResponse
handle(HttpRequest request, ConstraintViolationException exception) {
return HttpResponse
.status(HttpStatus.FORBIDDEN)
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8")
.body(new SignUpPhoneNumberErrorResponse<>(400,
"Wrong data used",
new ArrayList<>(exception.getConstraintViolations())));
}
}
where SignUpPhoneNumberErrorResponse
is my error handling POJO which is getting serialized to JSON absolutely fine.
My Controller looks like this:
@Controller(PhoneAuthAndLoginConstants.CONTROLLER_BASE_PATH)
@Validated
public class UserPhoneNumberRegistrationAndLoginController {
@Inject
MongoDbUserSignUpPhoneNumberDAO mongoDbUserSignUpPhoneNumberDAO;
@Post(uri = PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_PATH,
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON)
public Single<ResponseDataEncapsulate>
signUpForPhoneVerification(@Valid @Body UserSignUpPhoneNumberEntity phoneNumber) {
return mongoDbUserSignUpPhoneNumberDAO.sendVerification(phoneNumber);
}
@Post(uri = PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_PATH
+
PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_VERIFICATION_CODE_PARAM,
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON)
public Single<ResponseDataEncapsulate>
sendUserSignUpConfirmation(@Valid @Body UserAccountStateSignUpEntity verificationData,
HttpHeaders httpHeaders) {
return mongoDbUserSignUpPhoneNumberDAO.signUp(verificationData);
}
}
My POJO for UserAccountStateSignUpEntity
looks like this:
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserAccountStateSignUpEntity implements UserSignUpEntity {
@NotNull @NotBlank @Size(min = 5, max = 13) private String phoneNumber;
@NotNull @NotBlank @Size(min = 7, max = 7) private String verificationCode;
@JsonIgnore private Boolean verifiedAccount = Boolean.FALSE;
public UserAccountStateSignUpEntity(String phoneNumber, String verificationCode) {
this.phoneNumber = phoneNumber;
this.verificationCode = verificationCode;
this.verifiedAccount = Boolean.TRUE;
}
@Override
public Map<String, Object> makePhoneEntityMapForMongo() {
HashMap<String, Object> returnMap = new HashMap<String, Object>() {{
put("phoneNumber", phoneNumber);
put("verificationCode", verificationCode);
put("verifiedAccount", verifiedAccount);
}};
return Collections.unmodifiableMap(returnMap);
}
}
I send in a request payload like this:
{
"phoneNumber" : "91-123456789",
"verificationCode" : "18887"
}
This should trigger a ConstraintViolationException
and my handler code should execute and I should get a HTTP Forbidden. But instead I get the default HTTP Bad Request error message.
Why isn't my handler getting executed? What can be done to make it execute?
I'm using Micronaut 1.1.3 as the web framework and the Hibernate Validator as the javax.validation
implementation.
回答1:
@Error that can be applied to method to map it to an error route and SignUpPhoneNumberErrorResponse would be returned as a error response body when any ConstraintViolationException occured.
For more detail visit Micronaut docs
@Controller("/${path}")
@Validated
public class UserPhoneNumberRegistrationAndLoginController {
@Post
public HttpResponse method(@Valid @Body UserAccountStateSignUpEntity verificationData, HttpHeaders httpHeaders) {
return null;
}
@Error(exception = ConstraintViolationException.class)
public SignUpPhoneNumberErrorResponse onSavedFailed(HttpRequest request, ConstraintViolationException ex) {
return new SignUpPhoneNumberErrorResponse(500,
"Wrong data used",
String.valueOf(ex.getConstraintViolations().stream().map( e -> e.getPropertyPath()+": "+e.getMessage()).collect(Collectors.toList())),
"Application",
"Error",
System.currentTimeMillis());
}
@Error(status = HttpStatus.NOT_FOUND, global = true)
public HttpResponse notFound(HttpRequest request) {
//return custom 404 error body
}
}
回答2:
I removed the @Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
annotation and replaced the ArrayList<>
in the body with a comma separated string and it started to work fine. Although I do not know the consequences of removing the annotation.
回答3:
I recently had the same problem with error handling in Micronaut. As I figured out, there is not a org.hibernate.exception.ConstraintViolationException
thrown, but a javax.persistence.PersistenceException
.
For me, then it worked with @Error(exception = PersistenceException::class)
(Kotlin).
回答4:
@Error
annotation handling for ConstraintViolationException
worked for me only when it is on controller.
In the end managed to handle it like this, by replacing the micronaut ConstraintExceptionHandler
bean:
@Produces
@Replaces(io.micronaut.validation.exceptions.ConstraintExceptionHandler.class)
@Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
public class ConstraintExceptionHandler extends io.micronaut.validation.exceptions.ConstraintExceptionHandler {
@Override
public HttpResponse handle(HttpRequest request, ConstraintViolationException exception) {
return return HttpResponse
.badRequest();
}
}
来源:https://stackoverflow.com/questions/56676486/constraintviolationexception-handler-isnt-executed-in-micronaut