AEM Workflow 自定义输入数据

AEM Workflow custom input data

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

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

我已经阅读了很多文档,但由于这是我第一次使用工作流,所以我可能遗漏了一些非常明显的内容。我将不胜感激任何建议,包括对相关文档的 link。

是的,这是可能的。您需要在工作流程中实施对话步骤:https://docs.adobe.com/content/help/en/experience-manager-64/developing/extending-aem/extending-workflows/workflows-step-ref.html#dialog-participant-step

你可以:

  1. 在 AEM 中的某处创建自定义菜单条目(例如页面编辑器,/apps/wcm/core/content/editor/_jcr_content/content/items/content/header/items/headerbar/items/pageinfopopover/items/list/items/<my-action>,请参阅库下的示例)

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

  3. 创建一个 JS-Listener,如果单击菜单项,它会打开一个对话框(参见代码)。您可以使用普通的 Coral UI 对话框,或者我的示例滥用了 Granite 页面对话框(Granite 读取 cq:dialog 中的数据结构,并创建一个 Coral UI 组件编辑对话框它——而 Coral 是普通的 JS UI-framework)

  4. 创建一个 Java-Servlet,用于捕获您的请求并创建工作流。理论上您可以使用 AEM servlet。但是我经常不得不自己写,因为它缺少一些功能。


这是 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");
        }
    }
}