Client driven business activity

3 Comments

In my previous blog, Distributed Compensation with REST and jBPM, I talked about removing complexity from both the distributed protocol and the server by forcing (or enabling, depending on your perspective) the client to handle things like business activity and compensating transactions. I asked the question, where does this leave WS-BA or more importantly, JBoss’s Business Activity Framework? It could easily still be used in a one process, web application. Many web applications are long running transactions that require compensation. But, I still think JBoss’s Business Activity Framework could be useful to help orchestrate distributed services, even restful ones, if we make compensation metadata available to the client so a local-only business activity coordinator could do its work locally. This would give us the decoupling benefit of BA, but would also allow us to keep our remote services stateless (and restful). The idea would be to move the BA annotations from the bean class, to the business interface:

public interface TravelAgent {
	@BACompensatedBy(value="cancel")
        @BAResult("reservationNumber")
        public int book(int room);

        public void cancel(@BAParam("reservationNumber") int reserverationNumber);
}

A client-side smart proxy could hide the interaction with the local activity coordinator. Another idea would be for the business process engine to introspect service references to see if they are annotated with compensation metadata, and interact with the coordinator themselves. A nice side effect of putting the metadata within the interface is that your service becomes self documenting. The user of this service knows exactly what’s going on by looking at the code.

You could combine this annotation-driven approach with the restful client-side framework I suggested in my comments on JSR-311.

public interface TravelAgent {
	@BACompensatedBy(value="cancel")
        @BAResult("$r.getId()")
        @UriTemplate("/hotel/reservations")
        @HttpMethod("POST")
        @Location("/hotel/reservations/$r.id")
        public Reservation book(@QueryParam("room") int room);

        @UriTemplate("/hotel/reservations/{reservationNumber}")
        @HttpMethod("DELETE")
        public void cancel(@BAParam("reservationNumber")  @UriParam("reservationNumber") int reserverationNumber);
}

This could make it fairly easy and metadata driven to have restful services interact with business activity.

In Java-to-Java calls, for example a remote or local EJB invocation, you wouldn’t necessarily need an interface-driven approach. The JBoss EJB 3.0 implementation, for instance, allows you to define both client-side and server side interceptors. At deployment time, the EJB container could scan the bean class for BA metadata, create a client interceptor initialized with this meta information, and attach the client interceptor to the proxy that is published to clients.

I think client driven conversations where the client holds all state makes for better written distributed services as they can be written in a more stateless, scalable manner. This doesn’t mean that you’d be able to apply this pattern to all scenarios. That’s why I think it might be interesting to make this approach configurable. The client must drive the compensation, the server must be allowed to participate in resource registration, or even a configuration of the client can decide whether it wants drive the coordination or not are all valid scenarios. Anyways, if you experiment with any of these patterns let me know. It would be cool to hear some real, live user experience instead of just guessing on whether or not this would be a good approach.

Mark’s rebuttal on compensations with REST and JBPM

3 Comments

I got what I hoped for. Mark Little responded to my previous blog. Cool, now I’ll really start to learn something…. Let me respond to some of his comments:

Bill: “One of my concerns is the complexity of the WS-* layer and how it affects maintainability and evolvability of a distributed system. WS-* requires both the client and server to have the necessary middleware components and libraries installed to work.”

Mark: Yes, but that’s the case for any distributed system: the endpoints have got to be able to understand each other or go through some intermediary that can do the protocol/data translation. The same is true for HTTP though.
Mark’s right, I said something obvious, but I think the layers you have to have in sync are very different in size and complexity. While a REST over HTTP web service only really requires an HTTP client, HTTP web service, and maybe an XML parser, WS-* requires those plus all the WS-* libraries, plus any generated stubs. What I like about REST over HTTP you can actually tell the server what data format you’re sending (content-type) and what format you want back (accept). Maybe there is something equivalent in the WS soup of specifications, but it doesn’t seem like that is what the industry is pushing as its default framework.

Bill: “What I continually like about REST over HTTP is that there is little to no requirement on either the client or server side for additional libraries or generated stubs other than a http client library and a http server.

