io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyReactiveViolationExceptionMapper Maven / Gradle / Ivy
package io.quarkus.hibernate.validator.runtime.jaxrs;
import static io.quarkus.hibernate.validator.runtime.jaxrs.ValidatorMediaTypeUtil.SUPPORTED_MEDIA_TYPES;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ElementKind;
import javax.validation.Path;
import javax.validation.ValidationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.reactive.common.util.ServerMediaType;
import org.jboss.resteasy.reactive.server.core.CurrentRequestManager;
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
@Provider
public class ResteasyReactiveViolationExceptionMapper implements ExceptionMapper {
private static final String VALIDATION_HEADER = "validation-exception";
@Override
public Response toResponse(ValidationException exception) {
if (!(exception instanceof ResteasyReactiveViolationException)) {
// Not a violation in a REST endpoint call, but rather in an internal component.
// This is an internal error: handle through the QuarkusErrorHandler,
// which will return HTTP status 500 and log the exception.
throw exception;
}
ResteasyReactiveViolationException resteasyViolationException = (ResteasyReactiveViolationException) exception;
if (hasReturnValueViolation(resteasyViolationException.getConstraintViolations())) {
// This is an internal error: handle through the QuarkusErrorHandler,
// which will return HTTP status 500 and log the exception.
throw resteasyViolationException;
}
return buildViolationReportResponse(resteasyViolationException);
}
private boolean hasReturnValueViolation(Set> violations) {
if (violations != null) {
for (ConstraintViolation> violation : violations) {
if (isReturnValueViolation(violation)) {
return true;
}
}
}
return false;
}
private boolean isReturnValueViolation(ConstraintViolation> violation) {
Iterator nodes = violation.getPropertyPath().iterator();
Path.Node firstNode = nodes.next();
if (firstNode.getKind() != ElementKind.METHOD) {
return false;
}
Path.Node secondNode = nodes.next();
return secondNode.getKind() == ElementKind.RETURN_VALUE;
}
private Response buildViolationReportResponse(ConstraintViolationException cve) {
Status status = Status.BAD_REQUEST;
Response.ResponseBuilder builder = Response.status(status);
builder.header(VALIDATION_HEADER, "true");
var rrContext = CurrentRequestManager.get();
// Check standard media types.
MediaType mediaType = ValidatorMediaTypeUtil.getAcceptMediaType(
rrContext.getHttpHeaders().getAcceptableMediaTypes(),
serverMediaTypes(rrContext));
if (mediaType == null) {
mediaType = MediaType.APPLICATION_JSON_TYPE;
}
List violationsInReport = new ArrayList<>(cve.getConstraintViolations().size());
for (ConstraintViolation> cv : cve.getConstraintViolations()) {
violationsInReport.add(new ViolationReport.Violation(cv.getPropertyPath().toString(), cv.getMessage()));
}
builder.entity(new ViolationReport("Constraint Violation", status, violationsInReport));
builder.type(mediaType);
return builder.build();
}
private List serverMediaTypes(ResteasyReactiveRequestContext context) {
if (context.getTarget() == null) {
return SUPPORTED_MEDIA_TYPES;
}
ServerMediaType serverMediaType = context.getTarget().getProduces();
if (serverMediaType == null) {
return SUPPORTED_MEDIA_TYPES;
}
return Arrays.asList(serverMediaType.getSortedMediaTypes());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy