并发调用LayoutLocalService.addLayout抛出StaleObjectStateException问题求助
Liferay DXP并行导入布局时StaleObjectStateException问题求助
更新说明
Liferay工单LPS-82954已受理,开发中的解决方案可参考该工单。
问题场景
我在基于Spring构建的Liferay Portlet中做并行导入Liferay布局的操作时,在Liferay DXP环境调用addLayout接口会抛出StaleObjectStateException。这个接口的实现逻辑在LayoutLocalServiceImpl.java里,异常是在接口内部更新对应LayoutSet(也就是更新刚添加布局的Group的PageCount)时触发的,单线程执行完全没有这个问题。
已尝试的解决动作
我已经试过两种方式,但都没有改善:
- 对
addLayout的调用加了同步锁; - 给调用方法添加了
@Transactional(propagation = Propagation.REQUIRES_NEW)注解。
当前排查发现
我发现LayoutSetLocalService.updatePageCount存在一个Bug:它没有返回更新后的LayoutSet,导致Liferay 7/DXP引入的mvcc Version没有递增,但我推测这个Bug应该不影响当前的问题场景,相关代码在LayoutSetLocalServiceImpl.java中。
想请教的问题
想问问大家:
- 有没有办法解决这个并行导入时的异常问题?
- 这是不是乐观锁机制导致的、必须接受的情况?
- 是不是我在创建线程的时候遗漏了Hibernate会话配置这类关键步骤?
相关代码片段
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; }
测试项目
测试项目的代码仓库在github上的andrebiegel/liferay-layout-issue。
内容的提问来源于stack exchange,提问作者André
相关产品推荐
相关产品推荐