Mark: So let’s assume we can get everyone to agree to use HTTP (not a big assumption, so I’m happy with this). Then we have to get them to agree to the protocol data, the format, representation, etc. that actually flows between the endpoints. It’s no good someone saying “because we agree on PUT or GET that’s the end of the story.” That’s a bit like saying that because we agree on using letters and envelopes to send mail around the world the recipients will be able to understand what’s being sent!

Its eerie. I gave the same argument to Vinoski over private email months ago, but then I thought about it a bit more. Don’t you have to do the same thing with WS? You still have to agree on the message you are sending. What is the name of the remote method call you are invoking. What are its parameters. What is the data format of its parameters, and so on. What allowed me to break the internal conflict I had was when I came to this realization: What if you think of PUT, GET, POST, DELETE, and OPTIONS as a set of metadata?

@Put void createOrder(Document theOrder);
@Delete void deleteOrder(int orderNum);
@Get Document getOrder();

Maybe I’m crazy, but these HTTP operations are really nothing more than annotations on a method. In using REST over HTTP, yes, you still have to agree on the data format exchange, but you are providing clearly defined, distinct, exact, metadata on the behavior of your endpoint. Behavior that can be generically communicated to mature tools and services that have been around forever that your operations department knows how to operate and fine tune your application with.

Mark: The Web works because the standards/specifications on which it is based were laid down back in the early 1990’s and haven’t really changed. The W3C manages them and everyone agreed to abide by them very early on; there’s strong commercial incentive not to change things. That has nothing to do with REST and everything to do with protocol agreement: same thing has happened with WS-*.

I am officially in my late 30s. I did work through both the short-lived DCE and long-lived CORBA eras that touted the same story of interoperability. Sorry if I am skeptical and worried that the industry will yet again re-invent itself in another 5-10 years.

Mark: Yes, we have interoperability on the WWW (ignoring the differences in HTML syntax and browsers). But we do not have interoperabilty for transactions, reliable messaging, workflow etc.

A wise man once told me if you run into a wall, redefine the problem. To me, that’s what the whole REST exercise is, redefining the problem in distributed computing. The whole underlying point of my previous blog was that maybe you don’t need interoperability for transactions, reliable messaging, and workflow in a distributed environment, if you let the client drive the application. Yes, you need transactions, reliable messaging and workflow at the client. The idioms I described with jBPM use all three of these subsystems, but they do not require a remote protocol definition. As responsible engineers, we should be questioning the need for WS-*. The amount of investment is just too huge for any organization. There’s too much money and time to be lost.

Bill’s next point was around flexibility. He mentions the ordering of compensations can sometimes (often?) be important and that you can’t rely on ordering within WS-BA. Unfortunately that’s not correct, as was pointed out several years ago.
Apologies. I didn’t make this mistake intentionally. The article Mark points out was one of the things I read before writing my previous blog. The talk of scopes was a little confusing there. Seemed more of talk of nested transactions than the control of ordering. But, even so, I still don’t get the need for it. Why the need for BA if it is not going to do things automatically for you? If the line between your business process and your compensation engine is starting to blur, why not have your bpm and compensation engine be the same thing? Cuts out one less piece of infrastructure you have to install and manage.

So just because I decide to use REST and HTTP doesn’t mean I get instant portability and interoperability. Yes, I get interoperability at the low level, but it says nothing about interoperability at the payload. That’s damn hard to achieve, as we’ve seen over the past 7+ years.

Not so sure this is true. If your content type is text/xml, you’ll probably have an XSD associated with it. If you use the design by contract to implement your web services that people like the Spring guys are pushing, you really have the same thing.

Bill: You still have strong decoupling in a bpm driven activity. The difference is that instead of compensation being hidden by the server, it is visible, and in your face, embedded directly in the business process. With jBPM, you can look at the process diagram and know exactly the flow of success and failure conditions of your distributed application. With BA, you would have to dive into the documentation and code to determine how your application functions.”

Mark: Yes, that’s right, but no different to what you’d find with a good WS-BPEL implementation.

