I have an interface for a Service object that looks something like the following (simplified for brevity):
public interface ItemService {
public Item getItemById(String itemId, int version);
public void create(Item item, User user);
public void update(Item item, User user);
public void delete(Item item, User user);
}
ItemService a single implementation, and is wired up as a Spring bean. It gets used by the UI portion of our project, and by the code that handles Ajax requests, to create and modify Item objects in our data store.
Under the hood each method sends out a series of Events when it gets called. The Events are received by other modules to do things like keep Lucene indexes up to date, or to send messages to administrators to let them know something has changed. Each method call constitutes a single transaction in Spring (using org.springframework.orm.hibernate3.HibernateTransactionManager and org.springframework.transaction.interceptor.TransactionProxyFactoryBean).
Recently there has been a need to compose a number of method calls together in a single transaction. Sometimes with more than one Service. For example, we might want to do something like:
*Begin transaction*
Get Items created by User Bill using ItemService
for each Item in Items
Update field on Item
Link Item to User Bill with LinkService
Update Item using ItemService
*Finish transaction*
We've done this by creating another Service which allows you to compose calls from Services in a single method in the parent service. Lets call it ComposingService. ComposingService, as with all the others, is also managed by Spring, and as transactions are reentrant, this should all work..
However, there is a problem: if any of those operations within the transaction fail, causing the transaction to