openrewrite / rewrite-gradle-plugin

OpenRewrite's Gradle plugin.
Apache License 2.0
64 stars 40 forks source link

Rewrite-spring yaml deserialization issue #33

Closed gadams00 closed 3 years ago

gadams00 commented 3 years ago

Rewrite-spring recipes RemoveObsoleteRunners and RunnerToExtension are both unable to be deserialized from declarative recipe lists in rewrite-gradle-plugin. We've observed that both contain an @Option annotated property that is of type List<String>. The exception observed is

java.lang.IllegalArgumentException: Could not resolve type id 'org.openrewrite.java.testing.junit5.RemoveObsoleteRunners' as a subtype of `org.openrewrite.Recipe`: no such class found

though based on observing the classpath, Recipe and RemoveObsoleteRunners are both definitely present, so we think this exception may be a red herring for the real issue.

aegershman commented 3 years ago

Note taking in this issue comment. Will update comment in-place to prevent notification noise.



AH! I just tested this. No, it doesn't have to do with List<x> types, it seems to be with any declarative recipes with any kind of option configuration provided which configures a recipe from within the same package.

Just posting this for personal debugging tracking.

The problem doesn't appear strictly related to the type of the recipe parameters (e.g. not specifically because a recipe Option is type List<String> vs. just a String, etc.), but it does seem to be happen when:

So, this causes an issue:

---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.testing.junit5.JUnit4to5Migration
...
recipeList:
  - org.openrewrite.java.testing.junit5.RemoveObsoleteRunners:
      obsoleteRunners:
        - org.junit.runners.JUnit4
        - org.junit.runners.BlockJUnit4ClassRunner

This causes an issue (for the sake of assume this would be valid):

---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.testing.junit5.JUnit4to5Migration
...
recipeList:
  - org.openrewrite.java.testing.junit5.RemoveObsoleteRunners: {} # problematic because it's a yaml map

But this is fine:

---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.testing.junit5.JUnit4to5Migration
...
recipeList:
  - org.openrewrite.java.testing.junit5.AddDependency # acceptable because it is yaml list value entry and not a yaml map itself

And this is fine

---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.testing.junit5.JUnit4to5Migration
...
recipeList:
  - org.openrewrite.java.ReorderMethodArguments: # doesn't explode because it's not in the same distribution package as the recipe it's configuring 
      methodPattern: org.junit.Assume assume*(String, boolean)
      oldParameterNames:
        - message
        - b
      newParameterNames:
        - b
        - message

Now the question still remains, why exactly does the maven-plugin still cooperate? Well I believe it’s still related to a classpath issue and being able to deserialize the yaml, but nonetheless, wanted clarity on this for myself at least.