diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java index b551bcd9bb9..b37548a5a27 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java @@ -42,7 +42,7 @@ public class Elvis extends SpelNodeImpl { @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { TypedValue value = children[0].getValueInternal(state); - if (value.getValue()!=null) { + if (value.getValue()!=null && !((value.getValue() instanceof String) && ((String)value.getValue()).length()==0)) { return value; } else { return children[1].getValueInternal(state); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java index 8a0784409c5..8e4b4b40a43 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java @@ -135,14 +135,26 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { if (moreTokens()) { Token t = peekToken(); if (t.kind==TokenKind.ASSIGN) { // a=b + if (expr==null) { + expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1)); + } nextToken(); SpelNodeImpl assignedValue = eatLogicalOrExpression(); return new Assign(toPos(t),expr,assignedValue); } else if (t.kind==TokenKind.ELVIS) { // a?:b (a if it isn't null, otherwise b) + if (expr==null) { + expr = new NullLiteral(toPos(t.startpos-1,t.endpos-2)); + } nextToken(); // elvis has left the building SpelNodeImpl valueIfNull = eatExpression(); + if (valueIfNull==null) { + valueIfNull = new NullLiteral(toPos(t.startpos+1,t.endpos+1)); + } return new Elvis(toPos(t),expr,valueIfNull); } else if (t.kind==TokenKind.QMARK) { // a?b:c + if (expr==null) { + expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1)); + } nextToken(); SpelNodeImpl ifTrueExprValue = eatExpression(); eatToken(TokenKind.COLON); diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java index 36f5cc34856..d71c5e114ab 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java @@ -627,4 +627,50 @@ public class SpringEL300Tests extends ExpressionTestCase { // end bean resolver tests + @Test + public void elvis_SPR7209_1() { + StandardEvaluationContext eContext = new StandardEvaluationContext(new XX()); + Expression expr = null; + + // Different parts of elvis expression are null + expr = new SpelExpressionParser().parseRaw("(?:'default')"); + Assert.assertEquals("default", expr.getValue()); + expr = new SpelExpressionParser().parseRaw("?:'default'"); + Assert.assertEquals("default", expr.getValue()); + expr = new SpelExpressionParser().parseRaw("?:"); + Assert.assertEquals(null, expr.getValue()); + + // Different parts of ternary expression are null + try { + expr = new SpelExpressionParser().parseRaw("(?'abc':'default')"); + expr.getValue(eContext); + Assert.fail(); + } catch (SpelEvaluationException see ) { + Assert.assertEquals(SpelMessage.TYPE_CONVERSION_ERROR,see.getMessageCode()); + } + expr = new SpelExpressionParser().parseRaw("(false?'abc':null)"); + Assert.assertEquals(null, expr.getValue()); + + // Assignment + try { + expr = new SpelExpressionParser().parseRaw("(='default')"); + expr.getValue(eContext); + Assert.fail(); + } catch (SpelEvaluationException see ) { + Assert.assertEquals(SpelMessage.SETVALUE_NOT_SUPPORTED,see.getMessageCode()); + } + } + + @Test + public void elvis_SPR7209_2() { + Expression expr = null; + // Have empty string treated as null for elvis + expr = new SpelExpressionParser().parseRaw("?:'default'"); + Assert.assertEquals("default", expr.getValue()); + expr = new SpelExpressionParser().parseRaw("\"\"?:'default'"); + Assert.assertEquals("default", expr.getValue()); + expr = new SpelExpressionParser().parseRaw("''?:'default'"); + Assert.assertEquals("default", expr.getValue()); + } + }