I want to add a BigDecimal
to a list using Spring Expression Language.
public class SpelTest {
public List<BigDecimal> values;
StandardEvaluationContext context;
SpelExpressionParser parser;
@Before
public void setup() {
values = new ArrayList<>();
context = new StandardEvaluationContext(this);
parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
}
@Test
public void shouldChangeValue() {
values.add(BigDecimal.ONE);
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // passes
}
@Test
public void shouldAddValue() {
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // fails
}
}
Changing the first entry passes but adding an entry fails with
Caused by: java.lang.NoSuchMethodException: java.math.BigDecimal.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3349)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
at org.springframework.util.ReflectionUtils.accessibleConstructor(ReflectionUtils.java:185)
at org.springframework.expression.spel.ast.Indexer$CollectionIndexingValueRef.growCollectionIfNecessary(Indexer.java:715)
... 55 more
Not sure why SpEL isn't able to properly initialize a BigDecimal
when the list is empty. Surprisingly I found nothing about this problem.
Thanks for helping!
You could avoid this problem by setting the whole list instead of single (not initialized) elements. Instead of
parser.parseExpression("values[0]").setValue(context, "123.4");
use:
parser.parseExpression("values").setValue(context, "123.4");
This also works for multiple elements, quite neat:
parser.parseExpression("values").setValue(context, "123.4, 456.7");