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

Feat/jooby hibernate validator #3508

Merged

Conversation

kliushnichenko
Copy link
Contributor

Still need some docs, tests, cleanup, but the basic logic seems done

@kliushnichenko kliushnichenko marked this pull request as draft August 24, 2024 12:55
@agentgt
Copy link
Contributor

agentgt commented Aug 24, 2024

@kliushnichenko @jknack

I'm not sure I like the name of jooby-validation if it is going to have a hard dependency on jakarta.validation. Is the plan to make the validation pluggable in that module and it is just jakarta for now?

Otherwise I think it should be jooby-jakarta-validation.

Also the jooby-apt module should not have any dependency on basically anything ideally. I haven't code dived to see why you made it that way. (you don't need the actual classes you depend on with generated code)

EDIT actually maybe you changed it. When you get a chance @kliushnichenko maybe squash the commits to one or two?

modules/jooby-apt/pom.xml Outdated Show resolved Hide resolved
modules/jooby-validation/pom.xml Outdated Show resolved Hide resolved
cleanup

cleanup

cleanup
@kliushnichenko kliushnichenko force-pushed the feat/jooby-hibernate-validator branch from 5f1dd9b to 646f355 Compare August 24, 2024 17:14
@SentryMan
Copy link
Contributor

The way I've done it with other libs I've worked was to have an extensible Validator interface which clients can extend to provide custom validation. Example hibernate impl and avaje validation impl . Perhaps you guys could try something similar if you want to eliminate the dependencies

@jknack
Copy link
Member

jknack commented Aug 24, 2024

@SentryMan thank you. I feel here isn't necessary to add another abstraction over the jakarta one. Leaving jakarta-validator outside of core is enough.

@kliushnichenko
Copy link
Contributor Author

Updated. Pls verify the changes and I'll proceed with the documentation

@kliushnichenko
Copy link
Contributor Author

@SentryMan could you pls shed some light on avaje-validator. I thought it is fully compliant with jakarta-validation-api. But I can't find how I can get the instance of jakarta.validation.Validator baked by avaje-validator. All the entry points are available only at your custom abstraction io.avaje.validation.Validator.

Is it a trade-off of a reflection-free solution or maybe you can provide us jakarta-compliant entry point in the future release?

@SentryMan
Copy link
Contributor

SentryMan commented Aug 26, 2024

Is it a trade-off of a reflection-free solution

Jakarta validation is mainly reflection-based so we couldn't fully implement its interfaces. Hence why we took a page from spring in our http solution by defining another abstraction so we could support both jakarta and avaje validation

Copy link
Member

@jknack jknack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good

modules/jooby-hbv/src/main/java/module-info.java Outdated Show resolved Hide resolved
public class PasswordsShouldMatchValidator implements ConstraintValidator<PasswordsShouldMatch, NewAccountRequest> {

@Override
public boolean isValid(NewAccountRequest request, ConstraintValidatorContext constraintContext) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to access to jooby registry from ConstraintValidatorContext?????

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how we can put it into ConstraintValidatorContext, but there are other options for accessing the registry. It is possible by implementing a custom ConstraintValidatorFactory .

I don't think we need to support it out of the box bc it most likely will require introducing another custom abstraction.
I can add an example in the docs of how to do this. Maybe it is good enough for now?

Additionally, if the project utilizes some DI it is not a problem to inject any service/repo/etc. into custom validator

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, if the project utilizes some DI it is not a problem to inject any service/repo/etc. into custom validator

An example of that on docs will be nice.

@kliushnichenko
Copy link
Contributor Author

Getting back to avaje-validator support...

As SentryMan clarified, there is no way to smoothly support both (hbv/avaje) relying solely on jakarta.validation.Validator
So, my initial plan didn't quite work out 😄

Options that are running through my mind in this regard:

  1. Write a custom implementation of the jakarta.validation.Validator that will trigger io.avaje.validation.Validator under the hood
    Concerns:
    way too odd. Everything except one method validate() will be stubbed as Unsupported.
    Also, it will hide the rest of avaje-validator options, not ok.

  2. Each module can implement its own helper for validation. In jooby-apt pick the one that is available in classpath.
    Concerns:
    Complicates jooby-apt, probably duplicates some logic in two places, error-prone, complicates further support.

  3. Introduce one more abstraction, as SentryMan pointed out, to cover jooby-apt logic over a single interface.
    Concerns:
    plus one more abstraction, a bit more cumbersome, but, seems the most acceptable compromise

@jknack what's your take on it? maybe some other options?

@jknack
Copy link
Member

jknack commented Aug 30, 2024

Seems 3 it is OK. jooby-apt should call io.jooby.validation.BeanValidator and extra logic goes here (jooby-jakarta-validation) and probably on the jooby-avaje-validator module.

So jooby-apt will do what is doing here, wrap the call around BeanValidator

@kliushnichenko
Copy link
Contributor Author

kliushnichenko commented Sep 1, 2024

Updated.

Please note the following:

  • since avaje-validator has its own set of custom entities (Validator, ConstraintViolation, ConstraintViolationException), the BeanValidator helper no longer relies on either jakarta or avaje entities, making the module even simpler.
  • for the same reason, error handlers should be implemented separately and placed in their corresponding modules.
  • jooby-jakarta-validation has been renamed back to jooby-validation since it no longer has any dependency on jakarta.
  • a new MvcValidator interface has been introduced to isolate BeanValidator logic from specific implementations. It includes a single validate() method that performs validation and throws an exception. The type of exception thrown depends on the implementation (Jakarta or Avaje).

Naming is getting tough with a lot of Validator abstractions, any suggestions are welcomed.
@jknack pls confirm we are good with this solution and can move on

Copy link
Member

@jknack jknack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few minor comments

"Unable to load 'BeanValidator' class. " +
"Bean validation usage (@Valid) was detected, but the appropriate dependency is missing. " +
"Please ensure that you have added the corresponding validation dependency " +
"(e.g., jooby-hbv).");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: jooby-hibernate-validator

@@ -0,0 +1,6 @@
package io.jooby.validation;

public interface MvcValidator<E extends Throwable> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably make E RuntimeException


public interface MvcValidator<E extends Throwable> {

void validate(Object bean) throws E;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well not sure if we need a generic for exception, RuntimeExceptoion or Exception will be OK

@kliushnichenko
Copy link
Contributor Author

minor improvements, javadoc, asciidoc has been added. Ready to final review/merge.
avaje-validator-module I'll send in a separate PR

@kliushnichenko kliushnichenko marked this pull request as ready for review September 5, 2024 12:47
Copy link
Member

@jknack jknack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kliushnichenko love what you did! Let me know if we can merge.

@kliushnichenko
Copy link
Contributor Author

Yes, we can. Just a minor thing, master and my branch are under 3.2.10-SNAPSHOT, but I see 3.3.0 has already been released, is it expected, or we need to update both to 3.3.1-SNAPSHOT?

@jknack
Copy link
Member

jknack commented Sep 5, 2024

oh yea, let me push the version bump

@jknack
Copy link
Member

jknack commented Sep 5, 2024

@kliushnichenko done

@kliushnichenko
Copy link
Contributor Author

@jknack updated, feel free to merge

@jknack jknack merged commit 22a0f5a into jooby-project:3.x Sep 5, 2024
1 check passed
@jknack jknack added this to the 3.3.1 milestone Sep 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants