Context
Definition | Context initialization | Access to context elements |
In V12, the SAFE X3 engine is able to perform stateless as well as stateful operations. The same SAFE X3 process is able to reply fast to a new request with a context that might change.
So, storing some default values in the global [V] variable class, even if it is still possible, would considerably limit the flexibility of the engine to serve quickly different requests.
This is why global variables use is now obsolete, and therefore it has to be replaced by a new feature. The new SAFE X3 Context feature has been introduced by the version 7 to replace the old "global variables" mechanism defined in function 'GESAGB', and to introduce various cache mechanisms to facilitate the retrieve of SAFE X3 parameter values in different cases.
The context code holds some context information that is relatively constant and stable, such as the current folder, current language and current user...
The main difference between the global variables defined in V6 and the context is that we can now have several contexts simultaneously: this can be interesting, for instance, if we need temporarily to have access to another set of global variables and parameters when performing an operation that involves several folders or several users.
The context itself is an instance of the class 'WMACONTEXT' (This means that developers cannot create another class named WMACONTEXT
in the class dictionary). As the name of this class is subject to change in the future, it is better to use the constant [V]CST_C_NAME_CLASS_CONTEXT
.
This means that declaring a new context pointer would be done by the following instruction:
Local Instance MY_CONTEXT Using =[V]CST_C_NAME_CLASS_CONTEXT
When a context pointer is sent to a Subprog
, the declaration of the parameter to be done will be following the same pattern:
Subprog MY_PROG(MY_TEXT, VAR1, VAR2...)Variable Instance MY_CONTEXT Using =[V]CST_C_NAME_CLASS_CONTEXT...
The data needed to deliver all these services will be lazy loaded. Every time a resource is needed, the context class will load the data if not already stored in the context, otherwise the access will be direct. This is why creating a context is very fast and efficient, because only the data requested in a session will be loaded.
At connection time, the supervisor creates automatically a default global context instance called '[V]GACTX'. In every class instance, there is also a reference to a context (the global one, or another in some particular cases), and this reference is named 'ACTX'. This means that in an event where this
is defined, this.ACTX.USER
will give access to the user code performing the operation the event is called for.
In some cases, it might be interesting to create a dedicated context. This can be done by using the following methods:
In order to use all context facilities, the context must be initialized first, with the following methods (called by Fmet
on the instance being created) :
ACTX_INIT_LAN(AFOLDER, LAN, LOGIN)
returns 0 if OK, otherwise returns an error code.
ACTX_INIT_LANISO(AFOLDER, LANISO, LOGIN)
returns 0 if OK, otherwise returns an error code.
The parameters are the following:
AFOLDER
is the folder code.LAN
is the SAFE X3 language code.LANISO
is the ISO language code.LOGIN
is the SAFE X3 login code.# Creating a new context on the same folder as the standard one but with another user code and languageLocal Integer ERROR_CODELocal Instance MY_CONTEXT_INSTANCE Using C_WMACONTEXTMY_CONTEXT_INSTANCE = NewInstance C_WMACONTEXT AllocGroup NullERROR_CODE = fmet MY_CONTEXT_INSTANCE.ACTX_INIT_LAN(GACTX.FOLDER,"GER","JOHNDOE")If ERROR_CODE = 0# successfulElsif ERROR_CODE < 0# warningElse# errorEndif
Context codes are all read-only and are first initialized by the 2 methods mentioned before.
The initialization will be done in lazy mode and differently depending on the element:
# We are here in a method called for a given class, so "This" is available# This.ACTX is the current instance pointer on the contextLocal Integer ERROR_CODE(3)ERROR_CODE = fmet this.ACTX.ACTX_RE_INIT()Case ERROR_CODEWhen 0 : # successfulWhen 3 : # Context code reinitialize errorWhen 4 : # Context cache clean errorEndcase
Local Integer ERROR_CODEERROR_CODE = fmet this.ACTX.ACLEAN()Case ERROR_CODEWhen 0 : # successfulWhen default : # error (not possible for the moment)Endcase
All the three methods mentioned before can return an error code (status code). This error code gives developers necessary information to decide how the program will be directed after. Here below is the interpretation of the different error codes:
Code | Signification |
---|---|
0 | Successful. |
-1 | warning : The given language code is not supported, the default language of the folder is applied instead. |
1 | error: The given folder not accessible. |
2 | error: Incorrect login. |
3 | error: Error when initialize Context codes. |
4 | error: Cache clean error (not possible for the moment). |
As already mentioned above, at execution time, a context instance is created by default at the beginning of each Sage X3 session. This context instance is initialized with the current user, the current folder and the current language. The global variable 'GACTX' gives access to this context instance.
Besides, any functional class instantiated in Sage X3 includes a reference to the context named 'ACTX'. By default, ACTX
references to GACTX
, but developers are allowed to create other context instances to be referenced in their classes, and they can initialize the contexts in their own ways. (This will be the case if we need to access to another folder other than the current one, in a copy function for example.)
During the development, it is strongly recommended to :
this.ACTX
rather than GACTX
to access context elements in the code attached to a class (a method definition). Otherwise, the code will not work if called with different contexts. All the examples given in this wiki page use : 'this.ACTX'.GACTX
to access context elements only outside a class.All the paths that access to the various information stored in the context will start from GACTX
or from this.ACTX
.
Context codes are to replace the old global variables defined in the V6 dedicated function (GESAGB). In V12, the new function defining the context codes is the context dictionary (function GESACTX).. See the corresponding documentation.
APARAM
is a child instance of class ACONTEXT
, it implements a local cache to store the parameter values already accessed to avoid querying the database every time.
See the corresponding documentation to see the implementation and the eight public methods provided by APARAM cache.
Cached classes are dedicated classes intended to store in the context, values of "small" parameter tables such as currencies, units, language codes...
Refer to the corresponding documentation to see the implementation and the eight public methods provided by cached classes.
When such a class exists, the data from the corresponding table will be lazy loaded for every line that is requested. This is of course only usable with "small" tables that contains "few" useful data (usually a cache class does not contain all the columns of the table).
The context class contains also a set of methods used to handle the rights granted by the license. See the corresponding document for more details.
In Sage X3 version 7, the access rights always depend on the function code. The context supplies a set of methods that handle the access rights in a dedicated context cache. Refer to the corresponding document for more details.
The additional context methods are documented in the following document (also accessible from the API documentation section).