Index: pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmEnvironmentElResolver.java =================================================================== --- pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmEnvironmentElResolver.java (revision 6307) +++ pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmEnvironmentElResolver.java (working copy) @@ -27,32 +27,36 @@ import javax.el.ELContext; import javax.el.ELResolver; +import org.jbpm.api.JbpmException; import org.jbpm.pvm.internal.env.EnvironmentImpl; - /** * @author Tom Baeyens */ public class JbpmEnvironmentElResolver extends ELResolver { - + EnvironmentImpl environment; - + public JbpmEnvironmentElResolver(EnvironmentImpl environment) { this.environment = environment; } public Object getValue(ELContext context, Object base, Object property) { - // this resolver only resolves top level variable names to execution variable names. + // this resolver only resolves top level variable names to execution + // variable names. // only handle if this is a top level variable - if (base==null) { + if (base == null) { // we assume a NPE-check for property is not needed - // i don't think the next cast can go wrong. can it? + // i don't think the next cast can go wrong. can it? String name = (String) property; - Object object = environment.get(name); - if (object!=null) { + try { + Object object = environment.get(name, false); context.setPropertyResolved(true); return object; + } catch (JbpmException je) { + // Property not found... ignore in this case and return null below... + // Will be interpreted as property not found } } Index: pvm/src/main/java/org/jbpm/pvm/internal/env/BasicEnvironment.java =================================================================== --- pvm/src/main/java/org/jbpm/pvm/internal/env/BasicEnvironment.java (revision 6307) +++ pvm/src/main/java/org/jbpm/pvm/internal/env/BasicEnvironment.java (working copy) @@ -93,16 +93,30 @@ public Object get(String name) { return get(name, null); } - + public Object get(String name, String[] searchOrder) { - if (searchOrder==null) { - searchOrder = getDefaultSearchOrder(); + return get(name, searchOrder, true); + } + + public Object get(String name, boolean nullIfNotFound) { + return get(name, null, nullIfNotFound); + } + + public Object get(String name, String[] searchOrder, boolean nullIfNotFound) { + if (searchOrder == null) { + searchOrder = getDefaultSearchOrder(); + } + for (String contextName : searchOrder) { + Context context = contexts.get(contextName); + if (context.has(name)) { + return context.get(name); + } + } + if (nullIfNotFound) { + return null; + } else { + throw new JbpmException("Null value found for " + name + " but null is not allowed"); } - for (String contextName : searchOrder) { - Context context = contexts.get(contextName); - if (context.has(name)) return context.get(name); - } - return null; } public T get(Class type) { Index: pvm/src/main/java/org/jbpm/pvm/internal/env/EnvironmentImpl.java =================================================================== --- pvm/src/main/java/org/jbpm/pvm/internal/env/EnvironmentImpl.java (revision 6307) +++ pvm/src/main/java/org/jbpm/pvm/internal/env/EnvironmentImpl.java (working copy) @@ -141,6 +141,10 @@ * @return the object if it exists in the environment, null if there is no object with the given name in the specified searchOrder contexts. */ public abstract Object get(String name, String[] searchOrder); + + public abstract Object get(String name,String[] searchOrder, boolean nullAllowed) throws JbpmException; + + public abstract Object get(String name, boolean nullAllowed) throws JbpmException; /** searches an object based on type. The search doesn take superclasses of the context elements * into account. Index: pvm/src/test/java/org/jbpm/pvm/internal/expr/UelExpressionTest.java =================================================================== --- pvm/src/test/java/org/jbpm/pvm/internal/expr/UelExpressionTest.java (revision 0) +++ pvm/src/test/java/org/jbpm/pvm/internal/expr/UelExpressionTest.java (revision 0) @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jbpm.pvm.internal.expr; + +import org.jbpm.pvm.activities.WaitState; +import org.jbpm.pvm.internal.builder.ProcessDefinitionBuilder; + +import org.jbpm.pvm.internal.el.Expression; +import org.jbpm.pvm.internal.el.UelValueExpression; +import org.jbpm.pvm.internal.model.ExecutionImpl; +import org.jbpm.test.JbpmTestCase; + + +/** + * @author Tom Baeyens + */ +public class UelExpressionTest extends JbpmTestCase { + + public void testUelExpression() { + ExecutionImpl execution = (ExecutionImpl) ProcessDefinitionBuilder + .startProcess() + .startActivity("initial", new WaitState()) + .initial() + .endActivity() + .endProcess() + .startProcessInstance(); + + Expression expression = Expression.create("#{pv}", Expression.LANGUAGE_UEL_VALUE); + UelValueExpression uve = ((UelValueExpression) expression); + + execution.setVariable("pv", null); + + assertEquals(null, uve.evaluate(execution)); + } +} Index: test-db/src/test/java/org/jbpm/test/expr/UelExpressionTest.java =================================================================== --- test-db/src/test/java/org/jbpm/test/expr/UelExpressionTest.java (revision 0) +++ test-db/src/test/java/org/jbpm/test/expr/UelExpressionTest.java (revision 0) @@ -0,0 +1,60 @@ +package org.jbpm.test.expr; + +import java.util.Map; +import java.util.HashMap; +import org.jbpm.api.ProcessInstance; +import org.jbpm.test.JbpmTestCase; +import org.jbpm.api.JbpmException; + + +public class UelExpressionTest extends JbpmTestCase { + public static final String PROCESS_XML = "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + /** + * This test will cause javax.el.PropertyNotFoundException from EL + * because one of process variables will be set to null + */ + public void testPath1() { + // deploy process + deployJpdlXmlString(PROCESS_XML); + + try { + Map parameterMap = new HashMap(); + parameterMap.put("user_var1", "Some value"); + parameterMap.put("user_var2", null); + + // start process + ProcessInstance pi = executionService.startProcessInstanceByKey("UelExpressionTest", parameterMap); + assertTrue(pi.isEnded()); + } catch (JbpmException e) { + fail(e.toString()); + } + } + + public static class DocumentCreator { + /** + * Suppose var1 is essential and var2 is optional + * @param var1 + * @param var2 + */ + public void createDocument(String var1, String var2) { + System.out.println("Creating document"); + System.out.println("var1 = " + var1); + if (var2 != null) System.out.println("var2 = " + var2); + } + } + +}