EJB 的 SessionSynchronization#afterCompletion 方法的 CDI 等价物是什么?

What is the CDI equivalent of EJB's SessionSynchronization#afterCompletion method?

我阅读了 CDI 2.0 规范 (JSR 365) 并发现了 @Observes(during=AFTER_SUCCESS) 注释的存在,但它实际上需要定义一个自定义事件才能工作。

这是我得到的:

//simple """transactional""" file system manager using command pattern  

@Transactional(value = Transactional.TxType.REQUIRED)
@TransactionScoped
@Stateful
public class TransactionalFileSystemManager implements SessionSynchronization {
    private final Deque<Command> commands = new ArrayDeque<>();

    public void createFile(InputStream content, Path path, String name) throws IOException {
        CreateFile command = CreateFile.execute(content, path, name);
        commands.addLast(command);
    }

    public void deleteFile(Path path) throws IOException {
        DeleteFile command = DeleteFile.execute(path);
        commands.addLast(command);
    }

    private void commit() throws IOException{
        for(Command c : commands){
            c.confirm();
        }
    }

    private void rollback() throws IOException{
        Iterator<Command> it = commands.descendingIterator();
        while (it.hasNext()) {
            Command c = it.next();
            c.undo();
        }
    }

    @Override
    public void afterBegin() throws EJBException{

    }

    @Override
    public void beforeCompletion() throws EJBException{

    }

    @Override
    public void afterCompletion(boolean commitSucceeded) throws EJBException{
        if(commitSucceeded){
            try {
                commit();
            } catch (IOException e) {
                throw new EJBException(e);
            }
        }
        else {
            try {
                rollback();
            } catch (IOException e) {
                throw new EJBException(e);
            }
        }
    }
}

但是,我想采用仅 CDI 的解决方案,因此我需要删除所有与 EJB 相关的内容(包括 SessionSynchronization 接口)。我怎样才能使用 CDI 获得相同的结果?

首先是事实:本主题的权威来源是 Java 事务 API (JTA) 规范。网上一搜,得到了this.

然后是坏消息:为了真正参与 JTA 事务,您要么必须根据 Java 连接器体系结构 (JCA) 规范实施连接器,要么根据 XAResource JTA。从来没有做过,恐怕两者都会很难。不过,如果您进行搜索,您可能会找到文件系统连接器的现有实现。

您上面的代码永远不会完成真正的两阶段提交,因为如果您的代码失败,事务已经提交,因此应用程序状态不一致。或者,有一小段时间 window 当实际事务提交但文件系统更改尚未执行时,状态再次不一致。

一些解决方法我能想到,none其中解决了一致性问题:

  • 将文件系统命令保存在数据库中。这确保它们以事务方式排队。计划的作业唤醒并实际尝试执行排队的 FS 命令。
  • 注册一个 Synchronization with the current Transaction,从那里触发一个适当的事件。您的 TransactionalFileSystemManager 观察到此事件,我猜不需要 during 属性。