[jboss-user] [JBoss jBPM] - Re: dynamic commands

gogoasa do-not-reply at jboss.com
Fri Sep 21 06:01:33 EDT 2007


Here is my current implementation of BshCommand in case anybody needs it.
It supports passing optional parameters to scripts (in case you keep your script as a resource and want to pass it a parameter without having to String.replaceAll(...):

package org.jbpm.command;
  | 
  | import java.util.HashMap;
  | import java.util.Iterator;
  | import java.util.Map;
  | 
  | import org.jbpm.JbpmContext;
  | 
  | import bsh.Interpreter;
  | 
  | /**
  |  * this Command executes a BeanShell script, optionally binding some variables. 
  |  * This way you can dynamically execute arbitrary code on your jBPM installation. 
  |  */
  | public class BshCommand implements Command {
  | 
  | 	String JBPMCONTEXT_BINDING_VARIABLE = "jbpmContext";
  | 	
  | 	// the script code
  | 	protected String code;
  | 	
  | 	// variables to bind
  | 	protected Map scriptVariables;
  | 	
  | 	public BshCommand(String code) {
  | 		this(code, new HashMap());
  | 	}
  | 	
  | 	public BshCommand(String code, Map scriptVariables) {
  | 		this.setCode(code);
  | 		this.setScriptVariables(scriptVariables);
  | 	}
  | 	
  | 	/**
  | 	 * as Java does not have inline constructors for Maps but it does have constructors for arrays, you may prefer to provide
  | 	 * arguments using this constructor. 
  | 	 * 
  | 	 * @see BshCommand(String code, Map scriptVariables)
  | 	 */
  | 	public BshCommand(String code, String[] keys, Object[] values) {
  | 		if (keys == null || values == null)
  | 			throw new NullPointerException("cannot accept null keys or values");
  | 		if (keys.length != values.length)
  | 			throw new IllegalArgumentException("keys and values arrays must be of the same length");
  | 		
  | 		Map map = new HashMap();
  | 		for (int i = 0; i < keys.length; i++)
  | 			map.put(keys, values);
  | 		
  | 		this.setCode(code);
  | 		this.setScriptVariables(map);
  | 	}
  | 	
  | 	/**
  | 	 * convenient alias for BshCommand(String code, String[] keys, Object[] values) if you only want to pass one argument to
  | 	 * your script
  | 	 */
  | 	public BshCommand(String code, String key, Object value) {
  | 		this(code, new String[] {key}, new Object[] {value});
  | 	}
  | 	
  | 	
  | 	public Object execute(JbpmContext jbpmContext) throws Exception {
  | 		Interpreter interpreter = new Interpreter();
  | 		
  | 		interpreter.set(JBPMCONTEXT_BINDING_VARIABLE, jbpmContext);
  | 		
  | 		if (this.scriptVariables != null) {
  | 			for (Iterator i = this.scriptVariables.keySet().iterator(); i.hasNext();) {
  | 				String varName = (String) i.next();
  | 				if (varName.equals(JBPMCONTEXT_BINDING_VARIABLE))
  | 					continue;
  | 				Object o = this.scriptVariables.get(varName);
  | 				interpreter.set(varName, o);
  | 			}
  | 		}
  | 		Object result = interpreter.eval(this.getCode());
  | 		return result;
  | 	}
  | 
  | 	// accessors 
  | 	
  | 	public String getCode() {
  | 		return code;
  | 	}
  | 
  | 	public void setCode(String code) {
  | 		this.code = code;
  | 	}
  | 
  | 	public Map getScriptVariables() {
  | 		return scriptVariables;
  | 	}
  | 
  | 	public void setScriptVariables(Map scriptVariables) {
  | 		this.scriptVariables = scriptVariables;
  | 	}
  | 	
  | 	private static final long serialVersionUID = 1L;
  | }
  | 

some usage example. Suppose you have a script like this as a classpath resource (do not call it script.bsh if you deploy under jboss because jboss will think it must deploy it as an ejb. Call it moveTokenToNodeAndSignal.bsh.command for example):


  | // forcibly move a process instance's token to "System error" node and signal it to "restart".
  | 
  | pi = jbpmContext.getProcessInstance(pid);
  | tk = pi.getRootToken();
  | 
  | pdef = pi.getProcessDefinition();
  | node = pdef.getNode("System error");
  | 
  | tk.addLog(new org.jbpm.logging.log.MessageLog("forcing restart of process that has no 'restart' leaving transition")); 
  | tk.setNode(node);
  | tk.signal("restart");


  | String script = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("moveTokenToNodeAndSignal.bsh.command"));
  | commandService.execute(script, "pid", 4);
  | 



View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4087147#4087147

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4087147



More information about the jboss-user mailing list