java - ATG:更新订单模式

标签 java jakarta-ee atg oracle-commerce

众所周知,您必须使用以下模式才能更新 ATG Form-Handlers 中不继承自 PurchaseProcessFormHanlder 的订单:

boolean acquireLock = false;
ClientLockManager lockManager = getLocalLockManager();

try {
    acquireLock = !lockManager.hasWriteLock(profile.getRepositoryId(), Thread.currentThread());
    if (acquireLock) {
        lockManager.acquireWriteLock(profile.getRepositoryId(), Thread.currentThread());
    }

    boolean shouldRollback = false;

    TransactionDemarcation transactionDemarcation = new TransactionDemarcation();
    TransactionManager transactionManager = getTransactionManager();

    transactionDemarcation.begin(transactionManager, TransactionDemarcation.REQUIRED);

    try {
        synchronized (getOrder()) {
            ...
            ...
            ...
        }
    } catch (final Exception ex) {
        shouldRollback = true;
        vlogError(ce, "There has been an exception during processing of order: {0}", getOrder().getId());
    } finally { 
        try {
            transactionDemarcation.end(shouldRollback);
        } catch (final TransactionDemarcationException tde) {
            vlogError(tde, "TransactionDemarcationException during finally: {0}", tde.getMessage());
        } finally {
            vlogDebug("Ending Transaction for orderId: {0}", order.getId());
        }
    }
} catch (final DeadlockException de) {
    vlogError(de, "There has been an exception during processing of order: {0}", order.getId());
} catch (final TransactionDemarcationException tde) {
    vlogError(tde, "There has been an exception during processing of order: {0}", order.getId());
} finally {
    try {
        if (acquireLock) {
            lockManager.releaseWriteLock(getOrder().getProfileId(), Thread.currentThread(), true);
        }
    } catch (final Throwable th) {
        vlogError(th, "There has been an error during release of write lock: {0}", th.getMessage());
    }
}

理论上,任何继承自 PurchaseProcessFormHandlerFormHandler 都已实现以下步骤 OOTB:

  1. 获取LocalLockManager以避免并发线程修改相同的顺序:

    try {
        acquireLock = !lockManager.hasWriteLock(profile.getRepositoryId(), Thread.currentThread());
        if (acquireLock) {
            lockManager.acquireWriteLock(profile.getRepositoryId(), Thread.currentThread());
        }
    } catch (final DeadlockException de) {
        vlogError(de, "There has been an exception during processing of order: {0}", order.getId());
    }
    
  2. 创建新的交易:

    try {
        TransactionDemarcation transactionDemarcation = new TransactionDemarcation();
        TransactionManager transactionManager = getTransactionManager();
    
        transactionDemarcation.begin(transactionManager, TransactionDemarcation.REQUIRED);
    } catch (final TransactionDemarcationException tde) {
        vlogError(tde, "There has been an exception during processing of order: {0}", order.getId());
    }
    
  3. 结束正在使用的事务:

    try {
        TransactionManager transactionManager = getTransactionManager();
        Transaction transaction = transactionManager.getTransaction();
    
        // If transaction is elegible for commiting: 
        transactionManager.commit();
        transaction.commit();
    
        // otherwise
        transactionManager.rollback();
        transaction.rollback();
    } catch (final Exception ex) {
        error = true;
        vlogError(ex, "There has been an exception during processing of order: {0}", order.getId());
    } finally {
        // handle the error
    }
    
  4. 释放用于事务的锁:

    finally {
        ClientLockManager lockManager = getLocalLockManager();
        lockManager.releaseWriteLock(profile.getRepositoryId(), Thread.currentThread(), true);
    }
    

根据 ATG 文档,以下方法实现上述行为:

  1. 方法:beforeSet

    Called before any setX methods on this form are set when a form that modifies properties of this form handler is submitted. Creates a transaction if necessary at the beginning of the form submission process, optionally obtaining a local lock to prevent multiple forms from creating transactions that may modify the same order.

    • 步骤:1 和 2
  2. 方法:afterSet

    Called after any setX methods on this form are set when a form that modifies properties of this form handler is submitted. Commits or rolls back any transaction created in beforeSet, and releases any lock that was acquired at the time.

    • 步骤:3 和 4

例如您只需办理以下手续即可更新订单:

  1. 同步将用于订单更新的代码块,以避免线程并发。

    synchronized (getOrder()) {
        ...
        ...
        ...
    }
    
  2. 执行订单修改:

    synchronized (getOrder()) {
        getOrder().setXXX();
        getOrder().removeXXX();
    }
    
  3. 更新订单(将调用updateOrder管道链):

    synchronized (getOrder()) {
        ...
        ...
        ...
        getOrderManager().updateOrder(order);
    }
    

这非常简单,除非您必须在以下任何情况下编辑订单:

  • 不在 PurchaseProcessFormHandler 层次结构中的表单处理程序或自定义表单处理程序。
  • 帮助程序或工具类。
  • 处理器
  • ATG REST 网络服务
  • &c

如果是这样,您将必须在组件中实现事务模式

问题!

  • 除了事务模式之外,还有其他已知的模式可以使用吗?
  • 是否可以像 ATG 在 PurchaseProcessFormHandler 中那样实现/覆盖 FormHandler 中的 beforeSetafterSet 方法
  • 您还知道其他方法吗?

最佳答案

您上面概述的一系列步骤是更新订单的规定步骤系列。

请随意以任何您认为有用的方式将其分解出来。只需确保当您更新订单时,您或您继承的代码已执行必要的步骤。

ATG 进行类似因式分解的一种常见方法是,对于给定方法,例如 X(...),您将拥有 preX(...)doX(...)postX(...) 方法。您可以使用 preX()postX() 方法中的所有样板代码创建一个抽象类,甚至可以声明为最终类,并将 doX() 声明为抽象类。然后,您的组件将从抽象类继承,并且必须实现 doX() 方法。您可能还需要显式处理异常。

本质上,这就是标准表单处理程序所做的事情(以不同的名称)。

例如;

public final void X(...) {
  preX(...); // call the pre method

  try {
    doX(...); // call the do method
  } catch (XException xe) {
    // handle error
  }

  postX(...); // call the post method
}

protected final void preX(...) {
  // do everything you need to do before your customer code
}

protected final void postX(...) {
  // do everything you need to do after your customer code
}

protected abstract void doX(...) throws XException;

您可以做的另一件事是定义一个包含所有样板代码的注释,而不是从抽象类继承。

您可以用类似的方式做的第三件事,但很难硬塞进 ATG 代码中,可能是使用第三方框架定义一个方面或方法调用拦截器。

但是,再次强调,无论您做什么、如何做,只要确保遵循所有步骤即可。

关于java - ATG:更新订单模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37580167/

相关文章:

java - GSON 正确序列化枚举,但将其反序列化为字符串

java - 在 g.fillRect() 中使用负高度

java - 在带有 JFrame 表单的 Netbeans derby 中使用带有 WHERE 子句的 SELECT 语句

java - org.jboss.msc.service.StartException 服务 jboss.web.deployment.default-host./: Failed to start service

java - 创建带有字母边的加权矩阵

java - addShutDownHook 的内存泄漏

java - 未知实体bean类: null,请验证该类是否已使用@Entity注释进行标记

jboss - 是否可以对 ATG 类进行热交换

mysql - ATG 连接线程

java - ATG 核心 - EJB 关系