add EventAttributeELResolver

improved invalid variable ex message
This commit is contained in:
Keith Donald
2008-04-11 15:24:55 +00:00
parent a5a5c8e4cd
commit ab3d438119
7 changed files with 131 additions and 9 deletions

View File

@@ -25,6 +25,7 @@ import org.springframework.core.style.ToStringCreator;
public class EvaluationAttempt {
private Expression expression;
private Object context;
/**

View File

@@ -15,19 +15,17 @@
*/
package org.springframework.binding.expression;
import org.springframework.core.NestedRuntimeException;
/**
* Indicates an expression evaluation failed.
*
* @author Keith Donald
*/
public class EvaluationException extends NestedRuntimeException {
public class EvaluationException extends RuntimeException {
/**
* The evaluation attempt that failed. Transient because an EvaluationAttempt is not serializable.
*/
private transient EvaluationAttempt evaluationAttempt;
private EvaluationAttempt evaluationAttempt;
/**
* Creates a new evaluation exception.
@@ -35,7 +33,17 @@ public class EvaluationException extends NestedRuntimeException {
* @param cause the underlying cause of this exception
*/
public EvaluationException(EvaluationAttempt evaluationAttempt, Throwable cause) {
super(evaluationAttempt + " failed - make sure the expression is evaluatable in the context provided", cause);
this(evaluationAttempt, evaluationAttempt
+ " failed - make sure the expression is evaluatable in the context provided", cause);
}
/**
* Creates a new evaluation exception.
* @param evaluationAttempt the evaluation attempt that failed
* @param cause the underlying cause of this exception
*/
public EvaluationException(EvaluationAttempt evaluationAttempt, String message, Throwable cause) {
super(message, cause);
this.evaluationAttempt = evaluationAttempt;
}

View File

@@ -44,7 +44,9 @@ public class ELExpression implements Expression {
try {
Object result = valueExpression.getValue(ctx);
if (result == null && !ctx.isPropertyResolved()) {
throw new EvaluationException(new EvaluationAttempt(this, context), null);
EvaluationAttempt attempt = new EvaluationAttempt(this, context);
throw new EvaluationException(attempt, attempt
+ " failed: the expression path did not resolve--is the base variable incorrect?", null);
}
return result;
} catch (javax.el.PropertyNotFoundException e) {
@@ -59,7 +61,9 @@ public class ELExpression implements Expression {
try {
valueExpression.setValue(ctx, value);
if (!ctx.isPropertyResolved()) {
throw new EvaluationException(new SetValueAttempt(this, context, value), null);
SetValueAttempt attempt = new SetValueAttempt(this, context, value);
throw new EvaluationException(attempt, attempt
+ " failed: the expression path did not resolve--is the base variable incorrect?", null);
}
} catch (javax.el.PropertyNotFoundException e) {
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);

View File

@@ -12,6 +12,7 @@ import javax.el.VariableMapper;
import junit.framework.TestCase;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserException;
@@ -70,12 +71,24 @@ public class ELExpressionParserTests extends TestCase {
assertEquals(new Long(2), exp.getValue(new TestBean()));
}
public void testParseEvalExpressionWithContextCustomTestBeanResolver() {
public void testParseEvalExpressionWithContextCustomELVariableResolver() {
String expressionString = "specialProperty";
Expression exp = parser.parseExpression(expressionString, new FluentParserContext().evaluate(TestBean.class));
assertEquals("Custom resolver resolved this special property!", exp.getValue(new TestBean()));
}
public void testParseBeanEvalExpressionInvalidELVariable() {
try {
String expressionString = "bogus";
Expression exp = parser.parseExpression(expressionString, new FluentParserContext()
.evaluate(TestBean.class));
exp.getValue(new TestBean());
fail("Should have failed");
} catch (EvaluationException e) {
}
}
public void testParseLiteralExpression() {
String expressionString = "'value'";
Expression exp = parser.parseExpression(expressionString, null);
@@ -181,9 +194,10 @@ public class ELExpressionParserTests extends TestCase {
public Object getValue(ELContext arg0, Object arg1, Object arg2) {
if (arg1 == null && arg2.equals("specialProperty")) {
arg0.setPropertyResolved(true);
return "Custom resolver resolved this special property!";
} else {
throw new IllegalStateException();
return null;
}
}

View File

@@ -31,6 +31,7 @@ import org.springframework.util.ClassUtils;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.engine.AnnotatedAction;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
/**
@@ -50,6 +51,7 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser {
addPropertyAccessor(MutableAttributeMap.class, new MutableAttributeMapPropertyAccessor());
addPropertyAccessor(RequestContext.class, new RequestContextPropertyAccessor(new ObjectPropertyAccessor()));
addPropertyAccessor(Action.class, new ActionPropertyAccessor());
addPropertyAccessor(Event.class, new EventPropertyAccessor());
}
/**
@@ -193,4 +195,18 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser {
}
}
/**
* Resolves event attributes.
*/
private static class EventPropertyAccessor implements PropertyAccessor {
public Object getProperty(Map context, Object target, Object name) throws OgnlException {
Event event = (Event) target;
return event.getAttributes().get(name.toString());
}
public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
throw new OgnlException("Cannot set attributes on an Event instance - operation not allowed");
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.expression.el;
import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.PropertyNotWritableException;
import org.springframework.webflow.execution.Event;
/**
* Resolves attributes on an {@link Event} instance.
* @author Keith Donald
*/
public class EventAttributesElResolver extends ELResolver {
public Class getCommonPropertyType(ELContext elContext, Object base) {
if (base instanceof Event) {
return Object.class;
} else {
return null;
}
}
public Iterator getFeatureDescriptors(ELContext elContext, Object base) {
return null;
}
public Class getType(ELContext elContext, Object base, Object property) {
if (base instanceof Event) {
elContext.setPropertyResolved(true);
return Object.class;
} else {
return null;
}
}
public Object getValue(ELContext elContext, Object base, Object property) {
if (base instanceof Event) {
Event event = (Event) base;
elContext.setPropertyResolved(true);
return event.getAttributes().get(property.toString());
} else {
return null;
}
}
public boolean isReadOnly(ELContext elContext, Object base, Object property) {
if (base instanceof Event) {
elContext.setPropertyResolved(true);
return true;
} else {
return false;
}
}
public void setValue(ELContext elContext, Object base, Object property, Object value) {
if (base instanceof Event) {
elContext.setPropertyResolved(true);
throw new PropertyNotWritableException("Event attributes cannot be set with an expression.");
}
}
}

View File

@@ -59,6 +59,7 @@ public class WebFlowELExpressionParser extends ELExpressionParser {
customResolvers.add(new ImplicitFlowVariableELResolver(context));
customResolvers.add(new ScopeSearchingELResolver(context));
customResolvers.add(new SpringBeanWebFlowELResolver(context));
customResolvers.add(new EventAttributesElResolver());
customResolvers.add(new ActionMethodELResolver());
ELResolver resolver = new DefaultELResolver(customResolvers);
return new WebFlowELContext(resolver);