AEM工作流自定义输入数据

AEM工作流自定义输入数据,aem,aem-6,Aem,Aem 6,我需要在AEM中创建一个工作流,对于一个页面(指定为有效负载),找到页面上使用的所有资产,并将它们的列表上载到外部服务。到目前为止,我已经准备好了大部分代码,但业务流程要求我为每个页面使用一个特殊的代码(每个工作流运行时都不同),以便将列表上载到正确的位置 这时我有一个问题——你能为AEM工作流添加更多的输入值吗?也许通过扩展启动对话框,或者添加一些需要用户输入的特殊步骤?我需要能够在启动工作流或在其运行时以某种方式指定代码 我已经阅读了很多文档,但由于这是我第一次使用工作流,我可能遗漏了一些非

我需要在AEM中创建一个工作流,对于一个页面(指定为有效负载),找到页面上使用的所有资产,并将它们的列表上载到外部服务。到目前为止,我已经准备好了大部分代码,但业务流程要求我为每个页面使用一个特殊的代码(每个工作流运行时都不同),以便将列表上载到正确的位置

这时我有一个问题——你能为AEM工作流添加更多的输入值吗?也许通过扩展启动对话框,或者添加一些需要用户输入的特殊步骤?我需要能够在启动工作流或在其运行时以某种方式指定代码


我已经阅读了很多文档,但由于这是我第一次使用工作流,我可能遗漏了一些非常明显的东西。如果您能提供任何建议,包括相关文档的链接,我将不胜感激。

是的,这是可能的。您需要在工作流中实现一个对话框步骤:

