Wednesday, August 02, 2006
A couple of months back I was dealing with a problem that took me a while to solve. I have been looking at both the Automation source code, and the AL code, and, although I don’t consider myself an AL expert, I do know how the AL engine works, so I was expecting to find an error if it indeed exist.
After struggling quite a bit with the source code of the Automation server I decided to send my modified Automation to test and proceed to explain the tester how the code was working and, then it hit me! Of course, there was a logic error in the code that did not seem obvious at the beginning.
I’ll try to explain the problem in a nutshell, but please keep in mind that similar problems exist in AL code, and there is no easy way of solving it (other than changing your original design). Please also notice that this is not a bug, but a limitation and that this does not mean that there is no possible solution to your logic, but that you have to “think further”.
Think at this design:
2 Automation servers, both with Events. For illustrative purposes, one of them being the ‘'Navision Timer 1.0'.Timer’. The code would be similar to this:
Global variables:
Auto1 Automation 'MyAutomation’.MyLogic
NTimer Automation 'Navision Timer 1.0'.Timer
OnRun trigger:
CREATE(Auto1);
CREATE(NTimer);
NTimer.Interval(20); // in milliseconds
NTimer.Enabled(FALSE);
My Automation event:
...
GlobalVariable := myCurrentSomething;
NTimer.Enabled(TRUE);
...
Ntimer event:
...
Do_Some_Processing(GlobalVariable);
...
CLEAR(GlobalVariable);
NTimer::TimerError(ErrorString : Text[1024])
Do_Some_Error_Handling_Specific_to_the_context(ErrorString, GlobalVariable);
Now. The previous code looks quite fine. The main reason why people are using the NTimer is because they can get, programmatically, any AL error in the only parameter of the TimerError, which is very convenient. I will, in another item, explain how to get this error programmatically from an Automation component.
So that we all are on the same page, you should see from the previous code that we have three different events:
- My Automation event
- The NTimer event
- The TimerError event
Let’s test this code with a simple scenario:
My Automation event is raised, which enables the NTimer, which uses the GlobalVariable to save a state. Now, at this point, we don’t know if the NTimer event will be called first, or our Automation event. Right now, this is irrelevant.
Now, when the NTimer event is raised, it does some processing with the GlobalVariable and at the end it erases it, but if an AL error occurs, the TimerError event should be raised where we are also using the GlobalVariable. This is a problem!