Adobe Campaign, Marketing Automation

ACC | How to lock workflow

How to lock workflow in Adobe Campaign Classic

Many times, I have encountered situations where multiple individuals were simultaneously editing the same workflow. In such cases, the version that is saved last ultimately takes precedence. To avoid this issue, a simple solution would be to implement a workflow lock, which can prevent such scenarios from arising.

We want to achieve following business logic:

  • User can lock/unlock workflow to prevent other operators editing the workflow at the same time
  • Locked workflow can be modified only by who ever owns the lock (even admin gets error)
  • Admin can unlock workflow even without owning the lock


This can be achieved by following steps:

  1. add new field to xtk:workflow schema eg. lockedBy where you would store operator id. Each time someone presses the lock button it will either lock the workflow or unlock it.
  2. add lock/unlock button to xtk:workflow form
  3. add new schema methods to xtk:workflow schema and in JavaScript library
  4. add sysFilter to xtk:workflow schema or add validation to the xtk:workflow input form

Extending schema

Find schemas under Administritaion -> Configuration -> Data schemas and click on Add new schema. We will extend out of the box xtk:workflow schema.

Extend the data using an extension schema.

Make sure you are extending xtk:workflow and not nms:workflow

We will change the generated extension and add our fields, @lockedBy, additionally we will add new schema methods, that will be called to lock workflow.

NOTE: Even though we extended schema to cus:workflow we will still have to refer to it as xtk:workflow

With the new field added to the workflow schema we will have to restart following technical workflows:

  • Campaign jobs
  • Cost calculation
  • Jobs on service providers
  • Jobs on deliveries in campaigns
  • Offer notification

Or any other workflow that uses xtk:workflow table in any queries etc

<srcSchema created="2023-06-12 10:45:51.661Z" desc="Workflows definitions" extendedSchema="xtk:workflow"
           img="xtk:workflow.png" label="Workflows" labelSingular="Workflow" lastModified="2023-06-12 10:45:51.662Z"
           mappingType="sql" name="workflow" namespace="nxp" xtkschema="xtk:srcSchema">
  <createdBy _cs="Marcel Szimonisz (marcel.szimonisz)"/>
  <modifiedBy _cs="Marcel Szimonisz (marcel.szimonisz)"/>
  <element desc="Workflows definitions" img="xtk:workflow.png" label="Workflows"
           labelSingular="Workflow" name="workflow">
    <attribute label="Locked by" name="lockedBy" type="long"/>
  </element>
  <methods>
    <method library="cus:workflow.js" name="ToggleLockOnWorkflow" static="true">
      <parameters>
        <param desc="Workflow id" inout="in" name="id" type="int"/>
       <!-- <param desc="Status" inout="out" name="status" type="boolean"/>-->
      </parameters>
    </method>
  </methods>
</srcSchema>

You can add entire element that can contain more information about the time it has been locked or full name of the operator who has to worklfow locked. Next we will have to update database structure by navigating to Tools-> Advanced -> Update database structure ...

Do the best duo combination in Adobe Campaign Classic Clear the cache and logout for changes to take effect. Now we can see the field in the schema we can continue workfing on the form and on the javascript library.

Change the workflow form

Navigate to the Administration-> Configuration -> Input forms. We will add the lock button under the diagram container. Look for <-- [of]:Diagramme--> We can start by adding folliwing button form design right under it.

  <!--Lock workflow -->
  <container colcount="2" img="xtk:workflow.png" label="Diagram" name="diagram">
    <container colspan="2" type="visibleGroup" visibleIf="@lockedBy=='0'">
      <input img="nms:lock.png" label="Lock workflow" type="button">
        <enter>
        <!-- SOAP call to get the generated source -->
          <soapCall name="ToggleLockOnWorkflow" service="xtk:workflow">
            <param exprIn="@id" type="int"/>
          </soapCall>
        </enter>
      </input>
    </container>
    <container colspan="2" type="visibleGroup" visibleIf="@lockedBy!='0'">
      <input img="nms:unlock.png" label="Unlock workflow" type="button">
        <enter>
        <!-- SOAP call to get the generated source -->
          <soapCall name="ToggleLockOnWorkflow" service="xtk:workflow">
            <param exprIn="@id" type="int"/>
          </soapCall>
        </enter>
      </input>
    </container>
    <container colspan="2" padding-top="5" type="hpaned">
      <static/>
    </container>
<!--Lock workflow -->

When saving the form you may get many syntax errors from those one you can ignore as it was there since the fresh installation

XML-110013 Error line 1939, column 93 (document with schema 'form', name 'workflow' and description 'Workflow')

JavaScript Library

Similar to what we had described in the article how to add action button to the form view, we need to create JavaScript library nxp:workflow

var xtk_workflow_ToggleLockOnWorkflow = function(id){
  var operator = application.operator, 
      wkf = NLWS.xtkWorkflow.load(id),
      isAdmin = application.operator.hasRight("admin"),
      lockedBy = wkf.lockedBy>0 ? 0 : operator.id;
  
  if (wkf.lockedBy > 0 && wkf.lockedBy != operator.id && !isAdmin){
    logError("Workflow is locked!")
    return
  }
   
  wkf.lockedBy = lockedBy;
  wkf.save();
  //return true;
}

Add form validation on leave

One way how to achieve lock can be by using validation form feature everytime the workflow is saved. I will only enable the validation when the @lockedBy is not 0. We will call another schema method that will check if user has all necessary rights to modify or unlock the workflow. Which is even better beacuse we can perform any type of check that is needed and we will have the power of JavaScript finally!