您可以:

  • 在AEM中的某个位置创建自定义菜单项(例如,页面编辑器,
    /apps/wcm/core/content/Editor/\u jcr\u content/content/items/content/header/items/pageinfopopover/items/list/items/
    ,示例请参见libs下)

  • 使用
    categories=“[cq.authoring.editor]”
    创建一个客户端库。因此,它是作为页面编辑器的一部分加载的(而不是在页面的iframe中)

  • 创建一个JS侦听器,如果单击菜单项,它将打开一个对话框(请参见代码)。您可以使用普通的Coral UI对话框,或者我的示例误用了Granite页面对话框(Granite读取cq:dialog中的数据结构,并从中创建Coral UI组件编辑对话框,而Coral是普通的JS UI框架)

  • 创建一个Javaservlet,它捕获您的请求并创建工作流。理论上可以使用AEMServlet。但我经常不得不自己写,因为它缺少一些特性


  • 以下是JS侦听器:

    /*global Granite,jQuery,document,window */
    (function ($, ns, channel, window) {
        "use strict";
    
        var START_WORKFLOW_ACTIVATOR_SELECTOR = ".js-editor-myexample-activator";
    
        function onSuccess() {
            ns.ui.helpers.notify({
                heading: "Example Workflow",
                content: "successfully started",
                type: ns.ui.helpers.NOTIFICATION_TYPES.SUCCESS
            });
        }
    
        function onSubmitFail(event, jqXHR) {
            var errorMsg = Granite.I18n.getVar($(jqXHR.responseText).find("#Message").html());
            ns.ui.helpers.notify({
                heading: "Example Workflow",
                content: errorMsg,
                type: ns.ui.helpers.NOTIFICATION_TYPES.ERROR
            });
        }
    
        function onReady() {
            // add selector for special servlet to form action-url
            var $form = ns.DialogFrame.currentFloatingDialog.find("form");
            var action = $form.attr("action");
            if (action) {
                $form.attr("action", action + ".myexample-selector.html");
            }
    
            // register dialog-fail event, to show a relevant error message
            $(document).on("dialog-fail", onSubmitFail);
    
            // init your dialog here ...
        }
    
    
        function onClose() {
            $(document).off("dialog-fail", onSubmitFail);
        }
    
        // Listen for the tap on the 'myexample' activator
        channel.on("click", START_WORKFLOW_ACTIVATOR_SELECTOR, function () {
            var activator = $(this);
            // this is a dirty trick, to use a Granite dialog directly (point to data-structure like in cq:dialog)
            var dialogUrl = Granite.HTTP.externalize("/apps/...." + Granite.author.ContentFrame.getContentPath());
    
            var dlg = new ns.ui.Dialog({
                getConfig: function () {
                    return {
                        src: dialogUrl,
                        loadingMode: "auto",
                        layout: "auto"
                    }
                },
                getRequestData: function () {
                    return {};
                },
                "onSuccess": onSuccess,
                "onReady": onReady,
                "onClose": onClose
            });
    
            ns.DialogFrame.openDialog(dlg);
        });
    
    }(jQuery, Granite.author, jQuery(document), window));
    

    这是servlet

    @Component(service = Servlet.class,
            property = {
                    SLING_SERVLET_RESOURCE_TYPES + "=cq:Page",
                    SLING_SERVLET_SELECTORS + "=myexample-selector",
                    SLING_SERVLET_METHODS + "=POST",
                    SLING_SERVLET_EXTENSIONS + "=html"
            })
    public class RequestExampleWorkflowServlet extends SlingAllMethodsServlet {
    
        @Override
        protected void doPost(@Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) throws IOException {
    
            final Page page = request.getResource().adaptTo(Page.class);
    
            if (page != null) {
                Map<String, Object> wfMetaData = new HashMap<>();
                wfMetaData.put("workflowTitle", "Request Translation for " + page.getTitle());
                wfMetaData.put("something", "Hello World");
    
                try {
                    WorkflowSession wfSession = request.getResourceResolver().adaptTo(WorkflowSession.class);
                    if (wfSession != null) {
                        WorkflowModel wfModel = wfSession.getModel("/var/workflow/models/example-workflow");
                        WorkflowData wfData = wfSession.newWorkflowData(PayloadInfo.PAYLOAD_TYPE.JCR_PATH.name(), page.getPath());
                        wfSession.startWorkflow(wfModel, wfData, wfMetaData);
                        MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_OK, "Triggered Example Workflow");
                    } else {
                        throw new WorkflowException("Cannot retrieve WorkflowSession");
                    }
                } catch (WorkflowException e) {
                    MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
                }
            } else {
                MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error - cannot get page");
            }
        }
    }
    
    @组件(service=Servlet.class,
    属性={
    SLING_SERVLET_RESOURCE_TYPES+“=cq:Page”,
    SLING_SERVLET_选择器+“=myexample选择器”,
    SLING_SERVLET_方法+“=POST”,
    SLING_SERVLET_扩展+“=html”
    })
    公共类RequestExampleWorkflowServlet扩展SlingAllMethodsServlet{
    @凌驾
    受保护的void doPost(@Nonnull SlingHttpServletRequest请求,@Nonnull SlingHttpServletResponse响应)引发IOException{
    最终页面Page=request.getResource().adapto(Page.class);
    如果(第页!=null){
    Map wfMetaData=新HashMap();
    wfMetaData.put(“workflowTitle”,“请求翻译”+page.getTitle());
    wfMetaData.put(“某物”、“你好世界”);
    试一试{
    WorkflowSession wfSession=request.getResourceResolver().adapto(WorkflowSession.class);
    if(wfSession!=null){
    WorkflowModel wfModel=wfSession.getModel(“/var/workflow/models/example workflow”);
    WorkflowData wfData=wfSession.newWorkflowData(PayloadInfo.PAYLOAD_TYPE.JCR_PATH.name(),page.getPath());
    startWorkflow(wfModel、wfData、wfMetaData);
    MyServletUtil.respondSlingStyleHtml(response,HttpServletResponse.SC_OK,“触发的示例工作流”);
    }否则{
    抛出新的WorkflowException(“无法检索WorkflowSession”);
    }
    }捕获(工作流异常e){
    MyServletUtil.respondSlingStyleHtml(响应,HttpServletResponse.SC_内部_服务器_错误,e.getMessage());
    }
    }否则{
    MyServletUtil.respondslingtylehtml(响应,HttpServletResponse.SC_INTERNAL_SERVER_ERROR,“内部错误-无法获取页面”);
    }
    }
    }
    
    但从我在文章中看到的情况来看,该对话框显示在工作流创建上,而我的问题是在用户启动工作流时应该指定输入数据。所以我相信这并不能真正解决我的问题,是的。启动工作流时,带有对话框的步骤将成为收件箱中的一个项目。然后可以添加/设置数据。@RegyN很抱歉,对话参与者步骤是我想引用的,但是。。。当然,我接错了链接。我修复了链接。哦,好吧,这更有意义,谢谢:)我不知道我怎么错过了对话步骤。无论如何,答案是接受的布局,搜索和Adobe帮助的信息可以更好一些。。。再说一次:很抱歉造成混淆:)但所需的一切都已经由产品提供了吗?此外,还需要将数据绑定到适当的工作流实例节点。您的选项仅允许在工作流启动时传递数据。但在许多情况下,您可能希望在工作流运行时添加配置数据,特别是当工作流分配给另一个用户/组时。但要求输入“启动工作流时”。通常情况下,在第一步中启动工作流,然后在第二步中转到收件箱,找到启动的工作流并在自定义工作流步骤中输入数据,这对最终用户来说非常不方便。我认为这是一个遗憾,标准产品没有提供这一点。但在我看来,整个工作流引擎都是AEM中草率且容易出现错误的部分之一。”…在启动工作流或在其运行时编写代码。”尽管我理解您的观点,并与您分享您对该主题的看法,但我认为这是与产品的偏差应该非常仔细考虑的情况之一。