众所周知,您必须使用以下模式才能更新 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());
}
}
理论上,任何继承自 PurchaseProcessFormHandler 的 FormHandler
都已实现以下步骤 OOTB:
获取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()); }
创建新的交易:
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()); }
结束正在使用的事务:
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 }
释放用于事务的锁:
finally { ClientLockManager lockManager = getLocalLockManager(); lockManager.releaseWriteLock(profile.getRepositoryId(), Thread.currentThread(), true); }
根据 ATG 文档,以下方法实现上述行为:
方法: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
方法: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
例如您只需办理以下手续即可更新订单:
同步将用于
订单更新
的代码块,以避免线程并发。synchronized (getOrder()) { ... ... ... }
执行订单修改:
synchronized (getOrder()) { getOrder().setXXX(); getOrder().removeXXX(); }
更新订单(将调用
updateOrder
管道链):synchronized (getOrder()) { ... ... ... getOrderManager().updateOrder(order); }
这非常简单,除非您必须在以下任何情况下编辑订单:
- 不在
PurchaseProcessFormHandler
层次结构中的表单处理程序或自定义表单处理程序。 - 帮助程序或工具类。
- 处理器
- ATG REST 网络服务
- &c
如果是这样,您将必须在组件中实现事务模式。
问题!
- 除了事务模式之外,还有其他已知的模式可以使用吗?
- 是否可以像 ATG 在
PurchaseProcessFormHandler
中那样实现/覆盖 FormHandler 中的beforeSet
和afterSet
方法 - 您还知道其他方法吗?
最佳答案
您上面概述的一系列步骤是更新订单的规定步骤系列。
请随意以任何您认为有用的方式将其分解出来。只需确保当您更新订单时,您或您继承的代码已执行必要的步骤。
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/