Web services 服务@事务异常转换

Web services 服务@事务异常转换,web-services,cxf,aop,spring-transactions,Web Services,Cxf,Aop,Spring Transactions,我有一个web服务,其操作如下 public Result checkout(String id) throws LockException; 实施方式如下: @Transactional public Result checkout(String id) throws LockException { someDao.acquireLock(id); // ConstraintViolationException might be thrown on commit Data d

我有一个web服务,其操作如下

public Result checkout(String id) throws LockException;
实施方式如下:

@Transactional
public Result checkout(String id) throws LockException {
    someDao.acquireLock(id); // ConstraintViolationException might be thrown on commit
    Data data = otherDao.find(id);
    return convert(data);
}
我的问题是锁定只能在事务提交时失败,而事务提交发生在我的服务方法之外,因此我没有机会将
ConstraintViolationException
转换为我的自定义
LockException

选择1 建议的一个选项是将服务委托给另一个@Transactional方法。例如

public Result checkout(String id) throws LockException {
    try {
        return someInternalService.checkout(id);
    }
    catch (ConstraintViolationException ex) {
        throw new LockException();
    }
}

...

public class SomeInternalService {
    @Transactional
    public Result checkout(String id) {
        someDao.acquireLock(id);
        Data data = otherDao.find(id);
        return convert(data);
    }
}
我的问题是:

  • 对于外部服务尚未使用的内部服务,没有合理的名称,因为它们基本上在做相同的事情。这似乎是一个糟糕设计的指标
  • 如果我想在另一个地方重用某个InternalService.checkout,那么这个契约是错误的,因为无论使用它的是什么,都会得到一个ConstraintViolationException
选择2 我想也许可以使用AOP为翻译异常的服务提供建议。这对我来说似乎是错误的,因为
checkout
需要声明它抛出
LockException
供客户端使用,但实际的服务永远不会抛出它,而是由通知抛出。没有什么可以阻止将来有人从界面中删除
抛出锁异常,因为它似乎不正确

而且,这种方法更难测试。如果不创建spring上下文并在测试期间使用AOP,我无法编写JUnit测试来验证抛出的异常

选择3 在
签出中使用手动事务管理
?我真的不喜欢这样,因为应用程序中的所有其他内容都使用声明式样式



有人知道处理这种情况的正确方法吗?

没有正确的方法

您还有几个选择:

  • 使DAO具有事务性—这不是很好,但可以工作
  • 创建一个包装服务(称为Facade),其工作是围绕您提到的事务性服务进行异常处理/包装,这是一个明确的关注点分离,可以与真正的低级服务共享方法名称