众所周知,您必须使用以下模式才能更新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
在提交修改此表单处理程序属性的表单时,设置此表单上的任何setX方法之前调用。如有必要,在表单提交过程开始时创建事务,可选择获取本地锁定以防止多个表单创建可能修改相同订单的事务。
方法:afterSet
在提交修改此表单处理程序属性的表单时,设置此表单上的任何setX方法后调用。提交或回滚在beforeSet中创建的任何事务,并释放当时获取的任何锁。
例如,您只需处理以下程序即可更新订单:
Syncronize 将用于order updating
的代码块,以避免线程并发。
synchronized (getOrder()) {
...
...
...
}
执行订单修改:
synchronized (getOrder()) {
getOrder().setXXX();
getOrder().removeXXX();
}
更新订单(将调用updateOrder
管道链):
synchronized (getOrder()) {
...
...
...
getOrderManager().updateOrder(order);
}
这非常简单,除非您必须在以下任何情况下编辑订单:
PurchaseProcessFormHandler
层次结构中的表单处理程序或自定义表单处理程序。如果是这样,您必须在组件中实施交易模式。
beforeSet
& FormHandlers中的afterSet
方法与ATG在PurchaseProcessFormHandler
答案 0 :(得分:0)
您在上面列出的一系列步骤是更新订单的规定系列步骤。
随意以任何有用的方式将其分解出来。只需确保在更新订单时,您或您继承的代码已执行必要的步骤。
ATG执行类似因子分析的一种常见方法是针对给定方法,例如X(...)
,您将拥有preX(...)
,doX(...)
和postX(...)
方法。您可以使用preX()
和postX()
方法中的所有样板代码创建一个抽象类,甚至可以声明为final,并将doX()
声明为abstract。然后,您的组件将从抽象类继承,并且必须实现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代码中窃取,可能是使用第三方框架定义方面或方法调用拦截器。
然而,无论你做什么,无论你做什么,只要确保你遵循所有步骤。