Today I would like to present an approach of syncing Composer Generated templates between different environments.
From other blog post like
we already know, that there are different approaches of doing that, like JSON or Code First.
In cases, where you develop a new, custom plugin, which needs the standard entities to me adapted, it definitely makes sense, to put composer generation code directly inside that plugin and let it run from there. a practical example for that, would be my GenericTaxes plugin, which has a dependency to the field “Taxes” to be present on all sellable items. Therefore I added there the possibility to directly create the necessary composer template from code, like seen here https://github.com/Chris1415/Plugin.Sample.GenericTaxes/blob/master/Pipelines/Blocks/CreateGenericTaxesComposerTemplatesBlock.cs
But, what, if you have Composer templates, which are not generated by code?
For such cases, I implemented a sync mechanism which uses a JSON file as exchange medium. In the following chapters I will introduce and show the whole idea and implementation of that, including all the pitfalls.
The basic approach is
- Export Composer templates to JSON
- Share the file with another environment
- Import the JSON to the new system
For the import I also created a few behaviors of how to import templates
- Override – If a template is already existing in the new environment, it will be completely overridden
- Skip – If a template is already existing in the new environment, the import will be skipped
- Merge – If a template is already existing in the new environment, it will be merged with the new template, so that the result is a template, which consists of existing fields and new fields
But enough of the words. Lets have a look at the code. To interact with the Composer Template Sync Plugin I created two action within CommandsController
These call do nothing else than accessing the corresponding commands for Import and Export.
As you can see from the Commands, the core logic is implemented within special Pipelines, which are now only triggered.
In the following screenshot you can see, how the pipelines are configured
Lets see, how all this works in action.
The first step is to use Postman to export all of your Composer Templates
The result of the command is a JSON file on your disc with the following content.
To achieve that the corresponding pipeline at first grabs all the Composer Templates from system within the first block. The core logic is displayed in the following screenshot
After getting all the templates, they have to be mapped to a custom composer template model. (Why we have to do that, I will explain later on in more detail)
Behind the scenes, there are just a few extension methods, which take care of proper model mapping.
In the end we just serialize the model and write that file to the disc
Now lets see, why we had to map the standard Composer Model to a custom one.
The first approach of using a JSON file was indeed to use the standard Composer Template model. But what happened when I tried to serialize that model and reuse that in another system, was that while serialization I lost the information of the types of specific fields. What I mean with that you see in the following screenshot
If you use the standard API to retrieve Composer Template, you see, that it has at least 2 Components as “Components” both from different types.
When I serialize that output I get the following JSON file
A have already marked the parts of “Components”. You see, that the information are correctly serialized, but without the information of which type each component is.
The result now, when you want to deserialize this input is a loss of information
Both components were now imported just as “Component” and not as “ListMembershipComponent” and “EntityViewComponent” so a lot of information specific to there types were now skipped, which resulted in an imported Composer Template with no properties.
Of course there are now various techniques to overcome that issues. I decided to use a custom model, where I have full control of how that model is filled, exported and imported again.
Now lets go back to the functionalities of the given project. After exporting the composer templates to JSON, we are now able to import that to another environment. We do that with the provided ImportComposerTemplates functionality provided by the plugin.
This functionality is responsible for
- Reading the file from disc
- Mapping the mapped composer template models back to the standard ones (Without loosing any information)
- Executing the actual import, based on the import type
Below you can see the example implementation of Override type.
As you can see, the logic just
- Checks for the proper import type
- Grabs all existing Composer Templates from current environment
- Runs through all imported templates
- Maps the given model back to the standard model
- Checks if the template is already existing in the system, based on the unique composer template id
- In case it is existing it just deletes that template (we could also instead of full deletion just modify the template and increase the version afterwards)
- Then it creates the new composer template completely based in the imported one
The whole process is able to export and re import ALL information, which are important for a Composer Template like
- Name of the View
- Associations to Commerce Entities like to all sellable items
- List of Properties
- Constrains applied on the properties
If something is missing or has to be added, it can easily be added to the custom model and model mapping and on the next run all the new information are added to.
Possible extensions could be
- Associations by tagging
- Further Constrains
Within this plugin we were able to export and import Composer Templates with a JSON approach for composer templates, which were not created by code, but directly within the Composer UI.
The code shown here is just an example of how such a requirement of exchanging Composer Template between environments, could be fulfilled. You could use that plugin as base for your own implementations and see how things could work, and maybe also how they are not working.
- The whole code can be seen on github under https://github.com/Chris1415/Plugin.Sample.Composer.Template.Sync