3 Replies Latest reply on Feb 8, 2006 7:49 PM by Adrian Andrei

    BPEL - receive/reply flush

    Adrian Andrei Newbie

      Hi,

      I am writing a rather complex BPEL process that expects events while is looping in order to perform some lengthy process.

      My client times-out after 1 minute, and I was hoping to avoid that by responding to the receive with an early reply rather than wait for the loop to end. Even after I changed the BPEL code to have the reply activity before the lengthy loop the client is not receiving the response unless the loop ends.

      I then compared with your ATM example and I noticed that onMessage follows closely the reply activity. After I added an artificial onMessage after the reply the client received the initial response (did not get the second one though).

      I think that reply should flush the response as quickly as possible and not wait for another receive/onMessage activity to do that. One may want to implement complex, protocol-based business processes, (similar to ATM) therefore the response should be received promptly.

      Regards,
      AA

        • 1. Re: BPEL - receive/reply flush
          Adrian Andrei Newbie

          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
            Alejandro Guizar Master

            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 Newbie

              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