【问题标题】:Liferay model listener - on after update handler loopLiferay 模型侦听器 - 在更新处理程序循环后开启
【发布时间】:2016-06-17 09:38:43
【问题描述】:

我在 Liferay 6.2 GA6 中为 DLFileEntry 创建了自定义模型侦听器。但是,即使没有对 DLFileEntry 进行任何更改,也会重复调用 onAfterUpdate 方法。

让我描述一下情况:

  1. 通过 Liferay 中的内容管理更改文件条目
  2. onAfterUpdate 方法被触发(这没问题)
  3. onAfterUpdate 方法被一次又一次触发 - 即使没有对此条目进行更新

当(意外)更新事件发生时,我已经转储了堆栈跟踪。看起来onAfterUpdate是由incrementViewCounter(..)方法触发的,它是由BufferedIncrementRunnable类触发的

java.lang.Exception: Stack trace
        at java.lang.Thread.dumpStack(Thread.java:1365)
        at eu.package.hook.model.listener.DLFileEntryModelListener.onAfterUpdate(DLFileEntryModelListener.java:63)
        at eu.package.hook.model.listener.DLFileEntryModelListener.onAfterUpdate(DLFileEntryModelListener.java:32)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:67)
        at com.sun.proxy.$Proxy865.onAfterUpdate(Unknown Source)
        at com.liferay.portal.service.persistence.impl.BasePersistenceImpl.update(BasePersistenceImpl.java:340)
        at com.liferay.portlet.documentlibrary.service.impl.DLFileEntryLocalServiceImpl.incrementViewCounter(DLFileEntryLocalServiceImpl.java:1450)
        at sun.reflect.GeneratedMethodAccessor2034.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:115)
        at com.liferay.portal.spring.transaction.DefaultTransactionExecutor.execute(DefaultTransactionExecutor.java:62)
        at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:51)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111)
        at com.liferay.portal.increment.BufferedIncreasableEntry.proceed(BufferedIncreasableEntry.java:48)
        at com.liferay.portal.increment.BufferedIncrementRunnable.run(BufferedIncrementRunnable.java:65)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

我已阅读portal.properties docs page 中有关缓冲区增量的文档。不建议禁用此功能。

我还考虑过检查模型侦听器方法中是否对 DLFileEntry 对象进行了任何相关更改。我只是想检查一下,当onAfterUpdate方法被incrementViewCounter方法触发时,是否有任何配置可以绕过onAfterUpdate方法。

感谢任何帮助。

更新:

更新后开启方式:

private void createMessage(DLFileEntry model, String create) {
    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
    jsonObject.put("action", create);
    jsonObject.put("id", model.getFileEntryId());
    MessageBusUtil.sendMessage(SUPIN_MESSAGE_LISTENER_DESTINATION, jsonObject);
}


@Override
public void onAfterUpdate(DLFileEntry model) throws ModelListenerException {
    if (LOG.isTraceEnabled()) {
        URL[] urls = ((URLClassLoader) (Thread.currentThread().getContextClassLoader())).getURLs();
        LOG.trace("Current thread classpath is: " + StringUtils.join(urls, ","));
    }
    LogMF.info(LOG, "File entry on update event - id {0}" , new Object[]{model.getFileEntryId()});
    Thread.dumpStack();
    createMessage(model, UPDATE);

}

这里是消息监听器(消息总线),它执行更新后的操作:

private void createOrUpdate(DLFileEntry model, String createOrUpdate) {
    try {
        initPermissionChecker(model);

        LOG.info("Document " + model.getFileEntryId() + " " + createOrUpdate + "d in Liferay. Creating entry in Safe.");
        long documentInSafe;
        if (UPDATE.equalsIgnoreCase(createOrUpdate)) {
            documentInSafe = (long) model.getExpandoBridge().getAttribute(EXPANDO_SAFE_DOCUMENT_ID);
            if (documentInSafe > 0) {
                safeClient.updateDocumentInSafe(model);
            } else {
                documentInSafe = safeClient.createDocumentInSafe(model);
            }
        } else {
            documentInSafe = safeClient.createDocumentInSafe(model);
        }
        LOG.info("Document " + createOrUpdate +"d successfully with id " + documentInSafe);
        saveSafeIDToExpando(model, documentInSafe);
    } catch (Exception e) {
        LOG.error("Unable to safe ID of document in Safe", e);
    }
}

private void saveSafeIDToExpando(DLFileEntry model, long documentInSafe) throws SystemException {
    try {
        ExpandoTable table = ExpandoTableLocalServiceUtil.getDefaultTable(model.getCompanyId(), DLFileEntry.class.getName());
        ExpandoColumn column = ExpandoColumnLocalServiceUtil.getColumn(table.getTableId(), EXPANDO_SAFE_DOCUMENT_ID);
        ExpandoValueLocalServiceUtil.addValue(model.getCompanyId(), table.getTableId(), column.getColumnId(), model.getClassPK(), String.valueOf(documentInSafe));
        LOG.info("ID of document in Safe updated in expando attribute");
    } catch (PortalException e) {
        LOG.error("Unable to save Safe document ID in expando." , e);
        ;
    }
}

private void initPermissionChecker(DLFileEntry model) throws Exception {
    User safeAdminUser = UserLocalServiceUtil.getUserByScreenName(model.getCompanyId(), SAFE_ADMIN_SCREEN_NAME);
    PermissionChecker permissionChecher = PermissionCheckerFactoryUtil.create(safeAdminUser);
    PermissionThreadLocal.setPermissionChecker(permissionChecher);
    PrincipalThreadLocal.setName(safeAdminUser.getUserId());
    CompanyThreadLocal.setCompanyId(model.getCompanyId());
    LOG.info("Permission checker successfully initialized.");
}

【问题讨论】:

  • 可以看自定义onAfterUpdate方法的代码吗?
  • @DanieleBaggio - 感谢您的回复。我已将自定义代码添加到我的帖子中。我怀疑 ExpandoValueService 会反复触发 onAfterUpdate,但事实并非如此(我已经测试过它有/没有它)。

标签: liferay listener


【解决方案1】:

我建议这样做,但我不确定它是否能解决您的问题。

我已经更改了您自己的 onAfterUpdate 方法的主体。

使用 TransactionCommitCallbackRegistryUtil 可以将模型更新请求与后续 createMessage 逻辑分离。

public void onAfterUpdate(DLFileEntry model) throws ModelListenerException {

    TransactionCommitCallbackRegistryUtil.registerCallback(new Callable() {

         @Override
         public Void call() throws Exception {
              createMessage(model, UPDATE);
    }
}

【讨论】:

  • 感谢您的建议,但这没有帮助。 onAfterUpdate 被一次又一次触发:(
猜你喜欢
  • 2016-04-22
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 2021-01-11
  • 2012-06-21
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
相关资源
最近更新 更多