アップデート
Liferay チケットが承認されました。開発中の解決策: https://issues.liferay.com/browse/LPS-82954
状況
私のコンテキストは、liferay ポートレットを介した liferay レイアウトの並行インポートです。春で構築します。Liferay dxpで実行しているとき; レイアウトを追加するための API 呼び出しは、StaleObjectStateException をスローします。( https://github.com/liferay/liferay-portal/blob/d969e0e839db9ea64267f7bff0a76be93cd26fa0/portal-impl/src/com/liferay/portal/service/impl/LayoutLocalServiceImpl.java )
この例外は、対応する LayoutSet で API が内部的に更新を行うときに発生します (レイアウトが追加されたそのグループの PageCount を少し前に更新します)。
これは、シングル スレッド実行では発生しません。
行動
- まず、その通話を同期しました..より良い結果はありません
- その間、トランザクション自体が同期実行ブロック内にない可能性があるため、スレッドを同期するだけでは役に立たないということを読みました。したがって、トランザクションの注釈も追加しました。.. より良い結果なし
これまでのところ、次の洞察を得ました。
LayoutSetLocalService.updatePageCount() にバグがあります: 更新された LayoutSet が返されません.. したがって、(Liferay 7/DXP が導入された場合) LayoutSet の mvcc バージョンはインクリメントされません。..しかし、これが私の状況に影響を与えることはありません)。
それに取り組む機会があるかどうか、だれかが私にヒントを与えることができますか?
- それとも、これは楽観的ロックの結果であり、私はそれと一緒に暮らす必要がありますか?
- スレッドを作成するときにパズルを見逃しましたか? たぶんいくつかの奇妙な..私の休止状態のセッションを構成する...こと?
コードの抜粋
-> 利用可能なテスト プロジェクト: https://github.com/andrebiegel/liferay-layout-issue.git
private static final Object layoutCreationLock = new Object();
synchronized (layoutCreationLock) {
newLayout = addLayoutApiCall(pageContext, serviceContext, typeSettings, friendlyURLMap);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Layout addLayoutApiCall(IPageContext pageContext, ServiceContext serviceContext, String typeSettings,
Map<Locale, String> friendlyURLMap) throws PortalException {
Layout newLayout;
newLayout = LayoutLocalServiceUtil.addLayout( pageContext.getProjectConfiguration().getUserId(), pageContext.getProjectConfiguration()
.getSiteId(), pageContext.isPrivatePage(), pageContext.getParentLayoutId(), pageContext
.getNamesMap(), pageContext.getTitleMap(), pageContext.getDescriptionMap(), pageContext
.getKeywordsMap(), pageContext.getRobotsMap(), pageContext.getPageType(), typeSettings,
pageContext.isHiddenPage(), friendlyURLMap, serviceContext );
return newLayout;
}