2

Any Body explain me why isValid() method of ConstraintValidator class called twice ?
for example this is my example code :

@POST
@Path("/json/dog")
@Produces("application/json")
@Consumes("application/json")
public Response getDogByJson(@ValidAnimal JsonObject jsonObject) {
      return Response.ok("ok").build();
}



@Constraint(validatedBy = {AnimalValidation.class})
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ValidAnimal {

    String message() default "This is not valid !";

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

    Class<? extends Payload>[] payload() default { };
}   



public class AnimalValidation implements ConstraintValidator<ValidAnimal, JsonObject> {

    @Override
    public void initialize(ValidAnimal constraintAnnotation) {

    }

    @Override
    public boolean isValid(JsonObject jsonObject, ConstraintValidatorContext context) {
        System.out.println(">>>>>> : " + jsonObject);
        return true;
    }
}

When i send request to this web service isValid() method call double time .
Why ?

Note : I use OpenLiberty 18.0.0.3 with JavaEE 8

Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
mah454
  • 1,571
  • 15
  • 38
  • seems odd, as a debug step can you add `Thread.dumpStackTrace()` inside `isValid()` to see what is calling it? Also, what features do you have enabled in server.xml? – Andy Guibert Dec 18 '18 at 19:05

2 Answers2

5

I did a quick test and confirmed the behavior you are noticing. It looks like the first time is from the JAX-RS runtime calling validate, and then the CDI runtime calls validate also (since JAX-RS resources are also CDI beans). I'm looking into whether or not we can make JAX-RS avoid the call if OpenLiberty can detect that a CDI feature is enabled.

When I enable these features, isValid() only gets called once by JAX-RS:

<featureManager>
    <feature>jaxrs-2.1</feature>
    <feature>jsonp-1.1</feature>
    <feature>beanValidation-2.0</feature>
</featureManager>

at com.ibm.ws.jaxrs20.server.LibertyJaxRsInvoker.callValidationMethod(LibertyJaxRsInvoker.java:371)

But when we enable a CDI feature, the CDI runtime calls isValid() also:

<featureManager>
    <feature>jaxrs-2.1</feature>
    <feature>jsonp-1.1</feature>
    <feature>beanValidation-2.0</feature>
    <feature>cdi-2.0</feature>
</featureManager>

at org.hibernate.validator.cdi.internal.interceptor.ValidationInterceptor.validateMethodInvocation(ValidationInterceptor.java:66)
...
at com.ibm.ws.jaxrs20.server.LibertyJaxRsInvoker.performInvocation(LibertyJaxRsInvoker.java:160)

To summarize, this looks like a bug in OpenLiberty. An update should be made so that isValid() is only called once when JAX-RS and CDI features are enabled.

Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
0

I also confirm this bug on :
wildfly 14.
IBM Liberty 18.0.0.4.
Interesting tomee 8 has not this bug.

mah454
  • 1,571
  • 15
  • 38
  • I think this is also true for Payara 5.2020.6 (and likely below). I am finding the same behaviour running Bean Validations for a JAX-RS endpoint twice. The stacktrace seems to point for a JAX-RS invocation first and then as an interceptor (in my case the endpoint class is an EJB, but I think the point also applies). – CarlosGoncalves Mar 11 '21 at 12:32