diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java index 4ef4a0ed4ec..58af4a874d2 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java @@ -712,10 +712,10 @@ public class Indexer extends SpelNodeImpl { } TypeDescriptor elementType = this.collectionEntryDescriptor.getElementTypeDescriptor(); try { - Constructor ctor = ReflectionUtils.accessibleConstructor(elementType.getType()); + Constructor ctor = getConstructor(elementType.getType()); int newElements = this.index - this.collection.size(); while (newElements >= 0) { - this.collection.add(ctor.newInstance()); + this.collection.add(ctor == null ? null : ctor.newInstance()); newElements--; } } @@ -725,6 +725,15 @@ public class Indexer extends SpelNodeImpl { } } + Constructor getConstructor(Class type) { + try { + return ReflectionUtils.accessibleConstructor(type); + } + catch (Throwable ex) { + return null; + } + } + @Override public boolean isWritable() { return true; diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java index 0af23293e7b..9d496cb7118 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java @@ -20,6 +20,7 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -199,6 +200,27 @@ public class IndexingTests { } } + public List decimals; + + @Test + public void autoGrowWithoutDefaultConstructor() { + this.decimals = new ArrayList<>(); + SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + parser.parseExpression("decimals[0]").setValue(this, "123.4"); + assertThat(decimals.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); + } + + @Test + public void indexIntoPropertyContainingNullList() { + this.decimals = new ArrayList<>(); + this.decimals.add(null); + this.decimals.add(BigDecimal.ONE); + SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + parser.parseExpression("decimals[0]").setValue(this, "9876.5"); + assertThat(decimals.get(0)).isEqualTo(BigDecimal.valueOf(9876.5)); + assertThat(decimals.get(1)).isEqualTo(BigDecimal.ONE); + } + @Test public void indexIntoPropertyContainingList() { List property = new ArrayList<>(); diff --git a/src/docs/asciidoc/core/core-expressions.adoc b/src/docs/asciidoc/core/core-expressions.adoc index 729ae85a91a..c88f9a95cfb 100644 --- a/src/docs/asciidoc/core/core-expressions.adoc +++ b/src/docs/asciidoc/core/core-expressions.adoc @@ -339,8 +339,12 @@ index into an array or collection and the element at the specified index is `nul you can automatically create the element. This is useful when using expressions made up of a chain of property references. If you index into an array or list and specifying an index that is beyond the end of the current size of the array or -list, you can automatically grow the array or list to accommodate that index. The following -example demonstrates how to automatically grow the list: +list, you can automatically grow the array or list to accommodate that index. In order to add +an element at the specified index, SpEL will try to create the element using a default +constructor before setting the specified value. If the element type does not have a default +constructor, `null` will be added. Note if there is no built-in or custom converter, that knows +how to set the value, `null` will remain in the array or list at the specified index. +The following example demonstrates how to automatically grow the list: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java