【问题标题】:What is the CDI equivalent of EJB's SessionSynchronization#afterCompletion method?EJB 的 SessionSynchronization#afterCompletion 方法的 CDI 等效项是什么?
【发布时间】:2022-01-23 11:45:33
【问题描述】:

我已阅读 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 jakarta-ee ejb cdi jta


    【解决方案1】:

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

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

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

    我能想到的一些解决方法,都没有解决一致性问题:

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

    【讨论】:

    • 我的目标是检测不一致的状态,而不是阻止它们:execute() 方法在事务期间执行并创建具有占位符名称的文件 ("new_FILENAME" ),而 confirm()undo() 方法只是删除文件或重命名它(如果它们失败,我可以看到哪些文件仍然具有占位符名称)。这真的没什么太严重的,我什至对小的不一致状态时间窗口都很好。对于更严重的用例,我当然会使用其他东西(比如 txfs?),但现在你的 Synchronization 解决方案成功了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2012-05-05
    相关资源
    最近更新 更多