Chain of command (CoC) example

There is a quite good documentation about Chain of command (CoC) here: https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/method-wrapping-coc

But this is almost all that I could find about it now, so I have played a bit with it to see clearer and I am sharing here with you what I have experienced.

Chain of command (CoC) example

CoC is a way of augmentation (new way of class extension) by which you can wrap logic around a method of a base class that you are augmenting. There can be more CoC extensions of the same method in different packages that all reference the package of the base class. The order of execution is random.
“The system randomly runs one of these methods… When the call to the next … method occurs, the system randomly picks another method in the CoC. If no more wrapped methods exist, the system calls the original implementation”

Ok, but I had to try it out on an example. My test was around Global::int642int(..) method.

  1. I created a new Package that reference Application Platform where Global class sits.
  2. Created a new extension class with CoC on global::int642str where I multiply the value by 5.
    [extensionof(classStr(Global))]
    final static class Global_JADTest_Extension
    {
        static int int642int(int64 _value, boolean _throwIfError)
        {
            int i = next int642int(_value*5, _throwIfError);
            return i;
        }
    
    }
  3. Executed it with a runnable class and passed value 100
    class job1
    {        
        public static void main(Args _args)
        {        
            info(strFmt('%1',int642int(100)));
        }
    
    }
  4. Result was 500
  5. Created another CoC in the same new extension package but different class. Here I add 10 to the value. The order matters as we know from primary school mathematics.
    [extensionof(classStr(Global))]
    final static class Global_JADTest2_Extension
    {
        static int int642int(int64 _value, boolean _throwIfError)
        {
            int i = next int642int(_value+10, _throwIfError);
            return i;
        }
    
    }
  6. Called it 10 times with the job
    class job1
    {        
        public static void main(Args _args)
        {        
            for (int i = 0; i < 10; i++)
            {
                info(strFmt('%1',int642int(100)));
            }
        }
    
    }
  7. The result was always 550, so first, the add than the multiplier was executed.
  8. I opened another Visual Studio and created another extension model referencing application platform
  9. Added another CoC to the same method. This divides the value by 5.
    [extensionof(classStr(Global))]
    final static class Global_PEPTest_Extension
    {
        static int int642int(int64 _value, boolean _throwIfError)
        {
            int i = next int642int(_value/5, _throwIfError);
            return i;
        }
    
    }
  10. The result was always 150. So execution order was ((100/5)+10)*5.
  11. I added info(‘1’) as the first line of the multiplier extension. info(‘2’) to the add and info(‘3’) to the division method. So, the order that I experienced in the last step was 3->2->1.
  12. Went for lunch, executed again and the result was still 150 (3->2->1).
  13. Removed the ‘for’ loop and added an extra “start” message to the Infolog
  14. The result changed. New result was 110, the order was Start->2->1->3.

So I could see the order of execution changing like they already wrote in the documentation, but it was good to try and now I can see more clearly on how CoC work.

Noticed 2 things:

1.

It is interesting that I had an error when creating the extension class saying the class must be “final”, but in the end, I removed the ‘final’ keyword and it works without that.


2.

Ok, I know they told it is not allowed, but I tried to solve the order of execution issue with extending the extension, but it was not allowed even if I was allowed to remove the ‘Final’ keyword

Leave a Reply

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