com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Transition UI Sample

This sample explains how to customize the UI used for lifecycle transitions. We will be reusing the code of the Custom UI Sample. This sample requires Apache Maven. See Installation Prerequisites for links on how to install it.

Instructions

1. Navigate to GREG_HOME/samples/custom-ui/src/org.wso2.carbon.registry.samples.custom.topics.ui/src/main/resources/web/registry/custom/endpoint to find the source code of the JSP files included in the Custom UI Sample.

2. Add a new JSP file named custom_transition_ui_ajaxprocessor.jsp at 

GREG_HOME/samples/custom-ui/src/org.wso2.carbon.registry.samples.custom.topics.ui/src/main/resources/web/registry/custom/endpoint/custom_transition_ui_ajaxprocessor.jsp with the following source:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page import="org.wso2.carbon.governance.custom.lifecycles.checklist.ui.processors.InvokeAspectProcessor" %>
<%@ page import="org.wso2.carbon.registry.extensions.utils.CommonConstants" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.regex.Pattern" %>
<%@ page import="java.net.URLDecoder" %>
<%
    try {
        boolean isViewVersion = false;
        boolean preserveOriginal = true;
        boolean viewDependencies = true;
        String displayMediaType = "";
        String currentEnvironment = "";
        String[] preserveOrigParam = null;
        String[] viewVersion = null;
        String[] parameters = request.getParameterValues("parameterMap");
        String path = request.getParameter("path");
        String aspect = request.getParameter("aspect");
        String action = request.getParameter("action");
        String callBack = request.getParameter("callBack");
        if (callBack == null || callBack.trim().length() == 0) {
            callBack = "''";
        }
        if (parameters != null) {
            for (String parameter : parameters) {
                parameter = URLDecoder.decode(parameter, "utf-8");
                if (parameter.contains("&")) {
                    String[] joinedParams = parameter.split("&");
                    for (String joinedParam : joinedParams) {
                        if (joinedParam.split("=")[0].equals("preserveOriginal")) {
                            preserveOrigParam = joinedParam.split("=");
                        } else if (joinedParam.split("=")[0].equals("viewVersion")) {
                            viewVersion = joinedParam.split("=");
                            isViewVersion = !Boolean.parseBoolean(viewVersion[1]);
                        } else if(joinedParam.split("=")[0].equals("displayMediaType")){
                            displayMediaType = joinedParam.split("=")[1];
                        } else if(joinedParam.split("=")[0].equals("showDependencies")){
                            viewDependencies = Boolean.parseBoolean(joinedParam.split("=")[1]);
                        }else if(joinedParam.split("=")[0].equals("currentEnvironment")){
                            currentEnvironment = joinedParam.split("=")[1];
                        }
                    }
                } else {
                    if (parameter.split("=")[0].equals("preserveOriginal")) {
                        preserveOrigParam = parameter.split("=");
                    } else if (parameter.split("=")[0].equals("viewVersion")) {
                        viewVersion = parameters[0].split("=");
                        isViewVersion = !Boolean.parseBoolean(viewVersion[1]);
                    }else if(parameter.split("=")[0].equals("displayMediaType")){
                        displayMediaType = parameter.split("=")[1];
                    } else if(parameter.split("=")[0].equals("showDependencies")){
                        viewDependencies = Boolean.parseBoolean(parameter.split("=")[1]);
                    }else if(parameter.split("=")[0].equals("currentEnvironment")){
                        currentEnvironment = parameter.split("=")[1];
                    }
                }
            }
        }
            if (isViewVersion) {
                try {
                    if (preserveOrigParam != null) {
                        String preserveOrg = "";
                        if (preserveOrigParam[0].equals("preserveOriginal")) {
                            preserveOrg = preserveOrigParam[1];
                        }
                        preserveOriginal = !Boolean.toString(false).equals(preserveOrg);
                    }
                    String versionString = "preserveOriginal" + "^^" + preserveOriginal + "^|^";
%>
<script type="text/javascript">
    invokeAspect('<%=path%>', '<%=aspect%>', '<%=action%>', <%=callBack%>, '<%=versionString%>');
</script>
<%
    } catch (Exception ex) {
        ex.printStackTrace();
        response.setStatus(500);
        ex.getMessage();
        return;
    }
%>
<%
} else {
    String mediaType = request.getParameter("mediaType");
    if (preserveOrigParam != null && preserveOrigParam.length != 0) {
        preserveOriginal = Boolean.parseBoolean(preserveOrigParam[1]);
    }
        List<String> otherDependencies = new ArrayList<String>();
        if (displayMediaType == null || displayMediaType.equals("")) {
            displayMediaType = CommonConstants.SERVICE_MEDIA_TYPE.replace(".", "[.]").replace("+", "[+]");
        }
        if (!(Pattern.compile(displayMediaType).matcher(mediaType).find())) {
%>
<script type="text/javascript">
    invokeAspect('<%=path%>', '<%=aspect%>', '<%=action%>', <%=callBack%>, "");
</script>
<%
} else {
    String[] associations;
    if (!viewDependencies) {
        associations = new String[1];
        associations[0] = path;
    } else {
        associations = InvokeAspectProcessor.getAllDependencies(request, config);
    }   
%>
<script type="text/javascript" src="../lifecycles/js/lifecycles.js"></script>
<script type="text/javascript">
    proceedAction = function (path, aspect, action, mediaType, callBack) {
        lifecyleOperationStarted = false;
        document.getElementById(org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["proceed"]).disabled = true;
        var versionString = "";
        var table = $('versionTable');
        var rows = table.getElementsByTagName('input');
        var regexp = new RegExp("^\\d+[.]\\d+[.]\\d+(-[a-zA-Z0-9]+)?$", "i");
        for (var i = 0; i < rows.length; i++) {
            var obj = rows[i];
            if ((obj.type == "text")) {
                if (obj.value == null | obj.value.trim == "") {
                    document.getElementById(org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["proceed"]).disabled = false;
                    showRegistryError(obj.getAttribute("id") + ' ' + org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["version.can.not.be.empty"]);
                    return;
                }
                else if (!jQuery.trim(obj.value).match(regexp)) {
                    document.getElementById(org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["proceed"]).disabled = false;
                    showRegistryError(org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["version.error.1"]
                            + " " + obj.getAttribute("id") + " " + org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["version.error.2"]);
                    return;
                }
                versionString = versionString + obj.name + "^^" + jQuery.trim(obj.value) + "^|^";
            } else if ((obj.type == "checkbox")) {
                versionString = versionString + obj.name + "^^" + obj.checked + "^|^";
            } else if ((obj.type == "hidden")) {
                versionString = versionString + obj.name + "^^" + "0.0.0" + "^|^";
            }
        }
        invokeAspect(path, aspect, action, callBack, versionString,org_wso2_carbon_governance_custom_lifecycles_checklist_ui_jsi18n["proceed"]);
    }
    cancelVersionBox = function (path) {
        refreshLifecyclesSection(path);
    }
</script>
<fmt:bundle
        basename="org.wso2.carbon.governance.custom.lifecycles.checklist.ui.i18n.Resources">
    <form id="dependencyVersionFrom" name="dependencyVersion">
        <%
            if (associations.length > 0) {
        %>
        <table class="styledLeft" id="versionTable">
            <tbody>
            <tr>
                <td>Resource</td>
                <td>Version</td>
            </tr>
            <%
                for (String association : associations) {
                    String assoName = association.substring(association.lastIndexOf("/") + 1);
                    if (currentEnvironment == null || association.startsWith(currentEnvironment)) {
            %>
            <tr>
                <td>
                    <%=assoName%>
                    <span class="required">*</span>
                </td>
                <td>
                    <input type="text" name="<%=association%>" id="<%=assoName %>"
                           style="width:140px;"/>
                </td>
            </tr>
            <%
                    } else {
                        otherDependencies.add(association);
                    }
                }
            %>
            <tr>
                <td colspan="2"><fmt:message key="preserve.original"/>: <input type="checkbox" name="preserveOriginal"
                        <% if (preserveOriginal) {%> checked="checked" <%} %> value="true"
                                                                               id="preserveOriginal"/></td>
            </tr>
            <tr>
                <td colspan="2">
                    <input class="button registryWriteOperation" type="button" id="<fmt:message key="proceed"/>"
                           value="<fmt:message key="proceed"/>"
                           onclick="proceedAction('<%=path%>', '<%=aspect%>', '<%=action%>','<%=mediaType%>'
                                   ,<%=callBack%>)"/>
                    <input class="button registryWriteOperation" type="button"
                           value="<fmt:message key="cancel"/>"
                           onclick="cancelVersionBox('<%=path%>')"/>
                </td>
            </tr>
            <%
                }
                for (String otherDependency : otherDependencies) {
                    String assoName = otherDependency.substring(otherDependency.lastIndexOf("/") + 1);
            %>
            <input type="hidden" name="<%=otherDependency%>" id="<%=assoName %>"
                   style="width:140px;"/>
            <%
                }
            %>
            </tbody>
        </table>
    </form>
</fmt:bundle>
<%
                }
      }
} catch (Exception ex) {
    ex.printStackTrace();
    response.setStatus(500);
%><%=ex.getMessage()%><%
        return;
    }

