Skip to content

Commit

Permalink
Resteasy 1753: Bean validation handler should not swallow ConstraintD…
Browse files Browse the repository at this point in the history
…efinitionException, ConstraintDeclarationException nor GroupDefinitionException (#1346)

* Test enrichment

Signed-off-by: NicoNes <nicolas.nesmon@gmail.com>

* Bean validation handler should not swallow javax.validation.ConstraintDefinitionException,
 javax.validation.ConstraintDeclarationException nor GroupDefinitionException

Signed-off-by: NicoNes <nicolas.nesmon@gmail.com>

* Update ValidationExceptionsTest.java

* Update GeneralValidatorImpl.java

* Update GeneralValidatorImpl.java
  • Loading branch information
NicoNes authored and ronsigal committed Dec 16, 2017
1 parent 0a44130 commit 3c3f42f
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
import java.util.Set;

import javax.enterprise.context.ApplicationScoped;
import javax.validation.ConstraintDeclarationException;
import javax.validation.ConstraintDefinitionException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.GroupDefinitionException;
import javax.validation.MessageInterpolator;
import javax.validation.ValidationException;
import javax.validation.Validator;
Expand Down Expand Up @@ -106,14 +109,25 @@ public void validate(HttpRequest request, Object object, Class<?>... groups)
SimpleViolationsContainer violationsContainer = getViolationsContainer(request, object);
violationsContainer.setException(e);
violationsContainer.setFieldsValidated(true);
throw new ResteasyViolationException(violationsContainer);
throw toValidationException(e, violationsContainer);
}

SimpleViolationsContainer violationsContainer = getViolationsContainer(request, object);
violationsContainer.addViolations(cvs);
violationsContainer.setFieldsValidated(true);
}

private ValidationException toValidationException(Exception exception, SimpleViolationsContainer simpleViolationsContainer)
{
if (exception instanceof ConstraintDeclarationException ||
exception instanceof ConstraintDefinitionException ||
exception instanceof GroupDefinitionException)
{
return (ValidationException) exception;
}
return new ResteasyViolationException(simpleViolationsContainer);
}

