我有一个服务对象的接口,如下所示(为简洁起见进行了简化):
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
单个实现,并作为 Spring bean 连接起来。我们项目的 UI 部分以及处理 Ajax 请求的代码使用它来创建和修改Item
我们的数据存储中的对象。
在底层,每个方法在被调用时都会发出一系列事件。其他模块接收事件以执行诸如保持 Lucene 索引最新或向管理员发送消息以让他们知道某些内容已更改之类的操作。每个方法调用在 Spring 中构成一个事务(使用org.springframework.orm.hibernate3.HibernateTransactionManager
and org.springframework.transaction.interceptor.TransactionProxyFactoryBean
).
最近有需要compose在单个事务中一起调用多个方法。有时有多个服务。例如,我们可能想做类似的事情:
*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*
我们通过创建另一个服务来实现此目的,该服务允许您在父服务中的单个方法中编写来自服务的调用。我们称之为ComposingService
. ComposingService
与所有其他事务一样,也由 Spring 管理,并且由于事务是可重入的,因此这一切都应该有效。
然而,存在一个问题:如果事务内的任何这些操作失败,就会导致事务回滚我们不想发送任何事件.
按照目前的情况,如果交易中途失败,一半的事件将由ItemService
在事务回滚之前,这意味着某些模块将收到一堆尚未发生的事件的事件。
我们正在尝试找到某种方法来解决这个问题,但我们一直想不出任何优雅的方法。到目前为止,我们想出的最好的办法是这样的(而且很丑):
public interface ItemService {
public Item getItemById(String itemId, int version);
public void create(Item item, User user, List<Event> events);
public void update(Item item, User user, List<Event> events);
public void delete(Item item, User user, List<Event> events);
}
在此修改后的 ItemService 中,事件不是立即发送,而是添加到作为参数传入的事件列表中。该列表由以下人员维护ComposingService
,事件由以下方式发送ComposingService
一旦所有的电话ItemService
且其他服务已成功退出。
显然,问题在于我们以一种丑陋的方式更改了 ItemService 上的契约。调用类,即使它们是服务,也不应该担心管理事件。但我一直无法想出解决这个问题的方法,因此这个问题。
这看起来像是以前可能已经解决的问题。有人遇到过类似的问题吗?如果有,你是如何解决的?