See? I knew I’d learn something. But when I said “a bpm engine like jBPM might be a better solution to manage compensations.” I meant any bpm engine. What I really want here is to have the client drive the application and simplify the complexity of the distributed protocol. This is why I said I really liked the idea of using BA with a web application. It would all be local and controllable. After reading up on BPEL compensation handlers, I also like the idea of using them with RESTful web services. Again, put all the responsibility on the client for managing the coordination.  Then we don’t have a dual dependency on an in-sync client and server.

Distributed Compensation with REST and jBPM

9 Comments

Over the past few months I’ve been leading up to something. Although I was researching and diving into specifics of compensations, jbpm, and REST, I had a much grander purpose in writing these specific blogs:

These blogs were specifically written as a thought exercise in what it would take to write a coordinated distributed application. What pieces would we really need? Where does WS-* fit in? How about REST and BPM? Do we really need a business activity framework? How can we write scalable and maintainable distributed systems? I want to pull together my thoughts on the answers to these questions in this blog entry as well as ask a few more.

Maintainability: REST over WS

One of my concerns is the complexity of the WS-* layer and how it affects maintainability and evolvability of a distributed system. WS-* requires both the client and server to have the necessary middleware components and libraries installed to work. A distributed application usually means that it is an integration project. You are probably integrating with systems you do not control. There is probably a good chance you would not be able to bring down these systems to install or upgrade their middleware architecture. They may be poorly maintained or even not maintained at all. This is where the idea of REST comes in to simplify things and make things more usable over time. Since it has constrained, well defined interfaces over a mature and stable protocol, it has a higher chance of letting your distributed applications evolve as the WWW has evolved.

What I continually like about REST over HTTP is that there is little to no requirement on either the client or server side for additional libraries or generated stubs other than a http client library and a http server. This doesn’t mean that you cannot use a client and/or server side framework to implement your RESTful services or connect to an existing service. You are free to use whatever you want to make yourself productive, but not at the expense of requiring the client or server to have anything installed other than HTTP support.

Flexibility: BPM vs. WS-Business Activity

Earlier this year Mark Little introduced me to the idea of compensating transactions and a framework that could manage such an application. My first thought was that this stuff was interesting, but my intuition was telling me that compensations were something that might have to be modeled rather than managed. That compensations were more of a business process than something that could be coordinated automatically. My feeling is that compensation could easily become too complex for a transaction manager to handle generically. That if you modified a transaction manager to handle these more complex scenarios it would quickly start to look like a bpm framework.

Take an abort event for example. The coordinator in a compensating framework like WS-Business Activity has to make decisions on what order to perform a compensatory action on the resources participating in the activity. A default LIFO ordering seems very appropriate on the surface, but it falls apart in even the simplest of examples. For instance, let’s revisit the example I gave in my previous blog of the ordering of a computer at an online retailer. The business process might look like this:

  1. Bill credit card
  2. Pull parts from inventory
  3. Assemble computer
  4. Install software
  5. QA
  6. Ship

Let’s say the customer canceled the order after it had reached the QA state, #5. Having the customer wait for a LIFO compensation to receive refund on their credit card is just not acceptable. They will not want to wait for installed software to be wiped, the computer disassembled and parts sent back to inventory before they receive their refund. Therefore a 1-4-3-2 ordering of compensations might be more appropriate. Let’s expand this scenario even further. What if the customer paid in cash? The cash refund process might take just as long as disassembling the computer would. Maybe it would make more sense to do the refund in parallel with the other compensations? So, state #1 could be done in parallel with 4, 3, and 2, but, 4-3-2 still has ordering dependencies. You can’t disassemble the computer before you’ve wiped the hardrive. You can’t send parts back to inventory before you’ve disassembled the computer. So, you see, in even the simplest of business activities, you can have variable and complex compensation ordering. This is why I think a bpm engine like jBPM might be a better solution to manage compensations.