@Override
public void checkViolations(HttpRequest request)
{
Expand Down Expand Up @@ -165,7 +179,7 @@ public void validateAllParameters(HttpRequest request, Object object, Method met
catch (Exception e)
{
violationsContainer.setException(e);
throw new ResteasyViolationException(violationsContainer);
throw toValidationException(e, violationsContainer);
}
violationsContainer.addViolations(cvs);
if ((violationsContainer.isFieldsValidated()
Expand All @@ -191,7 +205,7 @@ public void validateReturnValue(HttpRequest request, Object object, Method metho
catch (Exception e)
{
violationsContainer.setException(e);
throw new ResteasyViolationException(violationsContainer);
throw toValidationException(e, violationsContainer);
}
violationsContainer.addViolations(cvs);
if (violationsContainer.size() > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.jboss.arquillian.container.test.api.OperateOnDeployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.resteasy.api.validation.ResteasyConstraintViolation;
import org.jboss.resteasy.api.validation.ResteasyViolationException;
import org.jboss.resteasy.api.validation.Validation;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
Expand All @@ -17,6 +18,7 @@
import org.jboss.resteasy.test.validation.resource.ValidationExceptionCrazyConstraint;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionCrazyValidator;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionIncorrectConstraint;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionMapper;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionOtherConstraint;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionOtherValidationException;
import org.jboss.resteasy.test.validation.resource.ValidationExceptionOtherValidationException2;
Expand All @@ -42,6 +44,8 @@

import static org.jboss.resteasy.utils.PortProviderUtil.generateURL;

import java.util.List;

/**
* @tpSubChapter Validator provider
* @tpChapter Integration tests
Expand All @@ -55,8 +59,11 @@ public class ValidationExceptionsTest {
static ResteasyClient client;

private static final String DEF_EXCEPTION = "constraintDefinitionException";
private static final String CUSTOM_DEF_EXCEPTION = "customConstraintDefinitionException";
private static final String DECL_EXCEPTION = "constraintDeclarationException";
private static final String CUSTOM_DECL_EXCEPTION = "customConstraintDeclarationException";
private static final String GROUP_DEF_EXCEPTION = "groupDefinitionException";
private static final String CUSTOM_GROUP_DEF_EXCEPTION = "customGroupDefinitionException";
private static final String OTHER_EXCEPTION = "otherException";
private static final String CRAZY_EXCEPTION = "crazyException";
private static final String ERROR_MESSAGE = "Expected other response";
Expand All @@ -76,6 +83,7 @@ public static Archive<?> deploy(String name, Class<?>... resourceClasses) throws
war.addClass(ValidationExceptionOtherValidator.class);
war.addClass(ValidationExceptionTestGroup1.class);
war.addClass(ValidationExceptionTestGroup2.class);
war.addClass(ValidationExceptionMapper.class);
return TestUtil.finishContainerPrepare(war, null, resourceClasses);
}

Expand All @@ -94,16 +102,35 @@ public static Archive<?> constraintDefinitionExceptionDeploy() throws Exception
return deploy(DEF_EXCEPTION, ValidationExceptionResourceWithIncorrectConstraint.class);
}

@Deployment(name = CUSTOM_DEF_EXCEPTION)
public static Archive<?> customConstraintDefinitionExceptionDeploy() throws Exception {
return deploy(CUSTOM_DEF_EXCEPTION, ValidationExceptionResourceWithIncorrectConstraint.class,
ValidationExceptionResourceWithIncorrectConstraint.ConstraintDefinitionExceptionMapper.class);
}

@Deployment(name = DECL_EXCEPTION)
public static Archive<?> constraintDeclarationExceptionDeploy() throws Exception {
return deploy(DECL_EXCEPTION, ValidationExceptionSubResourceWithInvalidOverride.class, ValidationExceptionSuperResource.class);
}

@Deployment(name = CUSTOM_DECL_EXCEPTION)
public static Archive<?> customConstraintDeclarationExceptionDeploy() throws Exception {
return deploy(CUSTOM_DECL_EXCEPTION, ValidationExceptionSubResourceWithInvalidOverride.class,
ValidationExceptionSuperResource.class,
ValidationExceptionSubResourceWithInvalidOverride.ConstraintDeclarationExceptionMapper.class);
}

@Deployment(name = GROUP_DEF_EXCEPTION)
public static Archive<?> groupDefinitionExceptionDeploy() throws Exception {
return deploy(GROUP_DEF_EXCEPTION, ValidationExceptionResourceWithInvalidConstraintGroup.class);
}

@Deployment(name = CUSTOM_GROUP_DEF_EXCEPTION)
public static Archive<?> customGroupDefinitionExceptionDeploy() throws Exception {
return deploy(CUSTOM_GROUP_DEF_EXCEPTION, ValidationExceptionResourceWithInvalidConstraintGroup.class,
ValidationExceptionResourceWithInvalidConstraintGroup.GroupDefinitionExceptionMapper.class);
}

@Deployment(name = OTHER_EXCEPTION)
public static Archive<?> otherExceptionDeploy() throws Exception {
return deploy(OTHER_EXCEPTION, ValidationExceptionResourceWithOther.class);
Expand Down Expand Up @@ -131,6 +158,21 @@ public void testConstraintDefinitionException() throws Exception {
Assert.assertTrue(ERROR_MESSAGE, entity.contains("ConstraintDefinitionException"));
}

@Test
@OperateOnDeployment(CUSTOM_DEF_EXCEPTION)
public void testCustomConstraintDefinitionException() throws Exception {
Response response = client.target(generateURL("/", CUSTOM_DEF_EXCEPTION)).request().post(null);
Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus());
String header = response.getStringHeaders().getFirst(Validation.VALIDATION_HEADER);
Assert.assertNotNull(ERROR_HEADER_MESSAGE, header);
Assert.assertTrue(ERROR_HEADER_VALIDATION_EXCEPTION_MESSAGE, Boolean.valueOf(header));
String entity = response.readEntity(String.class);
logger.info("entity: " + entity);
Assert.assertTrue(ERROR_MESSAGE, entity.contains("ConstraintDefinitionException"));
Assert.assertTrue(ERROR_MESSAGE,
entity.contains(ValidationExceptionResourceWithIncorrectConstraint.ConstraintDefinitionExceptionMapper.class.getName()));
}

/**
* @tpTestDetails Resource with incorrect constraint declaration, constraint definition exception is expected
* @tpSince RESTEasy 3.0.16
Expand All @@ -147,6 +189,22 @@ public void testConstraintDeclarationException() throws Exception {
logger.info("entity: " + entity);
Assert.assertTrue(ERROR_MESSAGE, entity.contains("ConstraintDeclarationException"));
}

@Test
@OperateOnDeployment(CUSTOM_DECL_EXCEPTION)
public void testCustomConstraintDeclarationException() throws Exception {
Response response = client.target(generateURL("/", CUSTOM_DECL_EXCEPTION)).request().post(null);
Assert.assertEquals(TestUtil.getErrorMessageForKnownIssue("JBEAP-3459"),
HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus());
String header = response.getStringHeaders().getFirst(Validation.VALIDATION_HEADER);
Assert.assertNotNull(ERROR_HEADER_MESSAGE, header);
Assert.assertTrue(ERROR_HEADER_VALIDATION_EXCEPTION_MESSAGE, Boolean.valueOf(header));
String entity = response.readEntity(String.class);
logger.info("entity: " + entity);
Assert.assertTrue(ERROR_MESSAGE, entity.contains("ConstraintDeclarationException"));
Assert.assertTrue(ERROR_MESSAGE,
entity.contains(ValidationExceptionSubResourceWithInvalidOverride.ConstraintDeclarationExceptionMapper.class.getName()));
}

/**
* @tpTestDetails Resource with incorrect group definition, group definition exception is expected
Expand All @@ -165,6 +223,21 @@ public void testGroupDefinitionException() throws Exception {
Assert.assertTrue(ERROR_MESSAGE, entity.contains("GroupDefinitionException"));
}

@Test
@OperateOnDeployment(CUSTOM_GROUP_DEF_EXCEPTION)
public void testCustomGroupDefinitionException() throws Exception {
Response response = client.target(generateURL("/", CUSTOM_GROUP_DEF_EXCEPTION)).request().get();
Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus());
String header = response.getStringHeaders().getFirst(Validation.VALIDATION_HEADER);
Assert.assertNotNull(ERROR_HEADER_MESSAGE, header);
Assert.assertTrue(ERROR_HEADER_VALIDATION_EXCEPTION_MESSAGE, Boolean.valueOf(header));
String entity = response.readEntity(String.class);
logger.info("entity: " + entity);
Assert.assertTrue(ERROR_MESSAGE, entity.contains("GroupDefinitionException"));
Assert.assertTrue(ERROR_MESSAGE,
entity.contains(ValidationExceptionResourceWithInvalidConstraintGroup.GroupDefinitionExceptionMapper.class.getName()));
}

/**
* @tpTestDetails Tests for: Exception thrown during validation of field, Exception thrown during validation of parameter,
* Exception thrown during validation of return value, Exception thrown by resource method
Expand Down Expand Up @@ -237,8 +310,11 @@ public void testCrazyMessage() throws Exception {
String header = response.getStringHeaders().getFirst(Validation.VALIDATION_HEADER);
Assert.assertNotNull(ERROR_HEADER_MESSAGE, header);
Assert.assertTrue(ERROR_HEADER_VALIDATION_EXCEPTION_MESSAGE, Boolean.valueOf(header));
String entity = response.readEntity(String.class);
logger.info("entity: " + entity);
ResteasyViolationException e = new ResteasyViolationException(entity);
ResteasyViolationException resteasyViolationException = new ResteasyViolationException(
response.readEntity(String.class));
List<ResteasyConstraintViolation> classViolations = resteasyViolationException.getClassViolations();
Assert.assertEquals(1, classViolations.size());
Assert.assertEquals(ValidationExceptionCrazyConstraint.DEFAULT_MESSAGE, classViolations.get(0).getMessage());
logger.info("entity: " + resteasyViolationException);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
@Target({FIELD, METHOD, PARAMETER, TYPE})
@Retention(RUNTIME)
public @interface ValidationExceptionCrazyConstraint {
String message() default "a[][]][][b";

String DEFAULT_MESSAGE="a[][]][][b";

String message() default DEFAULT_MESSAGE;

Class<?>[] groups() default {};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.jboss.resteasy.test.validation.resource;

import javax.validation.ValidationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;

import org.jboss.resteasy.api.validation.Validation;

/**
*
* @author Nicolas NESMON
*
*/
public abstract class ValidationExceptionMapper<T extends ValidationException> implements ExceptionMapper<T> {

@Override
public Response toResponse(T validationException) {
ResponseBuilder builder = Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(getClass().getName() + ":" + validationException.getMessage());
builder.type(MediaType.TEXT_PLAIN);
builder.header(Validation.VALIDATION_HEADER, "true");
return builder.build();
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package org.jboss.resteasy.test.validation.resource;

import javax.validation.ConstraintDefinitionException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;

@Path("/")
@ValidationExceptionIncorrectConstraint
public class ValidationExceptionResourceWithIncorrectConstraint {

@Provider
public static class ConstraintDefinitionExceptionMapper extends ValidationExceptionMapper<ConstraintDefinitionException> {
}

@POST
public void test() {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package org.jboss.resteasy.test.validation.resource;

import javax.validation.GroupDefinitionException;
import javax.validation.GroupSequence;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;

@Path("/")
@GroupSequence({ValidationExceptionTestGroup1.class, ValidationExceptionTestGroup2.class})
public class ValidationExceptionResourceWithInvalidConstraintGroup {

@Provider
public static class GroupDefinitionExceptionMapper extends ValidationExceptionMapper<GroupDefinitionException> {
}

private String s;

@GET
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package org.jboss.resteasy.test.validation.resource;

import javax.validation.ConstraintDeclarationException;
import javax.validation.constraints.Size;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;

@Path("/")
public class ValidationExceptionSubResourceWithInvalidOverride extends ValidationExceptionSuperResource {

@Provider
public static class ConstraintDeclarationExceptionMapper extends ValidationExceptionMapper<ConstraintDeclarationException> {
}

@POST
public void test(@Size(max = 3) String s) {
}
Expand Down

0 comments on commit 3c3f42f

Please sign in to comment.