在ModelListener

时间:2015-12-10 09:47:38

标签: liferay liferay-6

我根据用户使用的结构链接一个类别。例如:我的结构是" A"那么使用这种结构创建的任何内容都应该具有类别为" A"。

我已经在BaseModelListener模型上创建了一个扩展JournalArticle的侦听器。我重写onBeforeUpdate()看起来像:

@Override
public void onBeforeUpdate(JournalArticle aModel) throws ModelListenerException {
    try {
        long[] assetCategoryIds = refactorCategories(anArticle); // this reads the structure key and updates the list of category to the correct one.
        String[] assetTagNames = getTags(anArticle); 
        long[] assetEntryLinkIds = getEntryLinkIds(anArticle);
        JournalArticleLocalServiceUtil.updateAsset(anArticle.getUserId(), anArticle, assetCategoryIds, assetTagNames, assetEntryLinkIds);
    } catch (PortalException |SystemException ex) {
        throw new ModelListenerException("Cannot update the categories for articleId" + anArticle.getArticleId(), ex);
    }
}

我使用一组业务规则更正了categoryIds

以下是两种可能的情况:

  1. 没有分配类别:

    • 在这种情况下,上面的onBeforeUpdate()就像一个魅力,并且分配了正确的类别。
  2. 如果用户在调用之前分配了一个类别(可能是错误的类别):

    • 在这种情况下,调用onBeforeUpdate()实现并且我能够看到更新的资产(使用调试验证),但是当完成整个过程时,Web内容不会反映正确的类别。
  3. 我的理解:       调用updateAsset时,它会更改类别。但是当Hibernate保存内容时,它会保存用户选择的类别。这对我来说似乎有点奇怪。

    所以我希望检查是否有可能使用的解决方案或API。

    此外,我尝试了onAfterCreate()onAfterUpdate()onBeforeCreate(),但没有运气。

    我相信我可以挂钩JournalArticleService但我希望尽可能使用听众来做这件事。

    根据Tobias建议更新了代码:

    @Override
    public void onBeforeUpdate(JournalArticle aModel) throws ModelListenerException {
        ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();
         try {
            long[] assetCategoryIds = refactorCategories(anArticle); // this reads the structure key and updates the list of category to the correct one.
            if (serviceContext != null) {
                serviceContext.setAssetCategoryIds(assetCategoryIds);
            }
        } catch (PortalException |SystemException ex) {
            throw new ModelListenerException("Cannot update the categories for articleId" + anArticle.getArticleId(), ex);
        }
    }
    

2 个答案:

答案 0 :(得分:1)

请参阅JournalArticleLocalServiceImpl.addArticle() resp。 updateArticle()

  journalArticlePersistence.update(article);

  ...

  updateAsset(userId, article, serviceContext.getAssetCategoryIds(),
    serviceContext.getAssetTagNames(),
    serviceContext.getAssetLinkEntryIds());

第一行journalArticlePersistence.update(article)将调用您的侦听器,而updateAsset将保存用户提供的类别。在给你的听众打电话之后。

您可以获取当前服务上下文并从侦听器内部进行更改:

ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();
if (serviceContext != null) {
  serviceContext.setAssetCategoryIds(assetCategoryIds);
}

答案 1 :(得分:1)

我建议创建一个hook插件并使用服务包装器来扩展JournalArticleLocalService。我找到一个更适合任务的服务钩子。根据Liferay认证计划,通过服务挂钩执行此操作也是首选方法。

一般来说:

  • 我使用模型侦听器在持久化之前更新文章属性(例如自定义URL标题)。
  • 我使用服务挂钩来更新相关的资产条目(例如,类别和标签)。

示例扩展服务:

public class MyJournalArticleLocalService extends JournalArticleLocalServiceWrapper {

    @Override
    public JournalArticle addArticle(..., ServiceContext serviceContext) throws PortalException, SystemException {

        // set the right category in the service context, as the service context 
        // that the original service will work with can be modified here
        serviceContext.setAssetCategoryIds(refactorCategories(...));

        // delegate to the original implementation
        return super.addArticle(..., serviceContext);
    }

    @Override
    public JournalArticle updateArticle(..., , ServiceContext serviceContext) throws PortalException, SystemException {

        // set the right category in the service context, as the service context 
        // that the original service will work with can be modified here
        serviceContext.setAssetCategoryIds(refactorCategories(...));

        // delegate to the original implementation
        return super.updateArticle(..., serviceContext);
    }
}

使用服务挂钩,您可以在 Liferay完成持久化文章并创建/更新相关资产条目之后或之前更新类别

您可以在liferay-hook.xml描述符中注册服务挂钩:

<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd">

<hook>
    <service>
        <service-type>com.liferay.portlet.journal.service.JournalArticleLocalService</service-type>
        <service-impl>com.test.MyJournalArticleLocalService</service-impl>
    </service>
</hook>