When I had discussed this with Mark, he made a good point that you are just replacing one coordinator(BA) with another (jBPM). You still need a coordination engine. Although he is semantically correct, I think the solutions are very different. With BA you have something generic and decoupled from the business process. In a distributed system, it is also a defined contract that both the client and server must obey. Which brings me to my favorite quote in the O’Reilly RESTful Web Services book:

The client should be in charge of managing its own path through the application

While WS-BA puts the onus on both the client and server to have WS libraries that are of the same version and can interact with one another. This all works beautifully in controlled environments. You have a very nice decoupling between compensations and business logic in both client and server side code. But…. What happens when BA versions are out of sync, there’s interoperability problems, or even worse, one or more of the services you have to coordinate does not support WS-BA? With jBPM, success and failure paths are a part of the business process. There isn’t necessarily a contract between the client and server as the client is responsible for knowing how to compensate and to perform the compensation. You still have strong decoupling in a bpm driven activity. The difference is that instead of compensation being hidden by the server, it is visible, and in your face, embedded directly in the business process. With jBPM, you can look at the process diagram and know exactly the flow of success and failure conditions of your distributed application. With BA, you would have to dive into the documentation and code to determine how your application functions.

In his blog in late August, Heuristics, one-phase commit and compensations, Mark Little talks about his early compensation framework and its interaction with heuristics:

In both of these problem scenarios what typically happens is that someone (e.g., a system administrator) has to get to grips with the inconsistent data and figure out what was going on in the rest of the application in order to try to impose consistency. One of the important reasons this can’t really happen automatically (at the TM level) is because it required semantic information about the application, that simply isn’t available to the transaction system. They compensate manually.

Until then. What we were proposing was allowing developers to register compensation transactions with the coordinator that would be triggered upon certain events, such as heuristic outcomes or one-phase errors. And to do it opaquely as far as the application developer was concerned. Because these compensations are part of the transaction, they’d get logged so that they would be available during recovery. Plus, a developer could also define whether presumed abort, presumed commit or presumed nothing were the best approaches for the individual transaction to use (it has an affect on recovery and failure scenarios).

Reading this fed more fuel to my idea that compensations really belonged as part of a process model. Transactions that have heuristic outcomes many times require human intervention as well as action by the framework itself. Yes, there’s a lot a transaction manager could do to make it easier to record business activities, but you’re still going to have interact with a real person to resolve many issues. jBPM is great at modeling work that requires a human.

But what about reliability?

Great, so we’re going to use something like jBPM as both our coordination and compensation engine and REST to expose our services on the network. Can we trust these things to provide us with the reliability and consistency that we expect out of something like WS and WS-BA? If you’re modelling compensations in jBPM, you’re gonna need the ability to reliably perform these compensations. Luckily, I’ve already answered how you can guarantee execution and failure handling in jBPM. But what about REST, what does it add? If you have truly written RESTful services, you have a lot of reliability and consistency built into your application. HTTP GET, PUT, and DELETE are supposed to be idempotent, meaning that it doesn’t matter how many times you’ve invoked them, the result is the same. While jBPM can guarantee you execution and failure handling, it can’t guarantee that these events won’t be duplicated. Since your RESTful services should be idempotent, you won’t have to worry about it! (I know, easier said then done.)

Where does that leave WS-BA?

I did discuss my ideas a bit with Mark. One of his comments that struck home was “Imagine if you had to explicitly tell all of your XA resource managers to prepare and commit?” I’ll admit that in a WS-BA world, writing a client that integrates a bunch of distributed services into one business activity would be uber simple and clean. The work being done with the JBoss Business Activity Framework simplifies the server side greatly as well. A compensation framework like JBoss Business Activity, might work really really well in the controlled environment of a web application. Until I actually write one of these applications or talk to a bunch of users and customers that have used WS-BA to model their integration project, I will remain skeptical. I just hope that I can get the feedback I need to further formulate my thoughts on this subject. Your thoughts and experiences??????

Compensating Transaction Framework

5 Comments

