众所周知,您必须使用以下模式来更新 ATGForm-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());
}
}
理论上,任何FormHandler
从PurchaseProcessFormHandler继承的都已经实现了以下步骤 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 文档,以下方法实现了上述行为:
方法:之前设置
在提交修改此表单处理程序属性的表单时,在设置此表单上的任何 setX 方法之前调用。如有必要,在表单提交过程开始时创建事务,可选择获取本地锁以防止多个表单创建可能修改同一订单的事务。
- 步骤:1 & 2
方法:后集
在提交修改此表单处理程序属性的表单时,在设置此表单上的任何 setX 方法后调用。提交或回滚在 beforeSet 中创建的任何事务,并释放当时获得的任何锁。
- 步骤:3 & 4
例如,您只需处理以下程序即可更新订单:
同步将要用于的代码块
order updating
以避免线程并发。synchronized (getOrder()) { ... ... ... }
执行订单修改:
synchronized (getOrder()) { getOrder().setXXX(); getOrder().removeXXX(); }
更新订单(
updateOrder
将调用管道链):synchronized (getOrder()) { ... ... ... getOrderManager().updateOrder(order); }
这非常简单,除非您必须在以下任何情况下编辑订单:
- 不在 的层次结构中的表单处理程序或自定义表单处理程序
PurchaseProcessFormHandler
。 - 助手或工具类。
- 处理器
- ATG REST Web 服务
- &C
如果是这样,您将不得不在您的组件中实现事务模式。
问题!
- 是否有任何其他已知的模式可以使用而不是使用事务模式?
- 是否可以像 ATG 一样实现/覆盖 FormHandlers 中的
beforeSet
&方法afterSet
PurchaseProcessFormHandler
- 你知道其他方法吗?