OpenRewrite自定义Java Recipe报错:LST含缺失/无效类型信息
问题
我正在用OpenRewrite开发迁移Recipe,将Play Framework控制器转换为Spring Boot REST控制器。还没在visitor中编写任何LST修改代码,就遇到了java.lang.IllegalStateException错误,提示LST包含缺失或无效类型信息,指向方法调用ok("Hello, World!")。
错误栈
java.lang.IllegalStateException: LST contains missing or invalid type information MethodInvocation->Return->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit /*~~(MethodInvocation type is missing or malformed)~~>*/ok("Hello, World!") at org.openrewrite.java.Assertions.assertValidTypes(Assertions.java:87) at org.openrewrite.java.Assertions.validateTypes(Assertions.java:57) at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:305) at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:133) at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:128) at com.yourorg.NewPlayToSpringControllersRecipeTest.migratePlayControllerAndMethodToSpringRestController(NewPlayToSpringControllersRecipeTest.java:23) at java.base/java.lang.reflect.Method.invoke(Method.java:569) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
测试方法代码
package com.yourorg; import org.junit.jupiter.api.Test; import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.java.Assertions; import org.openrewrite.java.JavaParser; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; public class NewPlayToSpringControllersRecipeTest implements RewriteTest { @Override public void defaults(RecipeSpec spec) { spec.recipe(new NewPlayToSpringControllersRecipe()) .parser(JavaParser.fromJavaVersion().classpathFromResources(new InMemoryExecutionContext(), "jackson-databind", "jackson-core", "jackson-annotations", "spring-web-6.1.+", "play_2.11-2.7.+")); } @Test void migratePlayControllerAndMethodToSpringRestController() { rewriteRun( Assertions.java( """ package com.example; import play.mvc.Controller; import play.mvc.Result; public class MyController extends Controller { public Result sayHello() { return ok("Hello, World!"); } } """ ) ); } }
Recipe的getVisitor方法代码
package com.yourorg; import org.openrewrite.ExecutionContext; import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; import org.openrewrite.java.*; import org.openrewrite.java.tree.J; public class NewPlayToSpringControllersRecipe extends Recipe { @Override public String getDisplayName() { return "Migrate play framework controllers to spring boot REST controllers"; } @Override public String getDescription() { return "Transforms Play Framework controllers to Spring Boot REST controllers by removing the Play-specific superclass " + "and adding the @RestController annotation."; } @Override public TreeVisitor<?, ExecutionContext> getVisitor() { return new JavaIsoVisitor<ExecutionContext>() { @Override public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration cd, ExecutionContext executionContext) { System.out.println("visitClassDeclaration\n" + TreeVisitingPrinter.printTree(getCursor())); return super.visitClassDeclaration(cd, executionContext); } }; } }
解决方案
- 问题根源:OpenRewrite测试框架默认会验证LST的类型信息完整性。
ok("Hello, World!")是Play框架Controller类的静态方法,但测试时的classpath未正确加载Play依赖,导致解析器无法识别该方法的类型,触发类型验证失败。 - 修复步骤:
- 确保Play依赖正确引入:检查
classpathFromResources中指定的play_2.11-2.7.+是否能在项目资源classpath中找到对应JAR包。如果用Maven/Gradle管理依赖,建议直接通过构建工具引入Play的play-mvc依赖,而非从资源加载。 - 临时禁用类型验证:若仅需测试Recipe逻辑、暂时不关心类型检查,可在测试中关闭验证:
rewriteRun( spec -> spec.noValidate(), Assertions.java(/* 原测试代码 */) ); - 正确配置JavaParser的classpath:如果用Maven,推荐使用
JavaParser.fromJavaVersion().classpath("play-mvc"),让OpenRewrite自动从Maven仓库拉取依赖,确保依赖版本与测试代码中的Play版本(如2.7.x)一致。
- 确保Play依赖正确引入:检查
内容的提问来源于stack exchange,提问作者Azar
相关产品推荐
相关产品推荐

