Action ; Token.signal( ... ) ; Exception: locked tokens
jimknopf Nov 29, 2006 5:03 AMHi again,
I am calling an action and in this action i am fire a Rule from JRules. Based on the result of this rule i want to use a transition ( token.signal( "xxx" ) ).
But when i do this, i get an Exception. Is it not possible to use use token.signal in an action? And then, how should i realise actions in which i want to move to a next token? Is it only Possible with DecicionHandlers?
The Exception:
org.jbpm.JbpmException: can't continue execution on locked tokens. signalling the same token that executes an action is not allowed
at org.jbpm.graph.exe.Token.signal(Token.java:164)
at org.jbpm.graph.exe.Token.signal(Token.java:137)
</decision> <decision name="SGA"> <event type="node-enter"> <action name="checkSGA" class="actions.DefaultRuleAction"> <ruleFile>etr2.drl</ruleFile> <transitionName>t_sga a</transitionName> <transitionName_False>t_sga c</transitionName_False> </action> </event> <transition name="t_sga a" to="SGA A"></transition> <transition name="t_sga b" to="SGA B"></transition> <transition name="t_sga c" to="SGA C"></transition> </decision> <state name="SGA A">
Action:
public class DefaultRuleAction extends RuleAction { private static final long serialVersionUID = 8459834862286126414L; //Name der Variablen die in der Action beruecksichtigt werden. public List objectNames = null; public String transitionName = null; public String transitionName_False = null; public void execute( ExecutionContext executionContext) throws Exception { // TODO Auto-generated method stub System.err.println("My Timer-Rule-Action!"); if (this.ruleFile == null) { System.err.println("Es wurde kein Rule-File angegeben."); // TODO String aus einer Property laden. return; } // load up the RuleBase WorkingMemory workingMemory = null; try { RuleBase ruleBase = readRule(this.ruleFile); workingMemory = this.generateWorkingMemory( ruleBase ); this.assertObjectsIn( workingMemory, executionContext ); workingMemory.fireAllRules(); if( RuleAction.getResultFrom( workingMemory ) == true ){ if(this.transitionName != null){ executionContext.getToken().signal( transitionName ); } }else{ if(this.transitionName_False != null){ executionContext.getToken().signal( transitionName_False ); } } } catch (FileNotFoundException fnfe) { System.err.println("Es wurde ein falsches Rule-File angegeben."); fnfe.printStackTrace(); // TODO String aus einer Property laden. } catch (MissingRuleResultException mrre){ System.err.println("Es wurde kein RuleResult-Object im WorkingMemory der Regel gefunden."); mrre.printStackTrace(); // TODO String aus einer Property laden. } catch (Exception e){ System.err.println("Rule-Base konnte nicht angelegt werden."); e.printStackTrace(); // TODO String aus einer Property laden. } finally{ if(workingMemory != null) workingMemory.dispose(); } //ArcaViaController.getInstance().cancelTimer( executionContext.getTimer() ); }
public abstract class RuleAction implements ActionHandler{ /* Name der Variablen des Workflows welche in das WorkingMemory der Regel eingepflegt werden sollen.*/ protected List objectNames = null; protected String ruleFile = null; private RuleResult ruleResult = new RuleResult(); /** * Please note that this is the "low level" rule assembly API. * @throws Exception */ protected static RuleBase readRule(String ruleFileLocation) throws Exception{ // ruleFileLocation = "src" + // System.getProperty("file.separator") + // "rules" + // System.getProperty("file.separator") + // ruleFileLocation; System.err.println( ruleFileLocation ); //read in the source Reader source = null; try{ source = new InputStreamReader( RuleAction.class.getResourceAsStream( "/"+ruleFileLocation ) ); // source = new InputStreamReader( new FileInputStream( new File(ruleFileLocation) ) ); }catch( Exception e ){ throw new FileNotFoundException(); } //optionally read in the DSL (if you are using it). //Reader dsl = new InputStreamReader( DroolsTest.class.getResourceAsStream( "/mylang.dsl" ) ); //Use package builder to build up a rule package. //An alternative lower level class called "DrlParser" can also be used... DrlParser parser = new DrlParser(); PackageDescr packageDescr = parser.parse( source); /* * Wenn der default PackageBuilder eine Exception erzeugt (was er tat), * soll man ihn dann durch diese Code-Zeilen ersetzen laut der JBoss wiki Seite */ PackageBuilderConfiguration pkgBuilderCfg = new PackageBuilderConfiguration(); pkgBuilderCfg.setCompiler(PackageBuilderConfiguration.JANINO); PackageBuilder builder = new PackageBuilder(pkgBuilderCfg); //default PackageBuilder //PackageBuilder builder = new PackageBuilder(); //this wil parse and compile in one step //NOTE: There are 2 methods here, the one argument one is for normal DRL. //builder.addPackageFromDrl( source ); builder.addPackage(packageDescr); //Use the following instead of above if you are using a DSL: //builder.addPackageFromDrl( source, dsl ); //get the compiled package (which is serializable) Package pkg = builder.getPackage(); //add the package to a rulebase (deploy the rule package). RuleBase ruleBase = RuleBaseFactory.newRuleBase(); ruleBase.addPackage( pkg ); return ruleBase; } /** * Lädt aus dem uebergebenen WorkingMemory ein RuleResult-Object und * liefert den Result-Wert von diesem Object zurueck. * Dieser Result-Wert kann in einer Regel dazu verwendet werden, * ein Ergebniss zurueck zu liefern (zur Zeit nur true oder false). * * @param wm WorkingMemory aus welchem das RuleResult-Object geprueft werden soll. * @return Den Result-Wert des RuleResult-Objectes in dem uebergeben WorkingMemory. * @throws MissingRuleResultException Es gibt kein RuleResult-Object im uebergebenen WorkingMemory. */ protected static boolean getResultFrom( WorkingMemory wm ) throws MissingRuleResultException{ // if( wm == null ) // throw new NullPointerException(); List ruleResults = wm.getObjects( RuleResult.class ); if( ruleResults.size() < 1 ) throw new MissingRuleResultException(); RuleResult rs = (RuleResult)ruleResults.get(0); return rs.getResult(); } /** * Lädt das RuleResult Object in den WorkingMemory * so das man Ihn später in der Rule verwenden kann und * das in Ihm stehende Ergebniss der Regel mit der Methode * <code>getResultFrom(WorkingMemory wm)</code> auslesen kann. * * @param wm WorkingMemory welches mit einem RuleResult Object vorbereitet werden soll. */ protected void prepareWorkingMemory( WorkingMemory wm ){ // if( wm == null ) // throw new NullPointerException(); wm.assertObject( this.ruleResult ); } /** * Erzeugt einen neuen WorkingMemory in der uebergebenen RuleBase und * ruft fuer diesen dann <code>prepareWorkingMemory( WorkingMemory wm )</code> * auf um den WorkingMemory mit dem RuleResult-Object zu beladen. * * @param ruleBase RuleBase in welchem das neue WorkingMemory erzeugt werden soll. * @return Das Erzeugte WorkingMemory. */ protected WorkingMemory generateWorkingMemory( RuleBase ruleBase){ WorkingMemory wm = ruleBase.newWorkingMemory(); this.prepareWorkingMemory( wm ); return wm; } /** * Lädt die Variablen des Workflows welche der Action bei Ihrem Aufruf * durch den Workflow uebergeben wurden in den WorkingMemory der Regel. * * @param wm WorkingMemory welcher mit den Objecten beladen werden soll. * @param executionContext Context mittels welcher die Variablen enthaelt. */ protected void assertObjectsIn( WorkingMemory wm, ExecutionContext executionContext ){ if (objectNames != null) { // Ausgewählte Variablen einladen ContextInstance ci = executionContext.getContextInstance(); Iterator it = objectNames.iterator(); while (it.hasNext()) { String objectName = (String) it.next(); wm.assertObject(ci.getVariable(objectName)); } }/* * Zu gefährlich in der Handhabung daher deaktiviert else{ // * Alle Variablen einladen wenn keine uebergeben wurden * ContextInstance ci = executionContext.getContextInstance(); * Iterator it = ci.getVariables().entrySet().iterator(); * while(it.hasNext()){ workingMemory.assertObject( it.next() ); } } */ } }