local procedure MyProcedure(varSalesHeader:Record"Sales Header")
Message('I am pleased that you called.');
What happens now is that Codeunit only has one instance for each session. When the first sales document is posted then the an instance of the Codeunit is created and kept in memory on the server as long as the session is alive.
This will save the resources needed to initialize an instance and tear it down again.
Making sure that our subscriber Codeunits are set to single instance is even more important for subscribers to system events that are frequently executed.
Note that a single instance Codeunit used for subscription should not have any global variables, since the global variables are also kept in memory though out the session lifetime.
Make sure that whatever is executed inside a single instance subscriber Codeunit is executed in a local procedure. The variables inside a local procedure are cleared between every execution, also in a single instance Codeunit.
On March 11th and 12th I will be teaching a VSCode and Modern NAV Development. This course will be held from 8:00am-5:00pm each day
The goal of the workshop is to learn about the new development tool for Business Central (Dynamics NAV), VSCode, GIT source control management and to experience what AL programming is about • What makes AL different from C/AL • How do you build and deploy a new BC feature • How can I convert my current code into AL • How to get ready for publishing your IP to AppSource • How to use GIT for you code
On the Developer track I will host three sessions.
Wednesday, March 13, 201910:15 AM – 11:45 AM, Room: Founders III
DEV75: How to Prepare Your Code for ALBCUG/NAVUG
Ready to completely re-think your all-in-one C/AL application? How about we try this: figure out how to split the code into “bricks” by functionality and/or processes, then turn that pile of bricks back into a usable solution. Can you migrate your customer data from the all-in-one C/AL database to the new continuous delivery cycle, replacing C/AL bricks with AL bricks. Let’s find out!
Wednesday, March 13, 20194:00 PM – 5:30 PM, Room: Founders II
DEV78: How I Got my Big Database Upgraded to Business Central
Your database upgrade takes longer than your available downtime window – bit of a problem, right? How about when executing all the upgrade processes on your database will take close to 10 days? Yeah, that’s a big problem. Of course you cannot stop a business for 10 days, but how do you shrink that to fit the 30-hour window over the weekend? You’ll hear the real life story and learn about the tools and methods you can use to streamline your upgrades.
Thursday, March 14, 20198:00 AM – 9:30 AM, Room: Founders III
DEV79: Breaking the Compilation Dependencies
Going to the extension model requires a simple structure to allow multiple extensions to talk to each other without having to put all of them into a compile dependency or into the same extension. Applying the standard API pattern inside the Business Central Service tier will give us the possibility to do all required functionality in a fast and easy way. This session is about explaining this pattern and giving some examples on how we have been using this pattern.
The “Enabled” Codeunit will test for Setup table read permission and if the “Enabled” flag has been set in the default record.
LOCAL TestEnabled(VARTempBlob:Record TempBlob)
WITH JsonInterfaceMgt DOBEGIN
This is how we can make sure that a module is installed and enabled before we start using it or any of the dependent modules.
Table Access Interface
The main module has a standard response table. We map some of the communication responses to this table via Data Exchange Definition. From other modules we like to be able to read the response from the response table.
The response table uses a GUID value for a primary key and has an integer field for the “Data Exchange Entry No.”. From the sub module we ask if a response exists for the current “Data Exchange Entry No.” by calling the interface.
Some processes can be both automatically and manually executed. For manual execution we like to display a request page on a Report. On that request page we can ask for variables, settings and verify before executing the process.
For automatic processing we have default settings and logic to find the correct variables before starting the process. And since one module should be able to start a process in the other then we use the JSON interface pattern for the processing Codeunit.
We also like to include the “Method” variable to add flexibility to the interface. Even if there is only one method in the current implementation.
Reading through the code above we can see that we are also using the JSON interface to pass settings to the Data Exchange Framework. We put the JSON configuration into the “Table Filters” BLOB field in the Data Exchange where we can use it later in the data processing.
From the Report we start the process using the JSON interface.
This pattern is similar to the discovery pattern, where an Event is raised to register possible modules into a temporary table. Example of that is the “OnRegisterServiceConnection” event in Table 1400, Service Connection.
Since we can’t have Event Subscriber in one module listening to an Event Publisher in another, without having compile dependencies, we have come up with a different solution.
We register functionality from the functionality module and the list of modules in stored in a database table. The table uses a GUID and the Language ID for a primary key, and then the view is filtered by the Language ID to only show one entry for each module.
This pattern gives me a list of possible modules for that given functionality. I can open the Setup Page for that module and I can execute the Interface Codeunit for that module as well. Both the Setup Page ID and the Interface Codeunit ID are object names.
The registration interface uses the Method variable to select the functionality. It can either register a new module or it can execute the method in the modules.
WITH JsonInterfaceMgt DOBEGIN
LOCAL RegisterCollectionApp(JsonInterfaceMgt:Codeunit"IS Json Interface Mgt.")
Where the Subscriber that needs to respond to this Publisher is in another module we need to extend the functionality using JSON interfaces.
First, we create a Codeunit within the Publisher module with Subscribers. The parameters in the Subscribers are converted to JSON and passed to the possible subscriber modules using the “ExecuteMethodInApps” function above.
Having standard ways of talking between modules and solutions has opened up for a lot of flexibility. We like to keep our solutions as small as possible.
We could mix “Methods” and “Versions” if we at later time need to be able to extend some of the interfaces. We need to honor the contract we have made for the interfaces. We must not make breaking changes to the interfaces, but we sure can extend them without any problems.
By attaching the JSON Interface Codeunit to the post I hope that you will use this pattern in your solutions. Use the Code freely. It is supplies as-is and without any responsibility, obligations or requirements.