Fixing JavaTemplate Throwing ArrayIndexOutOfBounds
Are you getting a java.lang.ArrayIndexOutOfBoundsException
from your JavaTemplate
in your OpenRewrite recipe?
If you are using substitution indicators (#{}
) in your template string, you could have a mismatch between the number of indicators provided and the number of varargs parameters given to the apply
method.
Example
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
method = super.visitMethodDeclaration(method, executionContext);
...
return JavaTemplate.builder("this.#{} = #{}")
.build()
.apply(
getCursor(),
method.getBody().getCoordinates().lastStatement(),
"helloWorld" // variable to insert into template
);
}
The above recipe is adding a new field assignment to a constructor declaration. helloWorld
should be substituted into the template. Instead we see this exception being thrown:
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
at org.openrewrite.java.internal.template.Substitutions.lambda$substitute$0(Substitutions.java:80)
at org.openrewrite.internal.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:98)
at org.openrewrite.internal.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:72)
at org.openrewrite.java.internal.template.Substitutions.substitute(Substitutions.java:52)
at org.openrewrite.java.JavaTemplate.apply(JavaTemplate.java:58)
The JavaTemplate
is able substitute the first marker with the first parameter. When trying to do the same for the second marker it finds a second element is not provided. The template does not know the recipe intends both markers to be replaced with the same value. The recipe needs to be explicit like so:
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) {
method = super.visitMethodDeclaration(method, executionContext);
...
return JavaTemplate.builder("this.#{} = #{}")
.build()
.apply(
getCursor(),
method.getBody().getCoordinates().lastStatement(),
"helloWorld",
"helloWorld" // Needs to be specified twice!
);
}
References
Support our work
Subscribe to my newsletter
Read articles from BitFlipper directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by