Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validation doesn't work on OpenLiberty #293

Open
mthmulders opened this issue May 9, 2022 · 6 comments
Open

Validation doesn't work on OpenLiberty #293

mthmulders opened this issue May 9, 2022 · 6 comments
Labels
server:liberty Targets OpenLiberty server
Milestone

Comments

@mthmulders
Copy link
Contributor

Trying to build an application with Krazo on Jakarta EE 9, targeted to run on OpenLiberty. I'm using OpenLiberty 22.0.0.4, Krazo 2.0.1 (with the LibertyHttpCommunicationUnwrapper manually copied in).

The Controller that should process the form is a literal copy of the example in the MVC 2.0 spec.

I submit the form from the browser, but for convenience, this is the raw request:

curl 'http://localhost:9080/openliberty-mvc-validation/form/process' -X POST \
   -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \
   -H 'Accept-Language: en-GB,en;q=0.5' \
   -H 'Accept-Encoding: gzip, deflate, br' \
   -H 'Content-Type: application/x-www-form-urlencoded' \
   --data-raw 'age='

When I submit the form, I expect the Controller to be invoked, causing a) a log message to appear and b) hello.jsp to be rendered.

Instead, I get an XML response (formatted for reading convenience, the original response is unformatted):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<violationReport>
  <propertyViolations>
    <constraintType>PROPERTY</constraintType>
    <path>age</path>
    <message>must be greater than or equal to 18</message>
    <value>0</value>
  </propertyViolations>
</violationReport>

The good part is that the validation rules are applied to the input. The bad part is that the Controller is not invoked, and the user is seeing XML in their browser.

Please let me know if there's something I missed in the spec, something else I could try, or some additional information you might need.

Links:

@erdlet
Copy link
Member

erdlet commented May 10, 2022

Hi @mthmulders,

I could imagine the Accept: ..., application/xml causes the trouble. Are you receiving XML even if you remove this accepted content type? It'd be weird, as you defined a q-value, but not impossible.

Also I'll have a deeper look on your example later. Thanks for providing it!

@mthmulders
Copy link
Contributor Author

I've tried again, this time with

curl 'http://localhost:9080/openliberty-mvc-validation/form/process' -X POST \
   -H 'Accept: text/html' \
   -H 'Accept-Encoding: gzip, deflate, br' \
   -H 'Content-Type: application/x-www-form-urlencoded' \
   --data-raw 'age='

And it gives an empty response (-v shows that the response code is 400).

@erdlet
Copy link
Member

erdlet commented May 10, 2022

Thanks for testing this.

I'll have a look into that.

Unfortunately RESTEasy seems to work differently on OpenLiberty than in WildFly, so I have no clue what the problem could be.

@mthmulders
Copy link
Contributor Author

Unfortunately RESTEasy seems to work differently on OpenLiberty than in WildFly

Yes, I have noticed that before... If there's anything I could be of help with, please let me know.

@chkal
Copy link
Contributor

chkal commented May 15, 2022

@mthmulders What you are seeing in your reproducer project is actually the default behavior for JAX-RS when Bean Validation is provided by the runtime. In this case, requests are validated before the resource method is invoked and in case of validation errors, the request is aborted. This behavior definitely makes sense for plain JAX-RS.

As MVC requires a different behavior (controllers should always be invoked, regardless of whether a validation error occurred), Krazo has to use some "dirty" tricks. Especially, Krazo tries to veto the default CDI interceptor, which implements the behavior described above for all MVC controllers.

The interesting part of the code starts here:

// drop Hibernate Validator's marker annotations to skip the native validation
Predicate<Class> annotationBlacklist = this::isHibernateValidatorMarkerAnnotation;
if (ControllerUtils.isControllerMethod(method.getJavaMember())) {
log.log(Level.FINE, "Found controller method: {0}#{1}", new Object[]{
type.getJavaClass().getName(),
method.getJavaMember().getName()
});
return new AnnotatedMethodWrapper<>(method, markerAnnotations, annotationBlacklist);
}

If removing the CDI interceptor of bean validation does not work for some reason, you will get a behavior exactly like the one you are getting. Therefore, my guess is that our code needs some more adjustments to work correctly for Open Liberty.

@mthmulders
Copy link
Contributor Author

Thanks for the intro, @chkal. I've studied the Krazo code a bit and from what I understand, the code you've highlighted adds two annotations to existing controller methods:

  1. @ValidationInterceptorBinding - should be handled by the ValidationInterceptor.
  2. @AroundController - should be handled by the AroundControllerInterceptor.

The interesting thing I've observed is that for a GET request, first the ValidationInterceptor runs, and the AroundControllerInterceptor. For a POST request, none of them runs. I have added a custom validator to find a stacktrace of when the validations run - would that be of use to you?

@erdlet erdlet added the server:liberty Targets OpenLiberty server label Jun 20, 2022
@erdlet erdlet added this to the 3.1.0 milestone Aug 10, 2022
@erdlet erdlet modified the milestones: 3.1.0, Future Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
server:liberty Targets OpenLiberty server
Projects
None yet
Development

No branches or pull requests

3 participants