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.