我目前正在编写用于用户管理的Web服务。该项目涉及Oracle DB和XMPP聊天服务器。我正在使用Eclipselink,JPA和JTA进行事务管理。
在注册新用户时,我遇到了一个问题,而我似乎无法用我的JTA知识解决这个问题。
@Transactional(rollbackOn = XMPPException.class)
public User registerUser(User user) throws InvalidArgumentException, NullValueException, ConstraintViolationException, XMPPException {
if (user == null) {
throw new NullValueException(new ErrorBuilder(Error.USER_NULL));
}
if (user.getEmail() != null && !EmailUtils.isEmailValid(user.getEmail())) {
throw new InvalidArgumentException(new ErrorBuilder(Error.INVALID_EMAIL).withParams(user.getEmail()));
}
Character gender = getGenderOrDefault(user.getGender());
user.setGender(gender);
user.setRole(UserRole.USER.getChar());
em.persist(user);
//only add xmpp user if registration was successful (if transaction is not marked for rollback)
if (!em.getTransaction().getRollbackOnly()) { //throws Exception because I'm using JTA
xmppService.createUser(user);
}
return user;
}
问题是我需要在Oracle DB和XMPP服务器中创建新用户(使用他们的API)。这意味着如果两个单独的创建过程中的一个失败,我也需要回滚另一个。
但是,由于em.persist()不立即抛出异常,而是标记事务以进行回滚,因此继续执行方法并在XMPP服务器上创建用户。
我最初的想法是检查事务是否标记为回滚,但在使用JTA时似乎不能。
所以我的问题是:我应该怎么解决这个问题?我真的不想用2个单独的方法拆分它,如果XMPP失败,只需从Oracle DB中删除用户。