Mark Little’s team has put together a nice annotation framework on top of the JBoss TS, Business Activity service. What?!? JBoss has a Business Activity service? Yup, we do. Have had it for a long while, accept nobody but Mark (did he even?) made any noise about it within the JBoss community. What is the Business Activity service? Mark does a better job in an article he wrote a few years ago, (his book is even better), so I won’t get into a lot of detail. To summarize in my own words, the Business Activity service looks very much like XA and traditional transactions, except they are really meant for long running conversations or activity. Traditional transactions are not good in that scenario because they hold onto resources too long. Particpants in BA look a lot like resources in XA. The register themselves with an activity. An activity is very similar to a transaction in that you begin it, and either cancel (rollback) or close (commit) the activity when you are finished. Participants can interact at closing with a 2 phase protocol, much like 2PC in regular XA. The difference is that the rules are much more lax. Participants can choose to leave the activity whenever they like as well as some other neat things. See Mark’s book or article for more details. Oh, and I forgot, this is a WS-* specification.

So back to the annotation framework. Its pretty cool. It allows you to tie in a compensatory action to an executed method. So, if the business activity is cancelled, the coordinator will automatically callback to this compensation. Here’s an example:

@Stateless
@SOAPBinding(style = SOAPBinding.Style.RPC)
@HandlerChain(file = "jaxws-ba-handler-server.xml")
public class HotelBAImpl implements HotelBA
{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.PARAMETERS_MATCH)
	public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
		return reservationNumber;
	}

	@WebMethod
	public void cancel(String user, String pass, Integer room)
	{
		// ... business logic
	}
}

So, in the example, if you invoke the book() method of the Hotel service, it will interact with the coordinator to register a compensation action. This action will be to invoke the cancel() method with the exact parameters that were passed into the book() method if the activity is aborted. Alternatively, you can map the book() method’s return value and parameters to the compensation action using the @BAResult and @BAParam.

{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        @BAResult("reservationNumber")
        public Integer book(@BAParam("user") String user, @BAParam("password") String pass, Integer room)
        {
           // ... business logic
          return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber,
                                 @BAParam("user")String user, @BAParam("password") String pass)
        {
           // ... business logic
        }
}

There’s also a CompensationManager object that allows you to programatically put data into the activity that can be referenced by the @BAParam annotation:

{
        // injected field
        @CompensationManagement CompensationManager cm;

	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
               cm.put("reservationNumber", reservationNumber);

               return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber)
        {
           // ... business logic
        }
}

There’s a few more ways to define a compensation. You can have the method compensated by another different EJB method, Web Service, or even a plain POJO. I won’t get into further detail. You’ll have to read the documentation and take a look at the demo app that comes with the distribution.

Client interface

The client interface is very simple and similar to UserTransaction:

public abstract class UserBusinessActivity
{
    public static final int ATOMIC_OUTCOME = 0;
    public static final int MIXED_OUTCOME = 1;

    /**
     * Start a new business activity with atomic outcome.
     * If one is already associated with this thread
     * then the WrongStateException will be thrown. Upon success, this
     * operation associates the newly created transaction with the current
     * thread.
     */
    public abstract void begin()
        throws WrongStateException, SystemException;

    /**
     * Start a new BA with atomic outcome and the specified timeout as
     * its lifetime.
     * If one is already associated with this thread then the
     * WrongStateException will be thrown.
     */
    public abstract void begin(final int timeout)
        throws WrongStateException, SystemException;

    /**
     * The BA is normally terminated by the close method. This signals to
     * all registered participants that the BA has ended and no compensation
     * is required.
     */
    public abstract void close()
        throws TransactionRolledBackException, UnknownTransactionException, SystemException;

    /**
     * If the BA must undo its work then the cancel method is used. Any
     * participants that can compensate are forced to do so.
     */
    public abstract void cancel()
        throws UnknownTransactionException, SystemException;

    /**
     * If participants have registered for the BusinessAgreementWithComplete
     * protocol then they will be expecting the application to inform them
     * when all work intended for them has been sent (and responded to). The
     * complete method is used for this purpose.
     */
    public abstract void complete()
        throws UnknownTransactionException, SystemException;

    public abstract String transactionIdentifier();
}