%>

The JSP file names ending with ajaxprocessor.jsp will not be processed by the Tiles Framework, and such pages will not render with the standard Carbon UI templates. This allows us to create pages that can be embedded inside regular JSP pages.

3. Compile the source code by running the following command inside GREG_HOME/samples/custom-ui/src/org.wso2.carbon.registry.samples.custom.topics.ui:

mvn clean install

The command mvn clean install will trigger an Apache Maven Build in your command line. This requires you having installed Apache Maven. See Installation Prerequisites for links on how to install it.

A successful run of Apache Maven will generate a report similar to the following:

4. Copy the GREG_HOME/samples/custom-ui/src/org.wso2.carbon.registry.samples.custom.topics.ui/target/org.wso2.carbon.registry.samples.custom.topics.ui-5.1.0.jar into GREG_HOME/repository/components/dropins.

5. Start the WSO2 Governance Registry. See Running the Product for more information.

6. Add something similar to the following to your lifecycle configuration.

<data name="transitionUI">
    <ui forEvent="Promote" href="../registry/custom/endpoint/custom_transition_ui_ajaxprocessor.jsp?currentEnvironment=/_system/governance/trunk/"/>
</data>

To learn more on how transition user interfaces can be configured for lifecycles, read the documentation on Lifecycle Configuration Elements.

In this example, we have referred to a JSP at registry/custom/endpoint/custom_transition_ui_ajaxprocessor.jsp. This is based on the JSP file that you created earlier in this sample. If you had a different name or path structure, the URL will change accordingly. The parameters passed in the query string is parsed inside the JSP file that you created. In this example, we have used a JSP that is identical to the pre_invoke_aspect_ajaxprocessor.jsp found inside the org.wso2.carbon.governance.custom.lifecycles.checklist.ui bundle. This JSP is what's used in the default ServiceLifeCycle configuration.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.