Add following xml at the very bottom of the xtk:workflow input form right before the </form>

  <leave>
    <if expr="@lockedBy &gt; 0">
        <soapCall name="CanBeModified" service="xtk:workflow">
        	<param exprIn="@id" name="id" type="int"/>
      	</soapCall>
      <!--
		did not work :)
		<check expr="@lockedBy != [currentOperator/@id]">
        <error>The workflow is locked!</error>
      </check>
	-->
    </if>
  </leave>

Add following code to the cus:workflow.js JavaScript library that we have created before

var xtk_workflow_CanBeModified = function(id){
 var operator = application.operator, 
     wkf = NLWS.xtkWorkflow.load(id);
  if (wkf.lockedBy > 0 && wkf.lockedBy != operator.id)
    logError("Workflow is locked!")
  return;    
}

As we have learnt before, we have to add schema method as well.

    <method library="cus:workflow.js" name="CanBeModified" static="true">
      <parameters>
        <param desc="Workflow id" inout="in" name="id" type="int"/>
       <!-- <param desc="Status" inout="out" name="status" type="boolean"/>-->
      </parameters>
    </method>

With all in place now we can try if the lock feature is working as expected.

2023-06-13 08:24:07.559Z	0007C32E	0007C862	  2	error	log	Workflow is locked!

With the error hidden with settings on the security zone showErrors="false" we will get very generic eroro the real message can be seen in the web server log file or we can set showErrors to true so the message will look like following.

Add sysFilter to schema

We lock the workflow on the database level with sysFilter, so if you don’t use the workflow to make updates but instead use a script, the lock on the form will not prevent such changes. To lock the data schema, we add the following to achieve our goal.

<sysFilter name="writeAccess">
	<condition enabledIf="hasNamedRight('admin')=false" expr="@lockedBy = [currentOperator/@id] and @lockedBy > 0 or @lockedBy = 0"/>
</sysFilter>

With sysFilter we can also skip the <leave/> section in the form and thus xtk_workflow_CanBeModified can be removed from cus:workflow.js

Additionally we can add information such as email of operator who has the lock on the workflow, by adding link to operator and displaying the information next to the lock button.

Hidden feature: Workflow lock also applies for any workflow templates that can be used as campaign workflows or inside sub-worfklow activity, this is to prevent anybody who can access the templates (shared templates) to be modified by accident.

Hope this tutorial will get you started and create more advanced workflow lock. Let me know how it went.

Oh hi there 👋
I have a FREE e-book for you.

Sign up now to get an in-depth analysis of Adobe and Salesforce Marketing Clouds!

We don’t spam! Read our privacy policy for more info.

#JavaScript #jsapi #programming
Marcel Szimonisz
Marcel Szimonisz
MarTech consultant As a marketing automation consultant, I specialize in solving problems, automating processes, and driving innovation in my clients' marketing platforms.

I hold certifications in Adobe Campaign v6 (3x certified) and Salesforce Marketing Cloud (5x certified).

Additionally, I serve as a community advisor for Adobe Campaign, offering expert insights and guidance.

In addition to my professional pursuits, I also enjoy exploring various programming languages, CMSs, and frameworks, further enhancing my technical expertise and staying at the forefront of industry advancements.
Take a look at our subscription offering in case you are looking for a Marketing Automation Consultant.

One thought on “ACC | How to lock workflow

Leave a comment

Your email address will not be published. Required fields are marked *

Similar posts that you may find useful

How to leverage queryDef in Adobe Campaign
Adobe Campaign, Marketing Automation

ACC | How to Leverage queryDef in Adobe Campaign

7 minutes read

When it comes to programatically selecting records from the database in Adobe Campaign Classic, queryDef emerges as a crucial tool. As a static SOAP method extensively employed in JavaScript, particularly within workflows or web apps, queryDef offers unparalleled capabilities. However, what many may not realize is that there are three distinct implementations of this function. … Read more

Continue reading
Adobe Campaign post
Adobe Campaign, Marketing Automation

ACC | Add action button to the form view

2 minutes read

Have you ever wondered how to add new button with custom functionality to form view. I will show you step by step how to do it. In my example I will create signatures used in email campaigns, which will be dependent on the recipient’s profile information such as language, country etc. The way how I … Read more

Continue reading
Link campaign to the delivery send in salesforce marketing cloud
Salesforce Marketing Cloud

SFMC | Link campaign to delivery send

3 minutes read

Are you aware of Salesforce Marketing Cloud’s additional marketing feature known as Campaign? This tool allows you to group similar journeys together, providing greater organization for your marketing activities. However, one drawback is that the campaign information is not available in the data views. While waiting for a fix from Salesforce, you can establish a … Read more

Continue reading
preference center
Marketing Automation, Salesforce Marketing Cloud

SFMC | Multi-cloud preference center

5 minutes read

With majority of the implementations the out of the box center is not sufficient for the client and we are tasked to build custom preference center for them. We can assume that the preference center is only applicable for known subscribers most likely coming from email communication.  When we send email in salesforce marketing cloud, … Read more

Continue reading
Salesforce Marketing Cloud Tips
Marketing Automation, Salesforce Marketing Cloud, SFMC Tips & Tricks

SFMC | Queries are case insensitive

1 minute read

I recently discovered that when querying data views, case sensitivity in column names doesn’t make a difference; it consistently picks up the column when named correctly. Let’s explore where else column case sensitivity doesn’t play a significant role. First let’s create a data extension with some columns so we can test following in Query studio, … Read more

Continue reading