You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ts...@apache.org on 2007/11/08 03:50:13 UTC

svn commit: r593000 - in /struts/sandbox/trunk/struts2-juel-plugin: ./ src/main/java/com/googlecode/struts2juel/ src/main/java/com/googlecode/struts2juel/elresolvers/ src/main/resources/ src/test/java/com/googlecode/struts2juel/

Author: tschneider
Date: Wed Nov  7 18:50:10 2007
New Revision: 593000

URL: http://svn.apache.org/viewvc?rev=593000&view=rev
Log:
Updates to get conversion working better and used the newInstance() to retrieve the expression factory

Added:
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/UELReflectionContextFactory.java
      - copied, changed from r592986, struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionContextFactory.java
    struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/UelTest.java
Removed:
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/ExpressionFactoryLocator.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionContextFactory.java
    struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/ExpressionFactoryLocatorTest.java
    struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/JuelTest.java
Modified:
    struts/sandbox/trunk/struts2-juel-plugin/pom.xml
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/CompoundRootELContext.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionProvider.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStack.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStackFactory.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/NullFunctionMapper.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/PropertyValueExpression.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/elresolvers/XWorkBeanELResolver.java
    struts/sandbox/trunk/struts2-juel-plugin/src/main/resources/struts-plugin.xml

