In my recipe I select the method parameters which have both the NotNull
and RequestParam
annotations and I want to apply the OpenRewrite recipe AddOrUpdateAnnotationAttribute on these method parameters to set the required attribute to true of the RequestParam
annotation.
I'm struggling how to apply a recipe on a specific piece of code, not on the complete Java class. Does somebody has an example?
An example of the source code before applying my recipe:
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.constraints.NotNull;
class ControllerClass {
public String sayHello (
@NotNull @RequestParam(value = "name") String name,
@RequestParam(value = "lang") String lang
) {
return "Hello";
}
}
The expected source code after applying my recipe:
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.constraints.NotNull;
class ControllerClass {
public String sayHello (
@NotNull @RequestParam(required = true, value = "name") String name,
@RequestParam(value = "lang") String lang
) {
return "Hello";
}
}
Only the first parameter name
needs to be adopted as the second parameter has no NotNull
annotation.
My (simplified) recipe:
public class MandatoryRequestParameter extends Recipe {
@Override
public @NotNull String getDisplayName() {
return "Make RequestParam mandatory";
}
@Override
protected @NotNull JavaIsoVisitor<ExecutionContext> getVisitor() {
return new MandatoryRequestParameterVisitor();
}
public class MandatoryRequestParameterVisitor extends JavaIsoVisitor<ExecutionContext> {
@Override
public @NotNull J.MethodDeclaration visitMethodDeclaration(@NotNull J.MethodDeclaration methodDeclaration, @NotNull ExecutionContext executionContext) {
J.MethodDeclaration methodDecl = super.visitMethodDeclaration(methodDeclaration, executionContext);
return methodDeclaration.withParameters(ListUtils.map(methodDecl.getParameters(), (i, p) -> makeRequestParamMandatory(p, executionContext)));
}
private Statement makeRequestParamMandatory(Statement statement, ExecutionContext executionContext) {
if (!(statement instanceof J.VariableDeclarations methodParameterDeclaration) || methodParameterDeclaration.getLeadingAnnotations().size() < 2) {
return statement;
}
AddOrUpdateAnnotationAttribute addOrUpdateAnnotationAttribute = new AddOrUpdateAnnotationAttribute(
"org.springframework.web.bind.annotation.RequestParam", "required", "true", false
);
return (Statement) methodParameterDeclaration.acceptJava(addOrUpdateAnnotationAttribute.getVisitor(), executionContext);
}
}
}
When I execute my recipe, I got following error so my implementation is not the correct way of applying a recipe.
org.openrewrite.UncaughtVisitorException: java.lang.IllegalStateException: Expected to find a matching parent for Cursor{Annotation-\>root}
at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:253)
at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:145)
at org.openrewrite.java.JavaTemplate.withTemplate(JavaTemplate.java:520)
at org.openrewrite.java.JavaTemplate.withTemplate(JavaTemplate.java:42)
at org.openrewrite.java.tree.J.withTemplate(J.java:87)
at org.openrewrite.java.AddOrUpdateAnnotationAttribute$1.visitAnnotation(AddOrUpdateAnnotationAttribute.java:144)
at org.openrewrite.java.AddOrUpdateAnnotationAttribute$1.visitAnnotation(AddOrUpdateAnnotationAttribute.java:78)
at org.openrewrite.java.tree.J$Annotation.acceptJava(J.java:220)
at org.openrewrite.java.tree.J.accept(J.java:60)
at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:206)
at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:285)
at org.openrewrite.java.JavaVisitor.lambda$visitVariableDeclarations$23(JavaVisitor.java:873)
at org.openrewrite.internal.ListUtils.lambda$map$0(ListUtils.java:141)
at org.openrewrite.internal.ListUtils.map(ListUtils.java:123)
at org.openrewrite.internal.ListUtils.map(ListUtils.java:141)
at org.openrewrite.java.JavaVisitor.visitVariableDeclarations(JavaVisitor.java:873)
at org.openrewrite.java.JavaIsoVisitor.visitVariableDeclarations(JavaIsoVisitor.java:240)
at org.openrewrite.java.JavaIsoVisitor.visitVariableDeclarations(JavaIsoVisitor.java:31)
at org.openrewrite.java.tree.J$VariableDeclarations.acceptJava(J.java:5149)
at org.springframework.sbm.jee.jaxrs.recipes.MandatoryRequestParameter$MandatoryRequestParameterVisitor.makeRequestParamMandatory(MandatoryRequestParameter.java:45)
at org.springframework.sbm.jee.jaxrs.recipes.MandatoryRequestParameter$MandatoryRequestParameterVisitor.lambda$visitMethodDeclaration$0(MandatoryRequestParameter.java:33)