Skip to Content
Author's profile photo Stefan Barsuhn

C4C: Using global variables


When you debug in C4C, you have an output window where you can see the sequence all the various script files are called. However, inside the ABSL script file you don’t have access to this information (otherwise known as a stack trace). Your ABSL file is blind – it does not know when it is called.

Example: When you link one document to another, various script files are called, e.g.:

  • BusinessTransactionDocument-AfterModify
  • BusinessTransactionDocument-Before Save
  • Root-AfterModify
  • Root-BeforeSave

… at best not only for the root document but also for the target document.

Wouldn’t it be great if you had the ability to pass information between those ABSL calls?

In my case, I was faced with a very complicated bug in C4C (due to be fixed in 1802) that lead to an infinite loop when changing two quotes in the same roundtrip.

In an on-premise system, I would have set a static global variable in the first roundtrip and in the second loop it would still be set so that I can see I’ve been here and break the loop. In C4C, this is not possible.


I ended up creating a separate BO that stores the UUID of the object, the node name and the change time. Luckily, the changetime stays the same during the infinite loop, so I am able to detect whether the same ABSL file is called twice in the same roundtrip.

Business Object

import AP.Common.GDT as apCommonGDT;

businessobject InfiniteLoopDetection {

        // In this BO, we register the UUID and the last change time of an object
	// if an infinite loop happens we can detect it b/c an entry for UUID and time already exists
		[AlternativeKey] element ObjectUUIDandNode : LANGUAGEINDEPENDENT_EXTENDED_Text;
		element ChangeDateTime : GLOBAL_DateTime;

The BO does not have any script files, but I created a reuse function that maintains the BO:

Reuse Function

import ABSL;
import AP.Common.GDT;

// checks if the supplied object uuid and time are already contained in the 
// InfiniteLoopDetection BO and returns true if it is
// if not, the entry is added if the IV_UPDATE parameter is true
var result : DataType::Indicator=false;
//return result;
// combine UUID and node into the key field (system supports only one unique key)
var key = IV_OBJECT_UUID.content.ToString() + IV_NODE;

var il = InfiniteLoopDetection.Retrieve(key);  

if (il.IsSet())
	if (il.ChangeDateTime == IV_DATETIME)
		// loop detected, return true
		result = true;
	else if (IV_UPDATE == true)
		// otherwise update time, return false
		il.ChangeDateTime = IV_DATETIME;
		result = false;
else if (IV_UPDATE == true)
	var il_node : elementsof InfiniteLoopDetection;
	il_node.ObjectUUID.content = Library::UUID.Generate(); // needed b/c save fails if missing (alternative key)
	il_node.ObjectUUIDandNode = key;
	il_node.ChangeDateTime = IV_DATETIME;
	il = InfiniteLoopDetection.Create(il_node);
	// this must work - otherwise dump
	var oid = il.ObjectUUIDandNode;
	result = false;

return result;


  • IV_OBJECT_UUID: UUID of the Object you want to register as touched
  • IV_NODE: Node of the Object you have touched (Root, Party, etc.)
  • IV_DATETIME: Time the object was changed
  • IV_UPDATE: If set to true: creates a new entry if it doesn’t exist/updates an existing entry

ABSL file

Now in each ABSL file that needs to access this global data, I just call the following code:

if (RULHelperFunctions.InfiniteLoopCheckAndUpdate(this.UUID, this.SystemAdministrativeData.LastChangeDateTime, "CustomerQuote.Root.BeforeSave", true) == true)

This example is for CustomerQuote. The field and node names could differ for other business objects.

How it works

In my case, I just needed to check whether an object, identified by UUID, node name and change time was already touched in the same roundtrip.

So in the debugger I had identified which ABSL files are involved in my infinite loop. In those files, I put the above ABSL code at the top. During the first roundtrip, the helper BO is filled with the document’s UUID, the current node and the change time of the document. If there is no entry, the ABSL file (BeforeSave etc.) is executed normally. However, during the second loop in the same roundtrip, the entry in the helper BO will already exist as the Change time remains the same. In this case I exit the ABSL file (BeforeSave etc.) with the return statement and this breaks the loop.

Storing data

You can easily add more field to the custom BO. This way you will not only check whether an entry exists, but can also pass more elaborate information between ABSL calls.


It has been suggested to use Transient fields. However, the transient field is not cleared automatically after the round trip. Meaning that during the next roundtrip the transient field will have the same value. It is only cleared if you press Cancel on the UI.

But you can use this to your advantage: If you want to store temporary global data that is persistent during roundtrips, but reset when you leave the screen, use transient fields.

If you need the temporary data to be valid only throughout the same roundtrip, use my solution above.


This blog post was created and tested with C4C release 1708.

Thanks to Horst Schaude who had the idea of using the document change time to separate ABSL calls caused by the infinite loop from ABSL calls triggered by actual changes in the UI.

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Benny Huang
      Benny Huang

      Hi Stefan,

      I use the code as the sample, but at the script:

      il = InfiniteLoopDetection.Create(il_node);

      it raise the issue:

      Method or action 'Create' is not permitted in script file related to a library function.

      My unit is FOUNDATION.

      Could you help check where is the problem?


      Best Regards,

      Benny Huang

      Author's profile photo Benny Huang
      Benny Huang

      Hi Stefan,

      Sorry, I forget click the Write-Enabled.

      Now it is OK.



      Best Regards,

      Benny Huang


      Author's profile photo Benny Huang
      Benny Huang

      Hi Stefan,

      I meet another issue, when I Batch import the document.

      the first bo instance is a range number, and the second bo instance I want to number+1(all in the modify event).

      it can't use the custom businessobject. and I want to use the NumberRange, but it get the same number, not number+1.

      any idea?

      thanks a lot.

      Best Regards,

      Benny Huang