Problem:
I have some code that is failing because an object has not been initialized. The solution for this bug is easy to fix, when detected. However, what surprised me is that my elaborate exception handling didn't catch this exception. That meant the exception wasn't logged or handled, and code following the try catch block was never executed. The try...catch block was outside of the transaction, so there was no issue there.
In this particular case, the exception was inside a batch (RunBaseBatch) job. The job handled several unrelated processing tasks. Once the exception conditions were met, the job terminated, so the other unrelated processing tasks were never called.
Does anyone know if it is possible to catch an "object not initialized" exception in Dynamics AX 2009? I read one post that said it may not be possible to catch certain exceptions in AX, however, I hope that is not the case (reference: https://community.dynamics.com/product/ax/f/33/p/16352/23700.aspx#23700).
Code example: Here is some simplistic code that recreates the issue:
server static void main(Args args)
{
Array arr;
;
info ("debug: before try...catch");
try
{
// ttsbegin; // enable/disable to test with transactions
// arr = new Array(Types::String); // Enabling this line will prevent the exception
arr.exists(3);
// ttscommit; // enable/disable to test with transactions
}
catch (Exception::Internal) // This exception handler was the Magic Sauce!!
{
info ("debug: catch (Exception::Internal)");
}
catch (Exception::Error)
{
info ("debug: catch (Exception::Error)");
}
catch
{
info ("debug: catch");
}
info ("debug: after try...catch");
}
UPDATE 2013-01-29 I am waiting to accept an answer until this question has been viewed more. Thank you for the answers so far.
I know the example I gave was simplistic. This type of bug is easily fixable when it is known. And defensive programming is always a good idea.
However, in the real world, the code where the bug occurred was very complex. The error occurred several levels deep in an overloaded method of a subclass. It occurred in a specific scenario, when an overloaded method corrupted the protected value of a member variable from the super class. That is where the bug occurred in the code, however, it didn't manifest itself until the super class tried to use the member variable again. The bug was summarily fixed when it was detected and tracked down.
Defensively, yes you could check every protected member variable, every time you use it, but that does start to impact performance, code readability, practicality, etc., which is why languages offer exception handling.
The question here, is how can these type of bugs be caught to make code more robust and bullet-proof? In most development environments (C, C++, C#, or Java for example), a try...catch at a top level could be used to catch, log, and clean up ALL unexpected exceptions. So the code would be able to continue processing with the other unrelated tasks. AX is continuing at some level, because the whole system doesn't come to a grinding halt when this bug occurs. However, the code after the catch in this job is not executing because of what appears to be a deficiency in AX/X++.
I am looking for an innovative solution or work-around, if it exists, to catch the "object not initialized" exception (really ALL exceptions) and to continue processing.
You can, but you shouldn't. A behavior like this is almost certainly a bad design of your code, that will inevitably end in more problems in the future.
You need to make your code defensive to this case, making sure the object is instanciated before using it. Otherwise, you're using the catch
code to an expected behavior, wich makes no sense.
EDIT 2013/02/18
In complex scenarios like what you're describing, it's usually very hard to get a solution fully controlled. In AX, try..catch
statement is quite simplified and in a very large range of situations is not really needed (unlike Java, C#, ... where is always recommended).
This simplification is nice in almost all situations of AX development, as you don't need to waste time on exception handling. Just let them raise, and the InfoLog will handle them on a simple and reliable way.
The big problem comes where you really need this control... when there is not really a way of force it. I'm not sure if this is really an standard issue or it's espected by the product team to work that way, but this cases are always giving troubles in AX. When you need to catch some specific issue you have to be very creative and deffensive to prevent the exception as catching it will become even more creative...
Hope this helps :)