SysExtension framework pitfall: avoid new()
This research has been inspired by a real bug in the D365FO v. 10 (preview) application. It turned out that the SysExtentionAppClassFactory doesn’t explicitly call the new() method the 2nd time when it takes a previously resolved class name from the cache.
This is just good enough to pass an automated test or to fool a lazy tester, but in real life this may potentially result in run-time errors or other misbehaviour. Any code, any internal variable initialization you placed in the new() constructor is going to be bypassed the second time you call the same operation within the same client session.
To illustrate this, let’s use the demo project from my other blog.
Add the following code into the new() method of the MealCourse class:abstract public class MealCourse
{
...
protected void new()
{
info ("Yummy!");
}
}
Create a new action menu item to call this class, and place it on any of the D365FO menus. Call it once:
Right, yummy-yummy-yummy!
Call it again from in the same window (do not reload the browser but just click the menu item the 2nd time):
Nothing. The new() method has not been called.
Conclusion
Do not rely on the new() method when using the SysExtension framework. Let it be empty, do not put any logic at all inside. Perform the variable initialization in a dedicated method or any of the parm() methods, and call them explicitly in your constructor right after the SysExtensionAppClassFactory ::getClassFromSysAttribute() call.
X++ programming blog series
Further reading:
Print a custom product label: a Template solution in Process Guide Framework, with detours
Extending SysOperation contracts with DataMemberAttribute
X++ Decorator pattern in Dynamics 365
Get a cost center in D365FO
Find and merge a DimensionAttributeValue
SysExtension framework pitfall: avoid new()
Input validation and messaging in the Process Guide Framework
2 Comments
Hi Eugen,
I have just read both or you blog posts very carefully and wanted to give you a feedback.
The reason why new() is not called again is that you are using singleton. The point of singleton is to construct an instance once.
If you want to construct an instance every time, you should return false in your attribute class’s method useSingleton.
Therefore, I don’t believe it’s a bug as you state.
Respectfully,
Evaldas
Thanks for your reply! Even a singleton should serialize and de-serialize the internal variables somehow, do you agree? In the bug I was referring, a map initialized the first time was returning the CLR “No object…” error the 2nd time on an attempt to use the internal variable. If that object was properly instantiated and remained in the memory, the map class inside should have still be present in the RAM.