OK, here is the JoinAsync class. Instead of using a join when you have
asychronous logic going on, use a standard node that calls this in its action
and asynchronous logic should work.
Yes, it is a bit of a hack because it essentially reloads the parentToken for
analysis and then throws it away, but hey, it gets the job done.
| /**
| *
| */
| package com.whatever.jbpm;
|
| import java.rmi.RemoteException;
| import java.util.Collection;
| import java.util.Iterator;
|
| import org.apache.commons.logging.Log;
| import org.apache.commons.logging.LogFactory;
| import org.dom4j.Element;
| import org.jbpm.graph.action.Script;
| import org.jbpm.graph.def.Node;
| import org.jbpm.graph.exe.ExecutionContext;
| import org.jbpm.graph.exe.Token;
| import org.jbpm.jpdl.xml.JpdlXmlReader;
| import org.jbpm.jpdl.xml.Parsable;
| import org.jbpm.graph.def.ActionHandler;
| import org.jbpm.db.JbpmSession;
| import org.jbpm.db.JbpmSessionFactory;
|
| //public class JoinAsync extends Node implements Parsable {
|
| public class JoinAsync implements ActionHandler {
|
| private static final long serialVersionUID = 1L;
|
| /**
| * specifies if this joinhandler is a discriminator. a descriminator
| * reactivates the parent when the first concurrent token enters the
join.
| */
| private boolean isDiscriminator = false;
|
| /**
| * a fixed set of concurrent tokens.
| */
| private Collection tokenNames = null;
|
| /**
| * a script that calculates concurrent tokens at runtime.
| */
| private Script script = null;
|
| /**
| * reactivate the parent if the n-th token arrives in the join.
| */
| private int nOutOfM = -1;
|
| private static final JbpmSessionFactory jbpmSessionFactory =
JbpmSessionFactory.buildJbpmSessionFactory();
|
| public void read(Element element, JpdlXmlReader jpdlReader) {
| }
|
| public void execute(ExecutionContext executionContext) {
| Token token = executionContext.getToken();
|
| // if this token is not able to reactivate the parent,
| // we don't need to check anything
| if (token.isAbleToReactivateParent()) {
|
| // the token arrived in the join and can only reactivate
| // the parent once
| token.setAbleToReactivateParent(false);
|
| Node joinNode = token.getNode();
|
| Token parentToken = token.getParent();
| Token originalParentToken = parentToken;
|
| if (parentToken != null) {
|
| /*
========================================================== */
|
| // The parent token must be reloaded from the
database for
| // asynchronous behaviour to work properly
| log.debug("need to reload parent token from
database");
| JbpmSession jbpmSession = null;
| try {
| jbpmSession =
jbpmSessionFactory.openJbpmSession();
|
| // Get the parent token from the
database
| log.debug("about to reload parent token
from database");
| parentToken =
jbpmSession.getGraphSession().loadToken(parentToken.getId());
| log.debug("reloaded parent token from
database!");
| // Need to load the children before
closing the session
| Iterator iter =
parentToken.getChildren().values().iterator();
| while (iter.hasNext()) {
| Token t = (Token) iter.next();
| // Need to set the flag on this
token since it isn't committed yet
| if (t.getId() == token.getId())
{
|
t.setAbleToReactivateParent(false);
| }
| }
| log.debug("reloaded parent token's
children from database!");
|
| } catch (Exception ex) {
| System.out.println("error: " +
ex.toString());
| } finally {
| if (jbpmSession != null) {
| jbpmSession.close();
| }
| }
|
| /*
========================================================== */
|
| boolean reactivateParent = true;
|
| // if this is a discriminator
| if (isDiscriminator) {
| // reactivate the parent when the first
token arrives in the
| // join. this must be the first token
arriving because otherwise
| // the isAbleToReactivateParent() of
this token should have been
| // false
| // above.
| reactivateParent = true;
|
| // if a fixed set of tokenNames is
specified at design time...
| }
| else if (tokenNames != null) {
| // check reactivation on the basis of
those tokenNames
| reactivateParent =
mustParentBeReactivated(parentToken, tokenNames.iterator());
|
| // if a script is specified
| }
| else if (script != null) {
|
| // check if the script returns a
collection or a boolean
| Object result = script.eval(token);
| // if the result is a collection
| if (result instanceof Collection) {
| // it must be a collection of
tokenNames
| Collection runtimeTokenNames =
(Collection) result;
| reactivateParent =
mustParentBeReactivated(parentToken, runtimeTokenNames.iterator());
|
| // if it's a boolean...
| }
| else if (result instanceof Boolean) {
| // the boolean specifies if the
parent needs to be reactivated
| reactivateParent = ((Boolean)
result).booleanValue();
| }
|
| // if a nOutOfM is specified
| }
| else if (nOutOfM != -1) {
|
| int n = 0;
| // wheck how many tokens already
arrived in the join
| Iterator iter =
parentToken.getChildren().values().iterator();
| while (iter.hasNext()) {
| Token concurrentToken = (Token)
iter.next();
| if (joinNode ==
concurrentToken.getNode()) {
| n++;
| }
| }
| if (n < nOutOfM) {
| reactivateParent = false;
| }
|
| // if no configuration is specified..
| }
| else {
| // the default behaviour is to check
all concurrent tokens and
| // reactivate
| // the parent if the last token arrives
in the join
| reactivateParent =
mustParentBeReactivated(parentToken, parentToken.getChildren().keySet()
| .iterator());
| }
|
| /*
========================================================== */
|
| // Reset the parent token back to the one on
the open session
| parentToken = originalParentToken;
|
| /*
========================================================== */
|
| // if the parent token needs to be reactivated
from this join node
| if (reactivateParent) {
|
| // write to all child tokens that the
parent is already reactivated
| Iterator iter =
parentToken.getChildren().values().iterator();
| while (iter.hasNext()) {
| ((Token)
iter.next()).setAbleToReactivateParent(false);
| }
|
| // write to all child tokens that the
parent is already reactivated
| ExecutionContext parentContext = new
ExecutionContext(parentToken);
| joinNode.leave(parentContext);
| }
| }
| }
| }
|
| public boolean mustParentBeReactivated(Token parentToken, Iterator
childTokenNameIterator) {
| boolean reactivateParent = true;
| while ((childTokenNameIterator.hasNext()) &&
(reactivateParent)) {
| String concurrentTokenName = (String)
childTokenNameIterator.next();
|
| Token concurrentToken =
parentToken.getChild(concurrentTokenName);
|
| if (concurrentToken.isAbleToReactivateParent()) {
|
log.debug("===================================================");
|
log.debug("===================================================");
| log.debug("join will not yet reactivate parent:
found concurrent token '" + concurrentToken + "'");
|
log.debug("===================================================");
|
log.debug("===================================================");
| reactivateParent = false;
| }
| }
| if (reactivateParent) {
|
log.debug("===================================================");
|
log.debug("===================================================");
| log.debug("all tokens have reached join. allowing
passage");
|
log.debug("===================================================");
|
log.debug("===================================================");
| }
| return reactivateParent;
| }
|
| public Script getScript() {
| return script;
| }
|
| public void setScript(Script script) {
| this.script = script;
| }
|
| public Collection getTokenNames() {
| return tokenNames;
| }
|
| public void setTokenNames(Collection tokenNames) {
| this.tokenNames = tokenNames;
| }
|
| public boolean isDiscriminator() {
| return isDiscriminator;
| }
|
| public void setDiscriminator(boolean isDiscriminator) {
| this.isDiscriminator = isDiscriminator;
| }
|
| public int getNOutOfM() {
| return nOutOfM;
| }
|
| public void setNOutOfM(int nOutOfM) {
| this.nOutOfM = nOutOfM;
| }
|
| private static final Log log = LogFactory.getLog(JoinAsync.class);
| }
|
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3911813#3911813
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3911813
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user