Here’s an example of using the activity service:

UserBusinessActivity businessActivity = UserBusinessActivityFactory.userBusinessActivity();
businessActivity.begin();
try {
   // do some work
   businessActivity.close();
} catch (Exception ex) {
   businessActivity.cancel();
}

There is of course some initialization to do. I’ll leave that to the documentation, but overall its a very simple API. What I like about this way of doing compensations is that the client is decoupled from the knowledge of whether something should be compensated for, and how it is compensated. The knowledge of this is encapsulated in the services the client interacts with. Services automatically register themselves for the appropriate callbacks. User code does not have to perform commits or rollbacks. Very similar in ease of use to what we’re used to with JCA combined with JTA transactions.

I really think this stuff would be even more useful in plain web applications, not just coordinated remote web services. In my previous blog, Andy Oliver commented how Hibernate application transactions with FlushMode NEVER isn’t always a great solution for long running web apps that interact with your browser. This new framework could provide a very simple mechanism for registering compensatory callbacks so that browser interactions with a database don’t have to be held in memory.

In my next blog on this subject, I want to dive into some ideas I have for improving this framework. Until then, have fun.

Guaranteed Execution in jBPM

2 Comments

Was thinking a bit about jBPM today. One thought crossed my mind: How can you guarantee that a specific state transition happens in jBPM? We’ll talk about guaranteed state transition in this blog, but first of all, before we even think of jBPM, how could you guarantee that *any* event happens in a general application? There are few things you have to think about here:

  • You want to be guaranteed that the event is scheduled to be processed
  • You only want the event to be scheduled if your business logic succeeds
  • You want to be guaranteed that somebody processes the event

Being as stupid and slow as I am, took me a few minutes to realize that JMS provides guaranteed delivery of messages. This is obvious to many people, but let’s walk through what you would have to do in JBoss to have the guaranteed processing of an event.

First things first is to write the sender code. Let’s do this in an EJB 3.0 stateless session bean. I know this is basic stuff, but you may not be familiar with a) EJB 3.0 or b) the JBoss specifics:

@Stateless
public class BusinessLogicBean implements BusinessLogic {
   @Resource(mappedName="java:/JmsXA") ConnectionFactory factory;
   @Resource(mappedName="queue/mylogic") Destination destination;

   public void doSomething() {
      ... do some logic ...
      Connection con = factroy.createConnection();
      ... do all the JMS sugar ...
      messageProducer.setDeliverMode(DeliveryMode.PERSISTENT);
      messageProducer.send(message);
   }
}

The doSomething() method is a transactional unit of work. We want every piece of business logic to have succeeded when we deliver the message. In other words, we want the message delivered as part of a transaction. To use a transactionally aware sender, we injected the “java:/JmsXA” connection factory into our SLSB. We also set the delivery mode of the producer to be PERSISTENT. So, we both guaranteed that the message would only be sent if the business logic succeeded and that the message has been scheduled for processing. On to the server:

@MessageDriven(activationConfig= {
      ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
      ActivationConfigProperty(propertyName="destination", propertyValue="queue/mylogic"),
      ActivationConfigProperty(propertyName="DLQMaxResent", propertyValue="5")
})
public class MyMessageConsuomer implements MessageListener {
   public void onMessage(Message msg) {
      ... do the work ...
   }
}

Typical message driven bean in EJB 3.0. Since this bean is using the container to manage transactions and being invoked inside of a transaction, the receipt of the message will not be sent back to the JMS provider if the business logic is rolled back. So, if there is a system failure, or some other reason for abort, the message will be redelivered, thus guaranteeing its processing. The “DLQMaxResent” property is JBoss specific and tells the JMS adapter how many times the message should be resent before it is sent to a “dead letter queue” and put to death. There’s other configuration items around dead-letter queues. Go read our documentation for additional DLQ settings.

Guaranteed State Transitions in jBPM

Guaranteed state transitions with jbpm is all about using asynchronous continuations and the Enterprise Archive. In jBPM if you mark a node as asynch then jBPM will use its configured messaging system to transition to that state in another thread and transaction. If you have deployed jBPM through the Enterprise Archive, JMS is used to do the transition. Here’s example .jpdl

