openrewrite / rewrite-gradle-plugin

OpenRewrite's Gradle plugin.
Apache License 2.0
65 stars 41 forks source link

READ_DATE_TIMESTAMPS_AS_NANOSECONDS when rewrite Spring Boot 2.7 to 3.x #348

Open nicolasb29 opened 3 days ago

nicolasb29 commented 3 days ago

Hi,

I'm using OpenRewrite to migrate Spring Boot 2.7 to Spring Boot 3.x, like a lot of people I think, but since the version 6.28.0 I have this error :

java.lang.RuntimeException: Error while visiting build.gradle: java.lang.NoSuchFieldError: Class com.fasterxml.jackson.annotation.JsonFormat$Feature does not have member field 'com.fasterxml.jackson.annotation.JsonFormat$Feature READ_DATE_TIMESTAMPS_AS_NANOSECONDS'

I made a project on GitHub to show the problem:

I made a Gradle dependencies and it seems that com.fasterxml.jackson is downgraded from 2.17.2 to 2.13.5 (version in dependency of Spring Boot 2.7.18, cause of the problem ?). The annotation READ_DATE_TIMESTAMPS_AS_NANOSECONDS was included in version 2.15.

Best regards.

timtebeek commented 3 days ago

Thanks for the detailed analysis already @nicolasb29 ; Can't say I've heard of these issues before. Quickly glancing at recipes we seem to have this one: https://github.com/openrewrite/rewrite-migrate-java/blob/cd36280b91d497086e220e965f2af3106e786ebf/src/main/resources/META-INF/rewrite/jakarta-ee-9.yml#L805-L810 But I'm not yet sure if that factors in, as it sounds like you're referring to an issue running OpenRewrite, not an issue after running OpenRewrite, correct?

nicolasb29 commented 3 days ago

Yes it's a problem while the task rewriteRun is running.

shanman190 commented 3 days ago

So my guess is the Spring Dependency Management plugin is the cause of the issues. It utilizes a Gradle resolutionStrategy which forces the versions across all Gradle configurations to the one that would come from the Spring Boot Gradle plugin (ie. org.springframework.boot:spring-boot-dependencies).

Ultimately this would have forced OpenRewrite's Jackson version to likely be different (in this case down).

nicolasb29 commented 3 days ago

One solution is to force the dependencies like in this PR. This solution will solve the problem with jackson annotations, but maybe others problems can append with others dependencies.


./gradlew rewriteRun --init-script init.gradle -Drewrite.activeRecipe=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0

> Task :rewriteRun
Validating active recipes
Scanning sources in project :
Using active styles []
There were problems parsing some source files, run with --info to see full stack traces
There were problems parsing .github/workflows/gradle.yml
There were problems parsing rewrite.yml
All sources parsed, running active recipes: org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
Changes have been made to build.gradle by:
    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7
        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6
            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5
                org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.0.x}
        org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=3.0.x}
            org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.1.x}
Changes have been made to init.gradle by:
    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7
        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6
            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5
                org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4
                    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3
                        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2
                            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1
                                org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0
                                    org.openrewrite.gradle.spring.AddSpringDependencyManagementPlugin
                    org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration
                        org.openrewrite.java.testing.junit5.JUnit4to5Migration
                            org.openrewrite.java.testing.junit5.GradleUseJunitJupiter
                org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.0.x}
        org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.1.x}
Please review and commit the results.
Estimate time saved: 10m

BUILD SUCCESSFUL in 13s
4 actionable tasks: 1 executed, 3 up-to-date
shanman190 commented 3 days ago

Yeah, I'm not 100% sure given any dependency that appears in a BOM imported into the Spring Dependency Management plugin would be potentially impacted. So this feels a little like a stop-gap.

Honestly, I've wondered if the Spring Dependency Management plugin should be a little more reserved in its behavior, but right now it would be a continually moving target.

nicolasb29 commented 3 days ago

In this example, there is also a problem with snake yaml

with errors like this There were problems parsing

nicolasb29 commented 2 days ago

Hi,

I think that you have to keep the detached configuration to resolve dependencies in isolated mode.

I have updated the PR.