Modified: struts/sandbox/trunk/struts2-juel-plugin/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/pom.xml?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/pom.xml (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/pom.xml Wed Nov  7 18:50:10 2007
@@ -29,12 +29,6 @@
 	</scm>
 	<dependencies>
 		<dependency>
-			<groupId>org.mortbay.jetty</groupId>
-			<artifactId>jsp-api-2.1</artifactId>
-			<version>6.1H.5-beta</version>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
 			<groupId>org.apache.struts</groupId>
 			<artifactId>struts2-core</artifactId>
 			<version>2.1.1-SNAPSHOT</version>
@@ -55,8 +49,7 @@
 			<groupId>de.odysseus.juel</groupId>
 			<artifactId>juel</artifactId>
 			<version>2.1.0</version>
-			<scope>test</scope>
-		</dependency>
+			</dependency>
 		<dependency>
 			<groupId>commons-beanutils</groupId>
 			<artifactId>commons-beanutils</artifactId>

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/CompoundRootELContext.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/CompoundRootELContext.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/CompoundRootELContext.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/CompoundRootELContext.java Wed Nov  7 18:50:10 2007
@@ -11,7 +11,6 @@
 import javax.el.VariableMapper;
 
 import com.googlecode.struts2juel.elresolvers.XWorkBeanELResolver;
-import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.util.CompoundRoot;
 
 /**
@@ -21,22 +20,20 @@
 public class CompoundRootELContext extends ELContext {
 	private VariableMapper variableMapper;
 	private FunctionMapper functionMapper = new NullFunctionMapper();
-	private XWorkConverter xworkConverter;
 
-	private static final ELResolver DEFAULT_RESOLVER_READ_WRITE = new CompositeELResolver() {
-		{
-			add(new ArrayELResolver(false));
-			add(new ListELResolver(false));
-			add(new MapELResolver(false));
-			add(new ResourceBundleELResolver());
-			add(new XWorkBeanELResolver(false));
-		}
-	};
-
-	public CompoundRootELContext(XWorkConverter xworkConverter,
-			CompoundRoot root) {
-		this.xworkConverter = xworkConverter;
+	private ELResolver DEFAULT_RESOLVER_READ_WRITE;
+
+	public CompoundRootELContext(CompoundRoot root) {
 		variableMapper = new CompoundRootVariableMapper(root);
+		DEFAULT_RESOLVER_READ_WRITE = new CompositeELResolver() {
+			{
+				add(new ArrayELResolver(false));
+				add(new ListELResolver(false));
+				add(new MapELResolver(false));
+				add(new ResourceBundleELResolver());
+				add(new XWorkBeanELResolver(false));
+			}
+		};
 	}
 
 	@Override
@@ -52,16 +49,5 @@
 	@Override
 	public FunctionMapper getFunctionMapper() {
 		return functionMapper;
-	}
-
-	public XWorkConverter getXworkConverter() {
-		return xworkConverter;
-	}
-
-	public Object convertType(Object value, Class toType) {
-		if (toType == null) {
-			return value;
-		}
-		return xworkConverter.convertValue(null, value, toType);
 	}
 }

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionProvider.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionProvider.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionProvider.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionProvider.java Wed Nov  7 18:50:10 2007
@@ -13,7 +13,7 @@
 import com.opensymphony.xwork2.util.reflection.ReflectionException;
 
 /**
- * A OgnlReflectionProvider based on Juel.
+ * A OgnlReflectionProvider based on Unified EL.
  */
 public class JuelReflectionProvider extends OgnlReflectionProvider {
 	private ExpressionFactory factory;
@@ -26,7 +26,7 @@
 
 	public void initExpressionFactory() {
 		if (factory == null) {
-			factory = ExpressionFactoryLocator.locateExpressFactory();
+			factory = ExpressionFactory.newInstance();
 		}
 	}
 	
@@ -35,7 +35,8 @@
     	initExpressionFactory();
         CompoundRoot compoundRoot = new CompoundRoot();
         compoundRoot.add(root);
-        ELContext elContext = new CompoundRootELContext(xworkConverter, compoundRoot);
+        ELContext elContext = new CompoundRootELContext(compoundRoot);
+        elContext.putContext(XWorkConverter.class, xworkConverter);
         // parse our expression
         ValueExpression valueExpr = factory.createValueExpression(elContext,
             expr, String.class);
@@ -47,7 +48,8 @@
     	initExpressionFactory();
         CompoundRoot compoundRoot = new CompoundRoot();
         compoundRoot.add(root);
-        ELContext elContext = new CompoundRootELContext(xworkConverter, compoundRoot);
+        ELContext elContext = new CompoundRootELContext(compoundRoot);
+        elContext.putContext(XWorkConverter.class, xworkConverter);
         // parse our expression
         ValueExpression valueExpr = factory.createValueExpression(elContext,
             expr, String.class);

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStack.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStack.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStack.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStack.java Wed Nov  7 18:50:10 2007
@@ -14,7 +14,7 @@
 import com.opensymphony.xwork2.util.ValueStack;
 
 /**
- * A ValueStack that uses Juel as the underlying Expression Language.
+ * A ValueStack that uses Unified EL as the underlying Expression Language.
  */
 public class JuelValueStack implements ValueStack {
 	private CompoundRoot root = new CompoundRoot();
@@ -54,7 +54,7 @@
 
 	public Object findValue(String expr, Class asType) {
 		try {
-			if (expr != null && expr.startsWith("#")) {
+			if (expr != null && expr.startsWith("#") && !expr.startsWith("#{")) {
 				int firstDot = expr.indexOf('.');
 				String key = expr.substring(1, firstDot);
 				String value = expr.substring(firstDot + 1);
@@ -66,10 +66,11 @@
 			}
 			if (expr != null && expr.startsWith("%{")) {
 				// replace %{ with ${
-				expr = "$" + expr.substring(1);
+				expr = "#" + expr.substring(1);
 			}
-			if (expr != null && !expr.startsWith("${")) {
-				expr = "${" + expr + "}";
+			if (expr != null && !expr.startsWith("${")
+					&& !expr.startsWith("#{")) {
+				expr = "#{" + expr + "}";
 			}
 			// parse our expression
 			ValueExpression valueExpr = factory.createValueExpression(
@@ -135,14 +136,9 @@
 	public void setValue(String expr, Object value,
 			boolean throwExceptionOnFailure) {
 		try {
-			if (expr != null && !expr.startsWith("${")) {
-				expr = "${" + expr + "}";
-			}
-			// hack to allow parameters to be set back
-			// uel doesn't support setting String[] values on String properties
-			if (value != null && value instanceof String[]
-					&& ((String[]) value).length == 1) {
-				value = ((String[]) value)[0];
+			if (expr != null && !expr.startsWith("${")
+					&& !expr.startsWith("#{")) {
+				expr = "#{" + expr + "}";
 			}
 			// parse our expression
 			ValueExpression valueExpr = factory.createValueExpression(
@@ -163,6 +159,7 @@
 		this.context = new TreeMap();
 		context.put(VALUE_STACK, this);
 		this.root = root;
-		this.elContext = new CompoundRootELContext(xworkConverter, root);
+		elContext = new CompoundRootELContext(root);
+        elContext.putContext(XWorkConverter.class, xworkConverter);
 	}
 }

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStackFactory.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStackFactory.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStackFactory.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelValueStackFactory.java Wed Nov  7 18:50:10 2007
@@ -22,7 +22,7 @@
 
 	public void initExpressionFactory() {
 		if (factory == null) {
-			factory = ExpressionFactoryLocator.locateExpressFactory();
+			factory = ExpressionFactory.newInstance();
 		}
 	}
 

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/NullFunctionMapper.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/NullFunctionMapper.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/NullFunctionMapper.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/NullFunctionMapper.java Wed Nov  7 18:50:10 2007
@@ -7,7 +7,7 @@
 public class NullFunctionMapper extends FunctionMapper {
 
 	@Override
-	public Method resolveFunction(String arg0, String arg1) {
+	public Method resolveFunction(String prefix, String localName) {
 		return null;
 	}
 

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/PropertyValueExpression.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/PropertyValueExpression.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/PropertyValueExpression.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/PropertyValueExpression.java Wed Nov  7 18:50:10 2007
@@ -15,10 +15,8 @@
 public class PropertyValueExpression extends ValueExpression {
 	private Object object;
 	private String property;
-    private XWorkConverter xworkConverter;
 
 	public PropertyValueExpression(Object object, String property) {
-    	this.xworkConverter = xworkConverter;
 		this.object = object;
 		this.property = property;
 	}
@@ -70,10 +68,14 @@
 	@Override
 	public void setValue(ELContext context, Object value) {
 		try {
-			Class propType = PropertyUtils.getPropertyType(object, property);
-			XWorkConverter xworkConverter = ((CompoundRootELContext) context).getXworkConverter();
-			Object convertedValue = xworkConverter.convertValue(value, propType);
-			PropertyUtils.setSimpleProperty(object, property, convertedValue);
+			XWorkConverter converter = (XWorkConverter) context
+					.getContext(XWorkConverter.class);
+			if (converter != null) {
+				Class propType = PropertyUtils
+						.getPropertyType(object, property);
+				value = converter.convertValue(null, value, propType);
+			}
+			PropertyUtils.setSimpleProperty(object, property, value);
 		} catch (IllegalAccessException e) {
 			throw new RuntimeException(e);
 		} catch (InvocationTargetException e) {

Copied: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/UELReflectionContextFactory.java (from r592986, struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionContextFactory.java)
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/UELReflectionContextFactory.java?p2=struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/UELReflectionContextFactory.java&p1=struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionContextFactory.java&r1=592986&r2=593000&rev=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/JuelReflectionContextFactory.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/UELReflectionContextFactory.java Wed Nov  7 18:50:10 2007
@@ -8,7 +8,7 @@
 /**
  * ReflectionContextFactory for Juel.
  */
-public class JuelReflectionContextFactory implements ReflectionContextFactory {
+public class UELReflectionContextFactory implements ReflectionContextFactory {
     public Map createDefaultContext(Object root) {
         return new HashMap();
     }

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/elresolvers/XWorkBeanELResolver.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/elresolvers/XWorkBeanELResolver.java?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/elresolvers/XWorkBeanELResolver.java (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/java/com/googlecode/struts2juel/elresolvers/XWorkBeanELResolver.java Wed Nov  7 18:50:10 2007
@@ -3,13 +3,10 @@
 import javax.el.BeanELResolver;
 import javax.el.ELContext;
 
-import com.googlecode.struts2juel.CompoundRootELContext;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 
 public class XWorkBeanELResolver extends BeanELResolver {
-
 	public XWorkBeanELResolver() {
-		super();
 	}
 
 	public XWorkBeanELResolver(boolean isReadOnly) {
@@ -19,11 +16,11 @@
 	@Override
 	public void setValue(ELContext context, Object base, Object property,
 			Object value) {
-		Class expectedType = getType(context, base, property);
-		if (expectedType != null) {
-			XWorkConverter converter = ((CompoundRootELContext) context)
-					.getXworkConverter();
-			value = converter.convertValue(null, value, expectedType);
+		XWorkConverter converter = (XWorkConverter) context
+				.getContext(XWorkConverter.class);
+		if (converter != null && base != null) {
+			Class propType = getType(context, base, property);
+			value = converter.convertValue(value, propType);
 		}
 		super.setValue(context, base, property, value);
 	}

Modified: struts/sandbox/trunk/struts2-juel-plugin/src/main/resources/struts-plugin.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/main/resources/struts-plugin.xml?rev=593000&r1=592999&r2=593000&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/main/resources/struts-plugin.xml (original)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/main/resources/struts-plugin.xml Wed Nov  7 18:50:10 2007
@@ -5,11 +5,11 @@
     "http://struts.apache.org/dtds/struts-2.0.dtd">
     
 <struts>
-	<bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="juel" class="com.googlecode.struts2juel.JuelValueStackFactory" />
-	<bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" name="juel" class="com.googlecode.struts2juel.JuelReflectionProvider" />	
-	<bean type="com.opensymphony.xwork2.util.reflection.ReflectionContextFactory" name="juel" class="com.googlecode.struts2juel.JuelReflectionContextFactory" />
+	<bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="uel" class="com.googlecode.struts2juel.JuelValueStackFactory" />
+	<bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" name="uel" class="com.googlecode.struts2juel.JuelReflectionProvider" />	
+	<bean type="com.opensymphony.xwork2.util.reflection.ReflectionContextFactory" name="uel" class="com.googlecode.struts2juel.UELReflectionContextFactory" />
 
-    <constant name="struts.valueStackFactory" value="juel" />
-    <constant name="struts.reflectionProvider" value="juel" />
-    <constant name="struts.reflectionContextFactory" value="juel" />
+    <constant name="struts.valueStackFactory" value="uel" />
+    <constant name="struts.reflectionProvider" value="uel" />
+    <constant name="struts.reflectionContextFactory" value="uel" />
 </struts>

Added: struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/UelTest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/UelTest.java?rev=593000&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/UelTest.java (added)
+++ struts/sandbox/trunk/struts2-juel-plugin/src/test/java/com/googlecode/struts2juel/UelTest.java Wed Nov  7 18:50:10 2007
@@ -0,0 +1,190 @@
+package com.googlecode.struts2juel;
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Map;
+
+import javax.el.ExpressionFactory;
+
+import org.apache.struts2.util.StrutsTypeConverter;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.util.CompoundRoot;
+
+public class UelTest extends XWorkTestCase {
+	private ExpressionFactory factory = ExpressionFactory.newInstance();
+	private XWorkConverter converter;
+	private DateFormat format = DateFormat.getDateInstance();
+
+	private class DateConverter extends StrutsTypeConverter {
+
+		@Override
+		public Object convertFromString(Map context, String[] values,
+				Class toClass) {
+			try {
+				return format.parseObject(values[0]);
+			} catch (ParseException e) {
+				return null;
+			}
+		}
+
+		@Override
+		public String convertToString(Map context, Object o) {
+			return format.format(o);
+		}
+
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+
+		converter = container.getInstance(XWorkConverter.class);
+		converter.registerConverter("java.util.Date", new DateConverter());
+	}
+
+	public void testBasicFind() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+		stack.setValue("${value}", "Hello World");
+		String value = stack.findString("${value}");
+		assertEquals("Hello World", value);
+
+		stack.setValue("${age}", "56");
+		String age = stack.findString("${age}");
+		assertEquals("56", age);
+	}
+
+	public void testSetStringArray() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+		stack.setValue("${value}", new String[] { "Hello World" });
+		String value = stack.findString("${value}");
+		assertEquals("Hello World", value);
+
+		stack.setValue("${age}", new String[] { "67" });
+		assertEquals(new Integer(67), stack.findValue("${age}"));
+	}
+
+	public void testDeferredFind() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+		stack.setValue("#{value}", "Hello World");
+		String value = stack.findString("#{value}");
+		assertEquals("Hello World", value);
+
+		stack.setValue("#{age}", "56");
+		String age = stack.findString("#{age}");
+		assertEquals("56", age);
+
+		stack.setValue("#{date}", new Date());
+		assertEquals(stack.findString("#{date}"), format.format(obj.getDate()));
+	}
+
+	public void test2LevelSet() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		TestObject nestedObj = new TestObject();
+		obj.setInner(nestedObj);
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+		stack.setValue("${inner.age}", "66");
+		assertEquals(66, obj.getInner().getAge());
+	}
+
+	public void testTypeConversion() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		TestObject inner = new TestObject();
+		obj.setInner(inner);
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+
+		stack.setValue("${age}", "22");
+		assertEquals(stack.findValue("${age}"), obj.getAge());
+
+		stack.setValue("${inner.value}", "George");
+		assertEquals(stack.findValue("${inner.value}"), obj.getInner()
+				.getValue());
+
+		stack.setValue("${inner.age}", "44");
+		assertEquals(stack.findValue("${inner.age}"), obj.getInner().getAge());
+
+		stack.setValue("${date}", new Date());
+		assertEquals(stack.findString("${date}"), format.format(obj.getDate()));
+	}
+
+	public void testNotFound() throws IllegalAccessException,
+			InvocationTargetException, NoSuchMethodException {
+		CompoundRoot root = new CompoundRoot();
+		TestObject obj = new TestObject();
+		root.add(obj);
+		JuelValueStack stack = new JuelValueStack(factory, converter);
+		stack.setRoot(root);
+		stack.setValue("${value}", "Hello World");
+		String value = stack.findString("${VALUENOTHERE}");
+		assertNull(value);
+
+		value = stack.findString("VALUENOTHERE");
+		assertNull(value);
+	}
+
+	public class TestObject {
+		private String value;
+		private int age;
+		private Date date;
+		private TestObject inner;
+
+		public String getValue() {
+			return value;
+		}
+
+		public void setValue(String value) {
+			this.value = value;
+		}
+
+		public int getAge() {
+			return age;
+		}
+
+		public void setAge(int age) {
+			this.age = age;
+		}
+
+		public Date getDate() {
+			return date;
+		}
+
+		public void setDate(Date date) {
+			this.date = date;
+		}
+
+		public TestObject getInner() {
+			return inner;
+		}
+
+		public void setInner(TestObject inner) {
+			this.inner = inner;
+		}
+
+	}
+}