-
1. Re: BPEL - receive/reply flush
adrian.andrei Feb 7, 2006 5:37 PM (in response to adrian.andrei)I think I found the issue: the send reply method is not commiting after send.
You may want to change the OutstandingRequest.java, line 64 (alpha4) and add session.commit();:finally { if (producer != null) { try { producer.close(); session.commit(); } catch (JMSException e) { log.warn(e); } } }
Regards,
AA -
2. Re: BPEL - receive/reply flush
aguizar Feb 8, 2006 6:53 PM (in response to adrian.andrei)The reason for using transacted JMS sessions is participating in global transactions when they are present, or commit/rollback at the same time the database transaction does.
When a listener receives a message, it begins a transaction, resumes the execution of the process instance until nothing more can be done, and then commits the transaction. That's why you get the reply when you introduce an inbound message activity. The "missing" session.commit() is, in fact, in RequestListener:public void onMessage(Message request) { [...] MessagerSession messagerSession = this.messagerSession; JbpmSession jbpmSession = messager.getJbpmSessionFactory().openJbpmSession(); org.hibernate.Session hibSession = jbpmSession.getSession(); Transaction tx = null; try { // start transaction to deliver request tx = hibSession.beginTransaction(); // reload persistent objects Receiver receiver = (Receiver) hibSession.load(Receiver.class, new Long(receiverId)); Token token = (Token) hibSession.load(Token.class, new Long(tokenId)); [...] // pass message content to the activity Element messageElem = (Element) ((ObjectMessage) request).getObject(); InboundMessageListener listener = receiver.getInboundMessageListener(); listener.messageReceived(receiver, messageElem, token); [...] // commit transaction to deliver request if (!messager.isDistributed()) messagerSession.getJmsSession().commit(); tx.commit(); } catch (Throwable e) { [...] // rollback jms transaction if (!messager.isDistributed()) { try { messagerSession.getJmsSession().rollback(); } catch (JMSException re) { log.warn("could not rollback jms session", re); } } // rollback db transaction if (tx != null) tx.rollback(); } finally { jbpmSession.close(); } }
I agree you could have complex processing after the reply activity and you want the message to leave as soon as it is ready. I can think of two alternatives:
Have the option to send the reply immediately, altough the ongoing transaction might be rolled back later. The client would receive a timely response, and be surprised in the future that the expected changes in the state of the process are not reflected.
Commit the transaction(s) and restart new one(s). This would result in a timely and reliable response, but consumes more resources and is unnecesary for many processes (isn't that the eternal argument against transactions?). In fact, it only makes sense for global transactions, as the separation of local db/jms transactions would produce inconsistent results in the event of failure anyway.
What behavior would you prefer to see? -
3. Re: BPEL - receive/reply flush
adrian.andrei Feb 8, 2006 7:49 PM (in response to adrian.andrei)I am not sure I explained my position. The commit I am talking about is in JMS, basically making sure that the reply (in this case) reaches the client in timely fashion.
Corelating that with the process instance persistency, it is a different story. My point doesn't exclude process instance persistency (for later recovery) since the message was sent already if the crash happens after the reply - on resume it will not sent twice.
If you want to take care of the client state as well, and persist (by posponing as much as you can the message delivery) their data is a different ballgame. This should be covered by future transaction protocols rather than that (Business Process Protocol, WS Protocol)
In my opinion is much more important to allow the user to define its own protocol rather than having him with hands tied.
So, I will tather go with the second option - if it is what I think it is.
I think that a BPEL implementation should focus on process instance recovery rather than implementing a data consistency protocol.
If the reply has been sent and then the BPEL crashed that is ok, upon recovery the BPEL should continue with the next activity.
If it was not delivered then upon recovery it needs to be delivered (removed from the queue) and reply activity marked as completed.
The current implementation makes the use of events (scope/eventHandlers) almost impossible to use - the client waits endlessly for the initial request to return (with the correlations for example)
Regards,
AA