I have added this code in the afterEvaluate block of my init.gradle to print dependencies:

 tasks.all { task ->
            if (task.name == "rewriteDryRun") {
                doFirst {
                    println "Dependencies for rewriteDryRun:"
                    project.configurations.named("rewrite").get().resolvedConfiguration.resolvedArtifacts.each { artifact ->
                        println "- ${artifact.moduleVersion.id}"
                    }
                }
            }
        }
./gradlew rewriteDryRun --init-script init.gradle -Drewrite.activeRecipe=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0       

> Task :rewriteDryRun
Dependencies for rewriteDryRun:
- org.openrewrite.recipe:rewrite-spring:5.24.1
- org.openrewrite:rewrite-polyglot:1.16.1
- org.openrewrite.recipe:rewrite-apache:1.9.1
- org.openrewrite.recipe:rewrite-hibernate:1.13.1
- org.openrewrite.recipe:rewrite-micrometer:0.11.1
- org.openrewrite.recipe:rewrite-migrate-java:2.30.1
- org.openrewrite.recipe:rewrite-openapi:0.10.1
- org.openrewrite.recipe:rewrite-reactive-streams:0.6.1
- org.openrewrite.recipe:rewrite-testing-frameworks:2.23.1
- org.openrewrite.recipe:rewrite-logging-frameworks:2.17.0
- org.openrewrite.recipe:rewrite-jenkins:0.18.1
- org.openrewrite.recipe:rewrite-java-dependencies:1.24.1
- org.openrewrite:rewrite-gradle:8.41.1
- org.openrewrite:rewrite-hcl:8.41.1
- org.openrewrite:rewrite-json:8.41.1
- org.openrewrite.recipe:rewrite-static-analysis:1.21.1
- org.openrewrite:rewrite-groovy:8.41.1
- org.openrewrite:rewrite-kotlin:1.23.1
- org.openrewrite:rewrite-java-21:8.41.1
- org.openrewrite:rewrite-java-17:8.41.1
- org.openrewrite:rewrite-java-11:8.41.1
- org.openrewrite:rewrite-java-8:8.41.1
- org.openrewrite.meta:rewrite-analysis:2.13.1
- org.openrewrite:rewrite-maven:8.41.1
- org.openrewrite:rewrite-csharp:0.16.1
- org.openrewrite:rewrite-java:8.41.1
- org.openrewrite:rewrite-properties:8.41.1
- org.openrewrite:rewrite-protobuf:8.41.1
- org.openrewrite:rewrite-xml:8.41.1
- org.openrewrite.recipe:rewrite-github-actions:2.10.1
- org.openrewrite:rewrite-yaml:8.41.1
- org.openrewrite:rewrite-core:8.41.1
- org.openrewrite.gradle.tooling:model:2.8.0
- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2
- com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.13.5
- com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.5
- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.5
- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.13.5
- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5
- com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.13.5
- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.13.5
- com.fasterxml.jackson.core:jackson-databind:2.13.5
- com.fasterxml.jackson.core:jackson-core:2.13.5
- org.testcontainers:testcontainers:1.20.4
- com.github.docker-java:docker-java-api:3.4.0
- com.fasterxml.jackson.core:jackson-annotations:2.13.5
- com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2
- org.openrewrite.tools:jgit:1.2.0
- org.openrewrite.tools:java-object-diff:1.0.1
- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.21
- org.jetbrains.kotlin:kotlin-reflect:1.6.21
- org.jetbrains.kotlin:kotlin-stdlib:1.6.21
- org.openrewrite:rewrite-java-lombok:8.41.1
- org.rnorth.duct-tape:duct-tape:1.0.8
- org.jetbrains:annotations:26.0.1
- org.openrewrite:rewrite-templating:1.19.1
- org.jspecify:jspecify:1.0.0
- io.quarkus.gizmo:gizmo:1.0.11.Final
- net.java.dev.jna:jna-platform:5.15.0
- org.apache.commons:commons-compress:1.27.1
- io.micrometer:micrometer-core:1.9.17
- io.github.classgraph:classgraph:4.8.179
- org.yaml:snakeyaml:1.30
- org.codehaus.groovy:groovy:3.0.19
- org.antlr:antlr4-runtime:4.11.1
- org.apache.commons:commons-text:1.12.0
- org.apache.commons:commons-lang3:3.12.0
- org.xerial.snappy:snappy-java:1.1.10.7
- org.ow2.asm:asm-util:9.7.1
- org.ow2.asm:asm-analysis:9.7.1
- org.ow2.asm:asm-tree:9.7.1
- org.ow2.asm:asm:9.7.1
- com.github.ben-manes.caffeine:caffeine:2.9.3
- dev.failsafe:failsafe:3.3.2
- org.apache.maven.shared:maven-shared-utils:3.4.2
- commons-io:commons-io:2.18.0
- org.apache.poi:poi:3.16
- org.codehaus.plexus:plexus-utils:3.5.1
- io.dropwizard.metrics:metrics-core:4.2.22
- io.projectreactor:reactor-core:3.4.34
- tech.picnic.error-prone-support:error-prone-contrib:0.19.1
- com.googlecode.javaewah:JavaEWAH:1.1.13
- org.jboss:jandex:2.4.2.Final
- com.github.docker-java:docker-java-transport-zerodep:3.4.0
- net.java.dev.jna:jna:5.15.0
- commons-codec:commons-codec:1.15
- org.hdrhistogram:HdrHistogram:2.1.12
- org.latencyutils:LatencyUtils:2.0.3
- org.jetbrains.kotlin:kotlin-script-runtime:1.6.21
- org.jetbrains.kotlin:kotlin-daemon-embeddable:1.6.21
- org.jetbrains.intellij.deps:trove4j:1.0.20200330
- org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21
- org.projectlombok:lombok:1.18.30
- tech.picnic.error-prone-support:refaster-support:0.19.1
- com.google.guava:guava:33.3.1-jre
- org.checkerframework:checker-qual:3.43.0
- com.google.errorprone:error_prone_annotations:2.28.0
- com.fasterxml.woodstox:woodstox-core:6.4.0
- org.codehaus.woodstox:stax2-api:4.2.1
- jakarta.xml.bind:jakarta.xml.bind-api:2.3.3
- jakarta.activation:jakarta.activation-api:1.2.2
- ch.qos.logback:logback-classic:1.2.12
- org.functionaljava:functionaljava:5.0
- org.kohsuke:wordnet-random-name:1.6
- org.apache.logging.log4j:log4j-core:2.17.2
- org.slf4j:slf4j-api:1.7.36
- org.apache.commons:commons-collections4:4.1
- org.reactivestreams:reactive-streams:1.0.4
- junit:junit:4.13.2
- tech.picnic.error-prone-support:error-prone-utils:0.19.1
- ch.qos.logback:logback-core:1.2.12
- org.apache.logging.log4j:log4j-api:2.17.2
- org.hamcrest:hamcrest-core:2.2
- com.github.docker-java:docker-java-transport:3.4.0
- org.hamcrest:hamcrest:2.2
- com.google.guava:failureaccess:1.0.2
- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
- com.google.code.findbugs:jsr305:3.0.2
- com.google.j2objc:j2objc-annotations:3.0.0
Validating active recipes
Scanning sources in project :
Using active styles []
All sources parsed, running active recipes: org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
These recipes would make changes to src/main/resources/application.yml:
    org.openrewrite.java.spring.boot3.SpringBootProperties_3_0
        org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=management.metrics.export.appoptics.api-token, newPropertyKey=management.appoptics.metrics.export.api-token}
These recipes would make changes to build.gradle:
    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7
        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6
            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5
                org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.0.x}
        org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=3.0.x}
            org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.1.x}
These recipes would make changes to init.gradle:
    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7
        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6
            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5
                org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4
                    org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3
                        org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2
                            org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1
                                org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0
                                    org.openrewrite.gradle.spring.AddSpringDependencyManagementPlugin
                    org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration
                        org.openrewrite.java.testing.junit5.JUnit4to5Migration
                            org.openrewrite.java.testing.junit5.GradleUseJunitJupiter
                org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.0.x}
        org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.1.x}
Report available:
    /Users/nicolasbonamy/Downloads/testopenrewrite/build/reports/rewrite/rewrite.patch
Estimate time saved: 15m
Run 'gradle rewriteRun' to apply the recipes.

BUILD SUCCESSFUL in 9s
4 actionable tasks: 1 executed, 3 up-to-date