[Update: 2013-09-26] See new functionality in AX for Retail 2012 R2 that makes maintaining customizations a bit easier: AX for Retail 2012 R2: Using the Extensions folder for POS Customizations
One of the most challenging aspects of an AX for Retail deployment that we in Support help out with is dealing with ongoing maintenance of POS customizations.
The AX for Retail POS application was designed to be easily customized: many of the components are shipped with full source code and a developer can simply modify, compile, and deploy their version of that component. For example, if your deployment has a unique requirement for custom pricing, you would load the Price Service C# project (which contains the source code for Microsoft’s version of the component), make your code changes, compile to the Price.dll and then copy the DLL into your Retail POS folder. The next time you launch the POS application your customized version will automatically be used instead of the stock version. This is a bit simplified; for more details you can see the product documentation for this topic.
Very simple and very powerful. To steal an over-used superhero movie cliché, though, with great power comes great responsibility. And that responsibility is to have a plan to manage the source code for your POS customizations.
The problem is pretty easy to describe. By my estimate, almost half of the POS in AX for Retail 2012 R2 is customizable. This includes some very important core areas of the product: the price/discount/tax engine, receipt printing, end of day processing, sales order processing, and most of the UI elements (Dialog and Interaction services).
Because the sample source code that we ship for services and triggers is actually the same source code that is used to compile the shipped version of those DLLs, it is very likely that a hotfix we ship will affect that same code. By my rough count, about a third of all AX for Retail hotfixes that we have shipped in 2012 R1 (“6.1”) include changes to plug-ins.
If one of these hotfixes is for a component that you customized, you will need to update your customization to merge in this code change.
In addition, when you install a POS hotfix, the installer does not know about any customizations. This means at the very least you will have to re-copy your customized DLLs back into the Retail POS directory after installing the hotfix.
The concept of a “three-way code merge” is not a new one. Most source code repository solutions have tools built-in for this problem and there are many standalone text compare utilities that can be used to work around the issue. However, the biggest issue that I’ve seen with POS customizations is simply the awareness of the issue. Once the awareness is there, coming up with a system to handle the issue isn’t too difficult. Walking through a simple example should help.
Consider that there are two developers at work on the code: you (the Partner) and Microsoft. Developer “Partner” is tasked with making a customization to the price engine (Price service) and the receipt printing engine (Printing service). Let’s say that Partner started development on version 6.0.1108.2423 of the POS (AX 2012 CU4).
This means that Partner used the AX Installer to install the POS application and POS Plug-ins (source code which gets installed to the “my documents” folder) on a development machine and then later ran the CU4 installer (KB 2765124) to get both the binaries and plug-ins up to 6.0.1108.2423. We will call this the baseline that was used for customizations.
Suggestion: Make a copy of the baseline directory and store it in a safe place. In this screenshot you can see I just made a copy of the entire directory and named it “Retail POS Plug-ins 2423”:
To keep things even more segregated, I also made a copy of the directory to use for the actual development work:
The customizations to the Printing and Price services should then be done in this development directory:
Deploying the customizations is as simple as compiling the projects and then copying the resulting DLLs to the Retail POS\Services directory:
Installing the Hotfix
This customization is pretty simple and was coded and thoroughly tested before deploying to production. However, after a couple of months the client has discovered a bug in the receipt printing process (totally unrelated to your rock-solid code, of course) and Microsoft delivered a hotfix to address the issue (KB 2804675, version 6.0.1108.3631). Because the fix was targeted at receipt printing, it should be no surprise that the Printing customization may be affected. However, because POS hotfixes are always cumulative, there is a possibility that a previous hotfix also affected the Price plug-in. Because of the way we set up the source code directories, we can quickly determine what plug-ins are affected.
A POS machine will typically only have a few components installed so we will only select those components during the update:
Inspecting the Retail POS\Services directory we can confirm that the customized DLLs have indeed been clobbered (as expected):
We can use a compare utility to confirm that source code has been updated in the Retail Plug-ins directory by comparing it against our 2423 directory:
This shows us every change that was made to any service or trigger between builds 2423 and 3631:
As you can see, the Price project does not show up in this list. This means that no changes to the Price service have been made since the previous baseline. Partner only needs to worry about updating the Printing project.
The Manual Three-way Merge
Unless a three-way merge tool is being used, the developer needs to make a choice: a) merge Microsoft’s changes into the customization or b) re-merge the customization into the new baseline. The general rule of thumb is to figure out who did the most changes. If Partner’s customization is huge and Microsoft only made a small change, copy and paste Microsoft’s changes into the customization. If the Microsoft changes are larger, copy the new baseline version of the files into the customization directory and re-do the customizations. Since this example only changed a couple of lines in the FormModulation.cs file, this is the choice to make.
[Side Note: A third scenario is possible but unlikely: if you analyze the code changes between the two baselines you may decide that the changes Microsoft made will never be applicable to your customer. For example, maybe a fix was made to pricing with respect to trade agreements. If your customer doesn’t use trade agreements you might not even bother merging them into your customization. In general, though, this is bad practice as it is too easy skim over changes that you may not understand or have interdependencies you may not be aware of.]
To do the merge using option b) we will copy the new baseline versions of the Printing.cs and FormModulation.cs files to the development directory using Windows Explorer (after first copying the text of the customization):
At this point Visual Studio should prompt you to re-load the file. This will blow away your customization so be careful here!
And then we will simply copy and paste the customization again:
And now we can re-compile and re-deploy the DLL and start testing.
Wrap-up and Tips
After testing is complete, make sure to make another copy of the Microsoft-provided source code to match the hotfix that was installed. This will be the next baseline that will be used for the next hotfix that requires a code merge:
Obviously this can be a pretty convoluted process and even small customizations can quickly become very difficult to manage. A couple of tips that may help you out:
- If you made the mistake of just doing your development directly in the “Retail POS Plug-ins” directory before making a backup of it, you can always find a different machine and run an AX installer for that version. Remember that we’re only dealing with text files here (.CS files) so you can make copies of them anywhere you want.
- Be liberal in your use of code comments of your customizations. Anything you can do to help another developer with comparing lines of code will make things a lot easier down the road.
- When possible, create separate methods or even separate .CS files for your code. The fewer “touches” in the actual code the better.
- As mentioned, this is not a new problem and there are lots of tools out there to help with this type of code merge. At the very least, make sure you are storing your development branch in some sort of version control system.
Installing POS hotfixes is a very important part of your deployment maintenance and remembering about customizations is something that sometimes slips through the cracks. You never know when a critical hotfix will need to be rapidly deployed; make sure you have this process down solid beforehand and make sure to budget time for this important step.