Overview
We have found inconsistent behavior when using a Map in a SpEL expression.
Example: mapWithArrays[1] != null && mapWithArrays[1][1] != null
It works the first 100 times it is executed. Then compilation is launched, which throws an exception.
Workaround: use mapWithArrays[new Integer(1)] != null && mapWithArrays[new Integer(1)][1] != null or mapWithArrays.get(1) != null && mapWithArrays.get(1)[1] != null.
Reproducer
Stacktrace
org.springframework.expression.spel.SpelEvaluationException: EL1074E: An exception occurred while compiling an expression
at org.springframework.expression.spel.standard.SpelExpression.compileExpression(SpelExpression.java:552)
at org.springframework.expression.spel.standard.SpelExpression.checkCompile(SpelExpression.java:492)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:310)
at com.baeldung.thymeleaf.CompilerTests.test(CompilerTests.java:25)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.IllegalStateException: Failed to instantiate CompiledExpression for expression: ((mapWithArrays.[1] != null) and (mapWithArrays.[1].[1] != null))
at org.springframework.expression.spel.standard.SpelCompiler.compile(SpelCompiler.java:114)
at org.springframework.expression.spel.standard.SpelExpression.compileExpression(SpelExpression.java:528)
... 30 more
Caused by: java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
spel/Ex2.getValue(Ljava/lang/Object;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object; @12: invokeinterface
Reason:
Type integer (current frame, stack[2]) is not assignable to 'java/lang/Object'
Current Frame:
bci: @12
flags: { }
locals: { 'spel/Ex2', 'java/lang/Object', 'org/springframework/expression/EvaluationContext' }
stack: { 'org/springframework/expression/EvaluationContext', 'java/util/Map', integer }
Bytecode:
0000000: 2c2b c000 0eb4 0012 c000 1404 b900 1802
0000010: 0001 b800 1e9a 0007 04a7 0004 039a 0008
0000020: 121f a700 252c 2bc0 000e b400 12c0 0014
0000030: 04b9 0018 0200 c000 2104 3201 b800 1e9a
0000040: 0007 04a7 0004 03b8 0027 b0
Stackmap Table:
same_frame(@28)
same_locals_1_stack_item_frame(@29,Integer)
same_frame(@37)
same_frame(@70)
same_locals_1_stack_item_frame(@71,Integer)
at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3373)
at java.base/java.lang.Class.getConstructor0(Class.java:3578)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
at org.springframework.util.ReflectionUtils.accessibleConstructor(ReflectionUtils.java:185)
at org.springframework.expression.spel.standard.SpelCompiler.compile(SpelCompiler.java:110)
... 31 more
Comment From: sbrannen
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Comment From: sbrannen
Hi @rmonje,
Congratulations on submitting your first issue for the Spring Framework! 👍
I have confirmed that your example fails to compile against main, and we'll look into it.
Cheers,
Sam
Comment From: sbrannen
This has been fixed in 6.1.x and ported to main, 6.0.x, and 5.3.x.
Feel free to try out the fix in the snapshot builds for 5.3.37, 6.0.22, 6.1.9, and 6.2.0.