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 second bit, which doesn’t have any corresponding objects in standard NAV as far as I can see.
I struggled with what to call this pattern (naming things is sometimes the hardest part of software development), if the previous pattern was Observer then this is something a bit more like PubSub – the difference being the Observer (and all NAV 2016 standard Events) happen within one session, where I want cross-session sharing.
However I didn’t want to confuse it with the NAV2016 standard Events which already use the terms Publisher and Subscriber. So I considered calling it “Cross Session Observer”. I also considered calling it “Real-time Observer”, as the reason behind creating the Pattern was to allow multiple users to be looking at the same view (and occasionally editing) to see real-time changes without having to reload all the data every minute or so. As my view was a Control Add-In this became quite important for performance sake.
In the end I stuck with PubSub as it is a messaging pattern, just using a NAV table as the messaging platform. However, I’ve avoided using the words Publisher and Subscriber in the objects to try avoid confusion. I will use them here to relate the objects back to the PubSub pattern.
The Observer pattern from my last blog acts as the Publisher, then we create a table to hold subscribers and filters (Change Observer), a Codeunit to be the Message Broker (ObserverMgt), and another table to hold the Messages (Change Notification).
These are the tables:
Change Observer: "Table ID" Integer "Observable Table" "Server ID" Integer "Session ID" Integer Change Notification: "Table ID" Integer "Observable Table" "Server ID" Integer "Session ID" Integer "Entry No." Integer AutoIncrement "Type of Change" Option Insert,Modify,Delete,Rename "Record ID" RecordID ... (other fields to indicate what has changed)
As you can see I decided that it was good enough for my implementation for the Observer to be identified by Server and Session ID’s. I think this could be extended to include other identifiers but this was the simplest approach. I also have only implemented one “filter” which is the Table ID that I am listening for.
The I have a Codeunit, ObserverMgt which gets called from my Observer(Publisher) OnDatabase… triggers, and for each Change Observer creates Change Notification records – I copied a bunch of code from Change Log to fill in these records.
The last thing I need are Subscribers, which in my cases are Pages. I added some functions to ObserverMgt (Listen, StopListening, Poll) to reduce code duplication, then on the Page I want to listen for changes I add a PingPong control (called Timer) and start Listening – remembering to Stop Listening when I’m done.
C/AL OnQueryClosePage(CloseAction : Action None) : Boolean ObserverMgt.StopListening(DATABASE::"NAV Whiteboard Booking"); Timer::AddInReady() IF ObserverMgt.Listen(DATABASE::"NAV Whiteboard Booking") THEN CurrPage.Timer.Ping(1000); Timer::Pong() CallUpdate; CurrPage.Timer.Ping(1000); LOCAL CallUpdate() ObserverMgt.Poll(DATABASE::"NAV Whiteboard Booking",TempChangeNotification); WITH TempChangeNotification DO BEGIN IF FINDSET THEN REPEAT IF "Type of Change" = "Type of Change"::Delete THEN BEGIN ... END ELSE IF RecRef.GET("Record ID") THEN BEGIN ... END; UNTIL NEXT = 0; END;
This is really pretty much the same as what I did in NAV2015, I’ve just extended my definitions somewhat to distinguish between the Event pattern part of it (inside a session) and the Messaging part of it (cross-session).
Hope this is interesting 🙂