graphql-java / graphql-java-extended-validation

Validation library for graphql-java input
MIT License
128 stars 34 forks source link

17.0 does not work with Spring Boot 2.5.x #52

Closed marcust closed 2 years ago

marcust commented 3 years ago

So I am currently looking for an upgrade path to GraphQL Java 17 with extended validation in a Spring Boot Application. It seems there is none, as the update to GraphQL Java 17 in extended validation came with an upgrade to Hibernate Validation (https://github.com/graphql-java/graphql-java-extended-validation/commit/d779f85c728484887464393f45decf2423d3da13) to Hibernate Validator 7, which is not supported by Spring Boot (as it is not supported by Spring, see https://github.com/spring-projects/spring-boot/issues/26705).

I tried some different combinations of downgraded/upgraded dependencies, but I am stuck. Am I missing something or can I not use the 17.0 version in a Spring Context?

hantsy commented 3 years ago

Hibernate Validator 7 used the new Jakarta EE 9 API level, which is planed in Spring 6.

Hope there is a variant for Jakarta EE 8, Hibernate Validator 6.2.1 + GraphQL 17.

berngp commented 3 years ago

Was there any reason to use Hibernate Validator 7.+ ? Since Spring Boot is not planning to support Hibernate Validator 7 until its 3.x versions could we move back to the latest Hibernate Validator 6.+? Which is 6.2.0.Final at this time.

Ref. https://github.com/spring-projects/spring-boot/issues/26705#issuecomment-850829424

hantsy commented 3 years ago

As I know there are several Jakarta EE spec implementation projects which used Eclipse Transformer or Tomcat Jakarta EE migration to maintain the same source codes for Jakarta EE 8 and Jakarta EE 9(transformed by these tools).

@berngp I think the main difference between Hibernate Validator 6.x and 7.0 is they are referring to Jakarta EE 8 and 9 respectively.

hantsy commented 3 years ago

I created a simple EE 8 branch to downgrade it to Jakarta EE 8, I think it works well(the build is passed), I just downgraded the deps to Jakarta EE 8 API level and replace the jakarta. to javax. in the java source codes.

https://github.com/hantsy/graphql-java-extended-validation/tree/ee8

And I am trying to add another build profile to generate a copy for Jakarta EE 9(replace the javax. to jakarta. back in the source codes), but I am not a guru of Gradle, there are some issues in the copy/replace tasks in the generateSources phase, check the jakarta.build which can be triggered by a "jakarta" property in command line(-Pjakarta), please help me to overcome this barrier if you are a Gradle guru.

berngp commented 3 years ago

@hantsy I'm not sure having two artifacts is the best approach. Users will have to figure out which is the proper version they need to use according to the internals of the platform they choose. IMO if there is no strong need to move to Validator 7 then an approach to use Validator 6.x might be a simpler approach. So, I think the options are:

hantsy commented 3 years ago

If this project decided to upgrade to EE 9, it is better to maintain the source codes and add transformer task to generate a jar for EE 9, which is done by some Jakarta projects.

In the application frameworks world, only micronaunt 3 migrated to EE 9 APIs, most of current framework/tools are using EE 8 compatible APIs. But GraphQL Java related projects could be referred in these framework/tools projects, maintain two variants is reasonable, but this graphql-java-extended-validation project can be EE 8 only, and let the framework/tools projects do the EE9 transforming themselves.

hantsy commented 3 years ago

@marcust Add all deps to your project dependencies, it works, see: https://github.com/hantsy/spring-graphql-sample/blob/master/dgs-codegen/build.gradle#L26-L30

WtfJoke commented 3 years ago

Since Spring Boot is not planning to support Hibernate Validator 7 until its 3.x versions could we move back to the latest Hibernate Validator 6.+? Which is 6.2.0.Final at this time.

Ref. spring-projects/spring-boot#26705 (comment)

I also would favor to continue with hibernate validator 6.2.0.Final.

In our spring boot app (2.5.x) we stick to graphql-java-extended-validation:16.0.0 (which brings hibernate validator 6.1.6 which is not compatible with 6.2.0.Final) and override the version manually, see https://github.com/graphql-java/graphql-java-extended-validation/issues/50#issuecomment-896580849

marcust commented 3 years ago

@marcust Add all deps to your project dependencies, it works, see: https://github.com/hantsy/spring-graphql-sample/blob/master/dgs-codegen/build.gradle#L26-L30

@hantsy this will only work until something in Spring tries to use Validation, because Spring will not be able to find the new SPI in the 7.x Validation and thus have a unsatisfied runtime dependency, see the issue linked in my original comment. If you throw in e.g. the spring boot validation starter that should trigger it.

hantsy commented 3 years ago

@marcust Try to use ResolutionStrategy to use different versions in the same build scripts.(But I have not tried this before)

See this discussion on stackoverflow: https://stackoverflow.com/questions/29374885/multiple-version-of-dependencies-in-gradle/29382370

marcust commented 3 years ago

@hantsy this will not work, because you can only have one version of an artifact on your classpath, and we are talking runtime dependencies here.

So if I start up your example with debug=true I see the following auto configuration snippet for Validation:

   ValidationAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.validation.executable.ExecutableValidator' (OnClassCondition)

assuming that I want to use any other Spring component that depends on Validation I have to make it find the correct conditional class by add the old validation api (that is what all of spring boot depends on)

   implementation 'javax.validation:validation-api:2.0.1.Final'

to the build.gradle file. This then gives me the following auto configuration report:

   ValidationAutoConfiguration:
      Did not match:
         - @ConditionalOnResource did not find resource 'classpath:META-INF/services/javax.validation.spi.ValidationProvider' (OnResourceCondition)
      Matched:
         - @ConditionalOnClass found required class 'javax.validation.executable.ExecutableValidator' (OnClassCondition)

So now I need the SPI, but I can not add the old validator version because we already have the new validator version:

    implementation 'org.hibernate.validator:hibernate-validator:7.0.1.Final'

in the build.gradle file.

Looking at the Validator jar file it only has the jakarta.validation.spi.ValidationProvider in the 7.0.1.Final jar file, whereas older Validator comes with the javax.validation.spi.ValidationProvider which is required by Spring Boot autoconfiguration.

So your example only works because you are not using the regular Spring Boot validation but only the Extended GraphQL Validation, which loads the validator not via Spring Boot but manually.

If you would add some bean validation (e.g. on your Entities) you would not be able to get that to work because of the dependency conflict.

Long story short, the only solution will be to have a version of this library that actually reverts back to validator 6.x

As I see @bbakerman did the update, is there any way we can get that done? Happy to help.

Or is there a compatibility layer between Jakarta Bean Validation 3.0 and JSR 380 that makes the 7.x Hibernate Validator work with Spring Boot? I guess that would be the only other option, but I guess there are too many changes (from a quick look at the changelog) to make that feasible.

hantsy commented 3 years ago

@marcust I understood it. Even the two different version validation API can be existed in one application, but the Hibernate Validator 6.2.x and 7.x API will be conflict. Hope someone can provide help for my PR https://github.com/graphql-java/graphql-java-extended-validation/pull/53 to build for two Jakarta EE versions.

berngp commented 3 years ago

@bbakerman would there be any appetite to support a version of this library to move back to Validator 6.+ & EE 8.

bbakerman commented 2 years ago

Was there any reason to use Hibernate Validator 7.+ ?

The reason it was updated was that we got reports of a Security Vulnerability in org.hibernate.validator:hibernate-validator:6.2.0.Final both inside Atlassian (where I work) and outside it from others.

So as part of the 17.x upgrade of graphql-java - this was updated as well. This is safety versus backwards compatibility challenge

Since Spring Boot is not planning to support Hibernate Validator 7 until its 3.x versions could we move back to the latest Hibernate Validator 6.+? Which is 6.2.0.Final at this time.

This library is not intended to be a Spring only thing. I appreciate that you want to use the version that Spring Boot is providing but this is safety versus backwards compatibility challenge. I decided to go for safety.

@bbakerman would there be any appetite to support a version of this library to move back to Validator 6.+ & EE 8.

If some one was to provide the PR (which would mostly be backing out aspects of commit https://github.com/graphql-java/graphql-java-extended-validation/commit/d779f85c728484887464393f45decf2423d3da13 then we would consider it.

We would merge that into a special branch.

I am guessing people want the latest graphql-java BUT with the older validation lib in place.

What we wont do it maintain it with new fixes or feature and so on. We dont have the capacity to manage multi branches with multiple versions.

bbakerman commented 2 years ago

Looking into this I created a PR that downgrades the version. The challenge is the ongoing maintenance of this branch.

Future fixes and enhancements probably wont go on this branch because multi branch development is very expensive in time for a volunteer open source project

bbakerman commented 2 years ago
<dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-java-extended-validation</artifactId>
  <version>17.0-hibernate-validator-6.2.0.Final</version>
</dependency>

This has now been released to maven. Please let me know if this has problems running on the Spring Boot version in any way

berngp commented 2 years ago

Thank @bbakerman for the detailed reply. You even went through the effort of creating a hibernate-validator-6.2.0.Final branch and publishing its artifact, going far beyond any effort I imagined. I agree, not that matters much, that having another branch and maintaining two release trains is taxing for any development team. It was not my intention, at any point in time, to create additional burden to you, or your team. You, and your team, already provide valuable free OSS software that we all can leverage at our own will.

I'll proceed to use the graphql-java-extended-validation:17.0-hibernate-validator-6.2.0.Final in the DGS Framework and update the thread. That said, I want to be clear that I don't expect you, or your team, maintain any updates on it, doing so will be unfair. If it helps, I am willing to merge changes form the main/master branch to the v17.x-validator-6.2.0.Final in the future.

PS. According to publicly available information, to this date, org.hibernate:hibernate-validator:6.2.0.Final doesn't have known vulnerabilities. There were some in [6.1.0,6.1.3.Final) but they were addressed in later releases. I checked SNYK, cve.mitre.org, and NIST.