<process-definition>
   <start-state>
     <transition to='guarantee'/>
   </start-state>
   <state name='guarantee' asynch='true'>
     ...
   </state>
...
</process-definition>

So, starting a process instance of this definition will generate a JMS message that transitions to the ‘guarantee’ state. By default, jBPM is configured to use transactional connection factory, “java:/JmsXA”, describe earlier in this blog. So, when the start-state transitions, it will create a persistent JMS message and deliver it to the queue transactionally. Now, the ‘guarantee’ node will be triggered by an MDB that receives the message sent by the jBPM message layer. This MDB uses container managed transactions. This means that if there is a failure within the execution of the state, the message will be redelivered until the transaction completes successfully. This MDB is configured to use JBoss’s old EJB 2.1 container which does not use JCA message inflow. The default message redelivery count is 10. Chapter 5 in the JBoss AS documentation shows how you can define the max redelivery as well as dead letter queue configurations. You’ll need to open up the Enterprise Archive, jbpm-enterprise.ear, to get to the file, jbpm-enterprise.jar. This file contains the ejb-jar.xml and jboss.xml files you need to modify to change the jbpm configuration of the message driven bean.

The only thing missing with this JMS transitioning in jBPM is that the node receiving the transition does not have knowledge on whether the message was redelivered or not. Future versions might incorporate this knowledge. I have pinged the jBPM team and there is some discussion on the jbpm forum.

That’s about it! Yeah, I know a lot of this stuff is basic, hope I didn’t bore you too much. I just wanted to set down some foundation for other topics I want to discuss that may use these JMS and jBPM features.

Must I compensate for everything?

16 Comments

I spent a lot of time over the past few months with the JBoss ESB and jBPM teams. It was my first real hands-on experience with the orchestration of both local and remote “web” services. Usually, as a middleware developer you think in terms of milliseconds. How fast can I transmit information from one point to the next and back again? How can I optimize this query to run faster? The jBPM guys think about things very differently. For them, the processes they model could span minutes, hours, days and even weeks or months. Its a very different way of looking at things. For instance, what if you have a process that spans days and something goes wrong? How do you handle failure and abort conditions? You sure as hell can’t do long running activities within a JTA transaction. This would hold up things like database resources too long. No, what you really need is the ability to undo operations in abort situations.

In middleware land, undo is more commonly referred to as Compensating Transactions. What’s an example? Cancellation of an order is a common compensation. When a customer makes an order over the internet, the business process usually goes through a set of committed states before the product is delivered. Let’s take the ordering of a computer for instance:

  • Bill credit card
  • Pull parts from inventory
  • Assemble computer
  • Install software
  • QA
  • Ship

You don’t want to build the computer without billing the customer. Once parts are pulled from inventory, inventory counts must be decremented. No way this can be done in a traditional ACID transaction. Each state transaction must be its own transaction that is committed. If an order is canceled, there are a number of things that must be done. The buyer must have their credit card credited. The computer must also be disassembled and parts sent back to inventory.

Long running conversations aren’t just a property of a business process run inside something like jBPM. Web applications are a perfect example of a long running activity where you don’t want to hold up resources. The Hibernate guys like to handle these situations by holding database updates in memory and flushing them when the activity commits. They suggest the combination of optimistic concurrency and flush mode NEVER/MANUAL to do this. Flush mode NEVER holds all database updates within the Hibernate session until you invoke flush(). Optimistic concurrency ensures you that your database is in the state you want it to be in when you perform the flush. With this approach compensation is not needed at all, because nothing is committed to the database. The problem is that you might have a resource that can’t be managed by Hibernate or that has a high probability of failing optimistic concurrency checks. In that scenario, compensation is the only thing you can do.

So, that’s my explanation of what compensating transactions are. In my next blog I want to talk about how middleware interacts with compensating transactions and whether or not you need a special compensating transaction engine or business activity service to enable compensating transactions.

%d bloggers like this: