[jbpm-commits] JBoss JBPM SVN: r6740 - in jbpm4/trunk/modules: pvm/src/main/java/org/jbpm/pvm/internal/wire/descriptor and 2 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Tue Oct 5 04:42:01 EDT 2010
Author: rebody
Date: 2010-10-05 04:42:00 -0400 (Tue, 05 Oct 2010)
New Revision: 6740
Added:
jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ExpressionTest.java
Modified:
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/Expression.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmElFactory.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmFunctionMapper.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/descriptor/ObjectDescriptor.java
jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ResourceBundleELResovlerTest.java
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml
Log:
JBPM-2887 support custom function in EL.
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/Expression.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/Expression.java 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/Expression.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -131,6 +131,11 @@
return elContext;
}
+ public static void reset() {
+ expressionFactory = null;
+ elContext = null;
+ }
+
public abstract String getExpressionString();
public abstract boolean isLiteralText();
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmElFactory.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmElFactory.java 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmElFactory.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -34,7 +34,7 @@
public static JbpmElFactory getJbpmElFactory() {
JbpmElFactory contextFactory = EnvironmentImpl.getFromCurrent(JbpmElFactory.class, false);
- if (contextFactory==null) {
+ if (contextFactory == null) {
contextFactory = new JbpmElFactoryImpl();
}
return contextFactory;
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmFunctionMapper.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmFunctionMapper.java 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/el/JbpmFunctionMapper.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -40,6 +40,9 @@
public JbpmFunctionMapper(Map<String, Class<?>> functionClassMap) {
this.functionClassMap = functionClassMap;
+ if (functionClassMap.isEmpty()) {
+ functionClassMap.put("", JstlFunction.class);
+ }
}
public Method resolveFunction(String prefix, String localName) {
@@ -52,7 +55,7 @@
Class<?> functionClass = functionClassMap.get(prefix);
if (functionClass == null) {
if (log.isInfoEnabled()) {
- log.info("cannot find functionClass for prefix : " + prefix);
+ log.info("cannot find functionClass for prefix : [" + prefix + "]");
}
return null;
}
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/descriptor/ObjectDescriptor.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/descriptor/ObjectDescriptor.java 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/descriptor/ObjectDescriptor.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -94,7 +94,7 @@
* TODO check if this member can be replaced by a RefDescriptor in the factoryDescriptor member.
*
* */
- String factoryObjectName;
+ protected String factoryObjectName;
protected Expression expression;
@@ -136,75 +136,81 @@
Object object = null;
Class<?> clazz = null;
- if (className!=null) {
+ if (className != null) {
try {
clazz = ReflectUtil.classForName(className);
} catch (Exception e) {
- throw new JbpmClassNotFoundException("couldn't load class "+className, e);
+ throw new JbpmClassNotFoundException("couldn't load class " + className, e);
}
- if (methodName==null) {
+ if (methodName == null) {
// plain instantiation
try {
Object[] args = getArgs(wireContext, argDescriptors);
Constructor<?> constructor = ReflectUtil.findConstructor(clazz, argDescriptors, args);
- if (constructor==null) {
- throw new WireException("couldn't find constructor "+clazz.getName()+" with args "+Arrays.toString(args));
+ if (constructor == null) {
+ throw new WireException("couldn't find constructor " + clazz.getName() + " with args " + Arrays.toString(args));
}
object = constructor.newInstance(args);
} catch (WireException e) {
throw e;
} catch (Exception e) {
- throw new WireException("couldn't create object '"+(name!=null ? name : className)+"': "+e.getMessage(), e);
+ throw new WireException("couldn't create object '" + (name != null ? name : className) + "': " + e.getMessage(), e);
}
}
- } else if (factoryObjectName!=null) {
+ } else if (factoryObjectName != null) {
// referenced factory object
object = wireContext.get(factoryObjectName);
- if (object==null) {
- throw new WireException("can't invoke method '"+methodName+"' on null, resulted from fetching object '"+factoryObjectName+"' from this wiring environment");
+ if (object == null) {
+ throw new WireException("can't invoke method '" + methodName
+ + "' on null, resulted from fetching object '" + factoryObjectName + "' from this wiring environment");
}
} else if (factoryDescriptor!=null) {
// factory object descriptor
object = wireContext.create(factoryDescriptor, false);
- if (object==null) {
- throw new WireException("created factory object is null, can't invoke method '"+methodName+"' on it");
+ if (object == null) {
+ throw new WireException("created factory object is null, can't invoke method '" + methodName + "' on it");
}
- } else if (expression!=null) {
+ } else if (expression != null) {
object = expression.evaluateInScope(wireContext.getScopeInstance());
}
- if (methodName!=null) {
+ if (methodName != null) {
try {
object = invokeMethod(methodName, argDescriptors, wireContext, object, clazz);
} catch (WireException e) {
throw e;
} catch (Exception e) {
- throw new WireException("couldn't invoke factory method "+methodName+": "+e.getMessage(), e);
+ throw new WireException("couldn't invoke factory method " + methodName + ": " + e.getMessage(), e);
}
}
return object;
}
- public static Object invokeMethod(String methodName, List<ArgDescriptor> argDescriptors, WireContext wireContext, Object object, Class< ? > clazz) throws Exception {
+ public static Object invokeMethod(String methodName,
+ List<ArgDescriptor> argDescriptors,
+ WireContext wireContext,
+ Object object,
+ Class<?> clazz) throws Exception {
// method invocation on object or static method invocation in case object is null
- if (object!=null) {
+ if (object != null) {
clazz = object.getClass();
}
Object[] args = ObjectDescriptor.getArgs(wireContext, argDescriptors);
Method method = ReflectUtil.findMethod(clazz, methodName, argDescriptors, args);
- if (method==null) {
+ if (method == null) {
// throw exception but first, generate decent message
- throw new WireException("method "+ReflectUtil.getSignature(methodName, argDescriptors, args)+" is not available on "+
- (object!=null ? "object "+object+" ("+clazz.getName()+")" : "class "+clazz.getName()));
+ throw new WireException("method " + ReflectUtil.getSignature(methodName, argDescriptors, args) + " is not available on "
+ + (object != null ? "object " + object + " (" + clazz.getName() + ")" : "class " + clazz.getName()));
}
if (object == null && (!Modifier.isStatic(method.getModifiers()))) {
// A non static method is invoked on a null object
- throw new WireException("method "+ clazz.getName() + "." + ReflectUtil.getSignature(methodName, argDescriptors, args)+" is not static. It cannot be called on a null object.");
+ throw new WireException("method " + clazz.getName() + "." + ReflectUtil.getSignature(methodName, argDescriptors, args)
+ + " is not static. It cannot be called on a null object.");
}
object = ReflectUtil.invoke(method, object, args);
return object;
@@ -225,37 +231,37 @@
if (isAutoWireEnabled) {
autoWire(object, wireContext);
}
- if (operations!=null) {
- for(Operation operation: operations) {
+ if (operations != null) {
+ for(Operation operation : operations) {
operation.apply(object, wireContext);
}
}
- } catch (Exception e) {
- throw new WireException("couldn't initialize object '"+(name!=null ? name : className)+"': "+e.getMessage(), e);
+ } catch (Throwable e) {
+ throw new WireException("couldn't initialize object '" + (name != null ? name : className) + "': " + e.getMessage(), e);
}
}
public Class<?> getType(WireDefinition wireDefinition) {
- if (className!=null) {
+ if (className != null) {
try {
return ReflectUtil.classForName(className);
} catch (Exception e) {
- throw new WireException("couldn't load class '"+className+"'", e);
+ throw new WireException("couldn't load class '" + className + "'", e);
}
}
Descriptor descriptor = null;
- if (factoryDescriptor!=null) {
+ if (factoryDescriptor != null) {
descriptor = factoryDescriptor;
- } else if (factoryObjectName!=null) {
+ } else if (factoryObjectName != null) {
descriptor = wireDefinition.getDescriptor(factoryObjectName);
}
- if (descriptor!=null) {
+ if (descriptor != null) {
Class<?> factoryClass = descriptor.getType(wireDefinition);
- if (factoryClass!=null) {
+ if (factoryClass != null) {
Method method = ReflectUtil.findMethod(factoryClass, methodName, argDescriptors, null);
- if (method!=null) {
+ if (method != null) {
return method.getReturnType();
}
}
@@ -271,11 +277,11 @@
*/
protected void autoWire(Object object, WireContext wireContext) {
Class<?> clazz = object.getClass();
- while (clazz!=null) {
+ while (clazz != null) {
Field[] declaredFields = clazz.getDeclaredFields();
- if (declaredFields!=null) {
- for (Field field: declaredFields) {
- if (! Modifier.isStatic(field.getModifiers())) {
+ if (declaredFields != null) {
+ for (Field field : declaredFields) {
+ if (!Modifier.isStatic(field.getModifiers())) {
String fieldName = field.getName();
Class<?> fieldType = field.getType();
@@ -306,16 +312,16 @@
}
}
- if (autoWireValue!=null) {
+ if (autoWireValue != null) {
try {
- if (log.isTraceEnabled()) log.trace("auto wiring field "+fieldName+" in "+name);
+ if (log.isTraceEnabled()) log.trace("auto wiring field " + fieldName + " in " + name);
ReflectUtil.set(field, object, autoWireValue);
} catch (JbpmException e) {
if(e.getCause() instanceof IllegalArgumentException) {
- log.info("WARNING: couldn't auto wire "+fieldName+" (of type "+fieldType.getName()+") " +
- "with value "+autoWireValue + " (of type "+autoWireValue.getClass().getName()+")");
+ log.info("WARNING: couldn't auto wire " + fieldName + " (of type " + fieldType.getName() + ") "
+ + "with value " + autoWireValue + " (of type " + autoWireValue.getClass().getName() + ")");
} else {
- log.info("WARNING: couldn't auto wire "+fieldName+" with value "+autoWireValue);
+ log.info("WARNING: couldn't auto wire " + fieldName + " with value " + autoWireValue);
}
}
}
@@ -335,9 +341,9 @@
*/
public static Object[] getArgs(WireContext wireContext, List<ArgDescriptor> argDescriptors) throws Exception {
Object[] args = null;
- if (argDescriptors!=null) {
+ if (argDescriptors != null) {
args = new Object[argDescriptors.size()];
- for(int i=0; i<argDescriptors.size(); i++) {
+ for (int i = 0; i < argDescriptors.size(); i++) {
ArgDescriptor argDescriptor = argDescriptors.get(i);
Object arg;
try {
@@ -346,7 +352,7 @@
} catch (RuntimeException e) {
// i have made sure that the runtime exception is caught everywhere the getArgs method
// is used so that a better descriptive exception can be rethrown
- throw new Exception("couldn't create argument "+i+": "+e.getMessage(), e);
+ throw new Exception("couldn't create argument " + i + ": " + e.getMessage(), e);
}
}
}
@@ -369,7 +375,7 @@
* @param operation operation to add.
*/
public void addOperation(Operation operation) {
- if (operations==null) {
+ if (operations == null) {
operations = new ArrayList<Operation>();
}
operations.add(operation);
Added: jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ExpressionTest.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ExpressionTest.java (rev 0)
+++ jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ExpressionTest.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -0,0 +1,144 @@
+
+package org.jbpm.pvm.internal.el;
+
+import java.util.*;
+import junit.framework.*;
+import org.jbpm.pvm.internal.model.*;
+import org.jbpm.pvm.internal.env.*;
+import org.jbpm.pvm.internal.processengine.*;
+
+public class ExpressionTest extends TestCase {
+ public void testPrimivite() {
+ Expression expr = Expression.create("#{1}");
+ assertEquals(Long.valueOf(1L), expr.evaluate());
+ }
+
+ public void testSimpleVariable() {
+ Expression expr = Expression.create("#{variableName}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("variableName", "variableValue");
+ assertEquals("variableValue", expr.evaluate(executionImpl));
+ }
+
+ public void testMap() {
+ Map map = new HashMap();
+ map.put("key", "value");
+
+ Expression expr = Expression.create("#{map.key}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("map", map);
+ assertEquals("value", expr.evaluate(executionImpl));
+ }
+
+ public void testList() {
+ List list = new ArrayList();
+ list.add("value");
+
+ Expression expr = Expression.create("#{list[0]}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("list", list);
+ assertEquals("value", expr.evaluate(executionImpl));
+ }
+
+ public void testArray() {
+ String[] array = new String[]{"value"};
+
+ Expression expr = Expression.create("#{array[0]}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("array", array);
+ assertEquals("value", expr.evaluate(executionImpl));
+ }
+
+ public void testBean() {
+ Bean bean = new Bean();
+ bean.setName("Lingo");
+
+ Expression expr = Expression.create("#{bean.name}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("bean", bean);
+ assertEquals("Lingo", expr.evaluate(executionImpl));
+ }
+
+ public void testMethod() {
+ Bean bean = new Bean();
+
+ Expression expr = Expression.create("#{bean.hello('Lingo')}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("bean", bean);
+ assertEquals("Hello Lingo", expr.evaluate(executionImpl));
+ }
+
+ public void testFunction() {
+ List list = new ArrayList();
+ list.add("1");
+ list.add("2");
+
+ Expression expr = Expression.create("#{length(list)}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ executionImpl.setVariable("list", list);
+ assertEquals(2, expr.evaluate(executionImpl));
+ }
+
+ public void testCustomFunction() {
+ EnvironmentFactory environmentFactory = ProcessEngineImpl.parseXmlString(
+ "<jbpm-configuration>" +
+ " <process-engine-context>" +
+ " <object class='org.jbpm.pvm.internal.el.JbpmElFactoryImpl'>" +
+ " <field name='functionClassMap'>" +
+ " <map>" +
+ " <entry>" +
+ " <key>" +
+ " <string value=''/>" +
+ " </key>" +
+ " <value>" +
+ " <class class-name='org.jbpm.pvm.internal.el.JstlFunction'/>" +
+ " </value>" +
+ " </entry>" +
+ " <entry>" +
+ " <key>" +
+ " <string value='myPrefix'/>" +
+ " </key>" +
+ " <value>" +
+ " <class class-name='" + CustomFunction.class.getName() + "'/>" +
+ " </value>" +
+ " </entry>" +
+ " </map>" +
+ " </field>" +
+ " </object>" +
+ " </process-engine-context>" +
+ "</jbpm-configuration>"
+ );
+
+ EnvironmentImpl environment = environmentFactory.openEnvironment();
+ try {
+ Expression.reset();
+ Expression expr = Expression.create("#{myPrefix:doSomething()}");
+ ExecutionImpl executionImpl = new ExecutionImpl();
+ assertEquals("do something", expr.evaluate(executionImpl));
+ } finally {
+ environment.close();
+ }
+ }
+
+ public static class Bean {
+ private String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String hello(String username) {
+ return "Hello " + username;
+ }
+ }
+
+ public static class CustomFunction {
+ public static String doSomething() {
+ return "do something";
+ }
+ }
+}
Modified: jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ResourceBundleELResovlerTest.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ResourceBundleELResovlerTest.java 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/pvm/src/test/java/org/jbpm/pvm/internal/el/ResourceBundleELResovlerTest.java 2010-10-05 08:42:00 UTC (rev 6740)
@@ -18,11 +18,11 @@
}
public static class MyResources extends ListResourceBundle {
- public Object[][] getContents() {
- return contents;
- }
- static final Object[][] contents = {
- {"text.title", "Title"}
- };
- }
+ public Object[][] getContents() {
+ return contents;
+ }
+ static final Object[][] contents = {
+ {"text.title", "Title"}
+ };
+ }
}
Modified: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml 2010-10-05 01:43:06 UTC (rev 6739)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml 2010-10-05 08:42:00 UTC (rev 6740)
@@ -1,15 +1,189 @@
<chapter id="scripting">
<title>Scripting</title>
-
- <para>Only jUEL is configured as the scripting language. jUEL is
- an implementation of the Unified Expression Language. For detailed description
- of how to use UEL, please refer to
- <ulink url="http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html">
- the JEE 5 Tutorial, section Unified Expression Language</ulink>
- </para>
-
- <para>To configure other scripting languages then jUEL, please
- refer to the developer's guide (non supported).
- </para>
+ <section>
+ <title>Script Manager</title>
+
+ <para>
+ Only jUEL is configured as the scripting language. jUEL is
+ an implementation of the Unified Expression Language. For detailed description
+ of how to use UEL, please refer to
+ <ulink url="http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html">
+ the JEE 5 Tutorial, section Unified Expression Language</ulink>
+ </para>
+
+ <para>
+ To configure other scripting languages then jUEL, please
+ refer to the developer's guide (non supported).
+ </para>
+ </section>
+
+ <section>
+ <title>Expression</title>
+
+ <para>
+ From jBPM-4.4, we used <ulink url="http://juel.sourceforge.net/">jUEL</ulink> to evaluate the expressions.
+ Here is the types of expressions that we supported:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Constants</para>
+ <programlisting><![CDATA[
+Expression expr = Expression.create("#{1}");
+assertEquals(Long.valueOf(1L), expr.evaluate());]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Simple Variable</para>
+ <programlisting><![CDATA[
+Expression expr = Expression.create("#{variableName}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("variableName", "variableValue");
+assertEquals("variableValue", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Map</para>
+ <programlisting><![CDATA[
+Map map = new HashMap();
+map.put("key", "value");
+
+Expression expr = Expression.create("#{map.key}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("map", map);
+assertEquals("value", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>List</para>
+ <programlisting><![CDATA[
+List list = new ArrayList();
+list.add("value");
+
+Expression expr = Expression.create("#{list[0]}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("list", list);
+assertEquals("value", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Array</para>
+ <programlisting><![CDATA[
+String[] array = new String[]{"value"};
+
+Expression expr = Expression.create("#{array[0]}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("array", array);
+assertEquals("value", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Java Bean</para>
+ <programlisting><![CDATA[
+Bean bean = new Bean();
+bean.setName("Lingo");
+
+Expression expr = Expression.create("#{bean.name}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("bean", bean);
+assertEquals("Lingo", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Invoke Method</para>
+ <programlisting><![CDATA[
+Bean bean = new Bean();
+
+Expression expr = Expression.create("#{bean.hello('Lingo')}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("bean", bean);
+assertEquals("Hello Lingo", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>BundleResource</para>
+ <programlisting><![CDATA[
+MyResources myResources = new MyResources();
+ExecutionImpl execution = new ExecutionImpl();
+execution.setVariable("resourceBundle", myResources);
+
+Expression expr = Expression.create("#{resourceBundle['text.title']}");
+Object result = expr.evaluate(execution);
+
+assertEquals("Title", result);]]>
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>Function</para>
+ <programlisting><![CDATA[
+List list = new ArrayList();
+list.add("1");
+list.add("2");
+
+Expression expr = Expression.create("#{length(list)}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+executionImpl.setVariable("list", list);
+assertEquals(2, expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Besides the default function - org.jbpm.pvm.internal.el.JstlFunction, we could provide our own function to EL.
+ </para>
+
+ <para>
+ First, we should modify jbpm.default.cfg.xml, add our custom function class and related prefix, like this:
+ </para>
+
+ <programlisting><![CDATA[
+
+<object class='org.jbpm.pvm.internal.el.JbpmElFactoryImpl'>
+ <field name='functionClassMap'>
+ <map>
+ <entry>
+ <key>
+ <string value=''/>
+ </key>
+ <value>
+ <class class-name='org.jbpm.pvm.internal.el.JstlFunction'/>
+ </value>
+ </entry>
+ <entry>
+ <key>
+ <string value='myPrefix'/>
+ </key>
+ <value>
+ <class class-name='custom.CustomFunction'/>
+ </value>
+ </entry>
+ </map>
+ </field>
+</object>]]>
+ </programlisting>
+
+ <para>
+ Then all of static methods of CustomFunction could be invoked in EL.
+ </para>
+
+ <programlisting><![CDATA[
+public class CustomFunction {
+ public static String doSomething() {
+ return "do something";
+ }
+}]]>
+ </programlisting>
+
+ <para>
+ The expression will use the prefix to get the related method of function class.
+ </para>
+
+ <programlisting><![CDATA[
+Expression expr = Expression.create("#{myPrefix:doSomething()}");
+ExecutionImpl executionImpl = new ExecutionImpl();
+assertEquals("do something", expr.evaluate(executionImpl));]]>
+ </programlisting>
+ </section>
+
</chapter>
More information about the jbpm-commits
mailing list