As per my note on my previous blog on this topic, I will outline how to achieve something similar in NAV2016, but split into two bits. This is the first bit which is more generic, and follows the pattern from the standard system.
Before NAV2016, Codeunit 1 was the ideal place to put code to track all record changes, and there are two standard Codeunits which do exactly this: Codeunit 423 Change Log Management and Codeunit 5150 Integration Management (these two still have code in Codeunit 1 – I’m not sure why they haven’t moved to using Events yet, but I suspect they will).
In NAV2016 we have Events – which mean you don’t need to touch Codeunit 1, just subscribe to it.
So for the pattern you need one Table to store which tables you want to track. You could set this in code (as per Codeunit 5150) but I think a table is better.
Observable Table: "Table ID" Integer Object.ID WHERE (Type=CONST(Table)) TrackInsert Boolean [optional] TrackModify Boolean [optional] TrackDelete Boolean [optional] TrackRename Boolean [optional]
And then one Codeunit with the following Event subscriptions (all pointing at Codeunit 1).
C/AL LOCAL [EventSubscriber] OnDatabaseInsert(RecRef : RecordRef) IF Observable.Get(TableId) AND Observable.TrackInsert THEN //do something LOCAL [EventSubscriber] OnDatabaseModify(RecRef : RecordRef) IF Observable.Get(TableId) AND Observable.TrackModify THEN //do something LOCAL [EventSubscriber] OnDatabaseDelete(RecRef : RecordRef) IF Observable.Get(TableId) AND Observable.TrackDelete THEN //do something LOCAL [EventSubscriber] OnDatabaseRename(RecRef : RecordRef;xRecRef : RecordRef) IF Observable.Get(TableId) AND Observable.TrackRename THEN //do something LOCAL [EventSubscriber] GetTableTriggerSetup(TableId : Integer;VAR OnDatabaseInsert : Boolean;VAR OnDatabaseModify : Boolean;VAR OnDatabaseDelete : Boolean;VAR OnDatabaseRename : Boolean) IF Observable.GET(TableId) THEN BEGIN IF Observable.TrackInsert THEN OnDatabaseInsert := TRUE; IF Observable.TrackModify THEN OnDatabaseModify := TRUE; IF Observable.TrackDelete THEN OnDatabaseDelete := TRUE; IF Observable.TrackRename THEN OnDatabaseRename := TRUE; END;
The first four should be relatively clear, obviously if you don’t need to control which exact triggers you want to fire you can remove all the IF Observable.Track.. conditions.
The last one requires a bit of explanation. Basically Codeunit 1 calls GetTableTriggerSetup once per table per session, and it uses the result to determine whether it will call the OnDatabase triggers. If you don’t set the relevant boolean to TRUE, the OnDatabase trigger may not get fired at all.
I say “may not” as anything else listening to this Event (e.g. Change Log) may set the values to TRUE for this table, this is also why you should only ever set them to TRUE, and never set them to FALSE.
This also means that after you insert/change the record in the Observable Table, you may want to restart your NAV session to make sure that any changes you make actually fire the correct triggers.
That’s it! Pretty simple and very powerful. Hope you find it useful
Nikolai
[…] Observer pattern from my last blog acts as the Publisher, then we create a table to hold subscribers and filters (Change Observer), a […]
LikeLike
[…] the difference being the latter is “Cross-session”. See my follow-up blogs here: Observer in NAV2016 and PubSub in […]
LikeLike