在工作流 Alfresco 上集成小程序

Integrate applet on workflow Alfresco

问题: 我有一个在 PDF 上制作 "changes" 的小程序,之后我必须将更改保存到存储库中的相应文件。如何将此小程序集成到工作流中?有任何提示或文档可供阅读吗?

我想在一个任务表单中(在一个任务编辑页面中),用一个带有按钮的新组件来调用小程序,但这是个好主意吗?和作品?因为我希望当此人按下接受按钮时,调用小程序,只有在进行更改时,任务才会完成。但是怎么办?

我们通过在 iframe 中打开第 3 方应用程序(小程序)进行了类似的集成。 入口点是一个带有自定义客户端 java 脚本的自定义文档库操作,用于打开 iframe 并将参数传递给它,但我想如果你想让它从表单按钮弹出,你可以为它。

第三层应用程序然后使用我们编写的自定义 alfresco 网络脚本与 alfresco 通信(用于保存您的 pdf)。

=>或者,如果您有小程序 java 代码,您可以将其移动到露天 java 网络脚本。这将大大简化架构。

正如我在 中提到的,它是可行的,但我不赞成你这样做

我的理解(来自之前关于 SO 的问题)是您要在露天实例中集成文档签名功能。并且您已经开发了一个 doclib 操作,它导航到一个带有小程序的特殊页面以验证用户身份,签署文档,然后上传它的新(签名)版本。现在,您需要将同一个小程序集成到工作流程中,以便让用户可以要求其他用户对文档进行数字签名(或类似的东西..)。

同样,我建议您将代码从小程序迁移到服务任务(服务器端),因为它具有更高的兼容性和更高的安全性(仅供参考:并非所有浏览器仍然支持 NPAPI,afaik 至少 Chrome 不再支持,因此他们需要配置才能 运行 你的小程序!)

话虽这么说,我猜你这样做的方法是:

  1. /org/alfresco/components/form/controls/workflow/activiti-transitions.ftl 中获得一些灵感并创建您自己的 sign-transition.ftl FTL,您可以在其中为您的小程序添加 html 和 js 代码,就像您在该页面中所做的一样.
  2. 记得从工作流包项目中获取文档 noderef(请记住,上次您从页面上的 get 参数中获取该信息 url)
  3. 一旦您成功将文档上传到您的存储库(在使用您的小程序签名后),您的 JS 回调应该调用与您按下转换按钮时相同的逻辑(使用 task 作为 itemKind 和 <taskId> 作为 itemId ....)

我没有你的小程序的详细信息,所以我不能确定它是否可行,但你可以尝试简单地使用一些 javascript 来访问你的小程序的 public 方法。

Alfresco 中的表单引擎可通过编写自定义控件轻松自定义。 自定义控件将生成将小程序嵌入表单所需的 html 和 javascript,并在按下按钮时调用它。

了解您是否可以在 Alfresco 上拦截小程序执行的更新会很有用。例如,您可以在 Alfresco 中有一个侦听器(行为),它将在文档更新时调用。如果根据您的业务逻辑,侦听器可以了解小程序已完成操作,它可以自动触发工作流的转换。 这个解决方案是健壮的,因为小程序执行的更新和任务的更新将是事务性的:它们都成功或更新被回滚。

如果可能,不要单独调用小程序和工作流的转换:这两个操作不会是原子的,您最终可能会得到不一致的存储库。

更新 为避免对 Alfresco 功能进行任何自定义,请勿修改活动转换。鉴于您只需要添加一个按钮来调用您的小程序,请使用自定义 ftl 并在您的表单配置中指定它。

下面的文章是学习如何做的一个很好的指南(我强烈建议阅读它并按照练习):

Jeff Potts' article on Advanced Workflows

如您在段落 Edit share-config-custom.xml 中所见,您可以指定用于呈现表单中每个字段的免费标记模板。如果愿意,您可以指定用于过渡按钮的不同模板。此模板将呈现小程序和 html 和 javascript 来调用它。

下面的class是一个监听行为的例子(这是从真实代码中复制的片段,我没有测试过,它只是为了展示行为的主要部分)创建节点或更新其属性。你必须选择对你更好的。小程序究竟有什么作用?它会创建一个新节点吗?或者更新它的属性?或者更新节点的内容?

以下link为您提供了触发转换的代码示例: Trigger Activiti workflow for task sitting in ReceiveTask looping

package com.someco.alfresco.behaviours;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy;
import org.alfresco.repo.policy.Behaviour;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.log4j.Logger;


public class SomeObjectCreatePolicy implements OnCreateNodePolicy, OnUpdatePropertiesPolicy {
    private final Logger logger = Logger.getLogger(SomeObjectCreatePolicy.class);

    @Override
    public void init() {
        this.policyComponent.bindClassBehaviour(
                QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
                Model.TYPE_ENTITY_OBJECT,
                new JavaBehaviour(this, "onCreateNode", 
                        Behaviour.NotificationFrequency.TRANSACTION_COMMIT));

        this.policyComponent.bindClassBehaviour(
                QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
                Model.TYPE_ENTITY_OBJECT,
                new JavaBehaviour(this, "onUpdateProperties", 
                        Behaviour.NotificationFrequency.EVERY_EVENT));
    }

    @Override
    public void onCreateNode(ChildAssociationRef childAssocRef) {
        /* Your logic to fire the transition */
    }

    @Override
    public void onUpdateProperties(NodeRef nodeRef,
            Map<QName, Serializable> before, Map<QName, Serializable> after) {
        /* Your logic to fire the transition */
    }
}

当然可以使用Spring实例化对象:

<bean id="org.alfresco.behaviours.someObjectCreatePolicy" class="com.someco.alfresco.policy.SomeObjectCreatePolicy"
        init-method="init">
</bean>