Singleton pattern template

Singleton pattern for single user session (process execution):
class VKSingletonTest
{
    private int rand;

    public static VKSingletonTest instance()
    {
        const str   mySysGlobalCacheKey   = 'VKSingletonTest';
        VKSingletonTest singleton;
        // AX2012
        //SysGlobalCache  globalCache = infolog.objectOnServer() ? appl.globalCache() : infolog.globalCache();
        // AX7/d365
        SysGlobalCache  globalCache = appl.globalCache();
 
        if (globalCache.isSet(classStr(VKSingletonTest), mySysGlobalCacheKey))
        {
            Info('cached instance');
            singleton = globalCache.get(classStr(VKSingletonTest), mySysGlobalCacheKey);
        }
        else
        {
            Info('new instance');
            singleton = new VKSingletonTest();
            //  Additional line for AX2012
            //globalCache.set(classStr(SingletonClass), mySysGlobalCacheKey, singleton);
            globalCache.set(classStr(VKSingletonTest), mySysGlobalCacheKey, singleton);
        }
 
        return singleton;
    }

    protected void new()
    {
        Random Random = new Random();
        rand = Random.nextInt();
    }

    public int getRand()
    {
        return rand;
    }

}
Simplified for D365F&SCM:
class VKSingletonTest
{
    private static VKSingletonTest singleton = new VKSingletonTest();
    private int rand;

    public static VKSingletonTest instance()
    {
        return singleton;
    }

    protected void new()
    {
        Random Random = new Random();
        rand = Random.nextInt();
    }

    public int getRand()
    {
        return rand;
    }
}
Test:
class VKTest
{
    public static void main(Args _args)
    {
        VKSingletonTest singleton = VKSingletonTest::instance();
        info(strFmt("%1", singleton.getRand()));

        singleton = VKSingletonTest::instance();
        info(strFmt("%1", singleton.getRand()));
    }
}
Both numbers will be the same in a single execution. However, for the next job execution numbers will be different.
SysGlobalObjectCache is server-shared caching across all user sessions on a specific server.
Single SysGlobalObjectCache exists for each server instance and is shared for all sessions.
class VKSingletonTest
{
    private int rand;
    #define.CurrentVersion(1)
    #localMacro.CurrentList
        rand
    #endmacro

    public static VKSingletonTest instance()
    {
        const str               myScopeKey  = 'VKSingletonTest';
        container               cacheKey    = ['VKSingletonTest'];
        container               cacheValue;
        VKSingletonTest         singleton;
        SysGlobalObjectCache    globalCache = new SysGlobalObjectCache();

        cacheValue = globalCache.find(myScopeKey, cacheKey);
 
        if (cacheValue == conNull())
        {
            Info('new instance');
            singleton = new VKSingletonTest();
            globalCache.insert(myScopeKey, cacheKey, singleton.pack());
        }
        else
        {
            Info('cached instance');
            singleton = new VKSingletonTest();
            singleton.unpack(cacheValue);
        }
 
        return singleton;
    }

    protected void new()
    {
        Random Random = new Random();
        rand = Random.nextInt();
    }

    public int getRand()
    {
        return rand;
    }

    public container pack()
    {
        return [#CurrentVersion, #CurrentList];
    }

    public boolean unpack(container packedClass)
    {
        Version version = RunBase::getVersion(packedClass);
 
        switch (version)
        {
            case #CurrentVersion:
                [version, #CurrentList] =  packedClass;
                break;
 
            default:
                return false;
        }
 
        return true;
    }

}
Standard example with caching values in CustVendExternalItemDescription class.

All entries in SysGlobalObjectCache can be removed for by running a class that uses the following URL:

/?mi=SysClassRunner&cls=SysFlushAOD.

The SysFlushAOD class clears all cache in SysGlobalObjectCache.

System administration / Setup / Refresh elements



Support The Author

 If you found value in what I share, I've set up a Buy Me a Coffee page as a way to show your support.

Buy Me a Coffee

Post a Comment


All Comments


Dmytro Obrusnik 14 November 2017

Why do you not use this piece of code? This is a code from MS Wiki: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/xpp-classes-methods

public class Singleton

{

private static Singleton instance;

private void new()

{

}

//static constructor

static void TypeNew()

{

instance = new Singleton();

}


Valery Moskalenko 16 August 2017

SysGlobalCache keep values inside one AOS server.

SysGlobalObjectCache keep values across all AOS servers.

To implement a real singleton, you should use SysGlobalObjectCache not SysGlobalCache.


Roman 09 February 2023

Completely Incorrect (regarding SysGlobalCache as well) . RTFM

A SysGlobalObjectCache object that is running in the AOS uses the same cache that is shared by all client sessions that are connected to that AOS. has access to a global cache that is shared by all client sessions.

Every record that is inserted into SysGlobalObjectCache is shared across multiple sessions that are in the same process. If an entry is inserted on the AOS, then all the sessions on the same AOS have access to the entry in the cache. However, any cache entries inserted on the AOS will not be automatically sent to the clients connected to that AOS. The entries will also not be sent to another AOS that is part of the deployment.

https://learn.microsoft.com/en-us/previous-versions/dynamicsax-2012/developer/how-to-use-the-sysglobalobjectcache-class-for-better-performance


Search

About

DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.

Authors are allowed to set their own "buy me a coffee" link.
Join us.

Blog Tags