A customization mechanism has been part of the 1C:Enterprise platform for a pretty long time. This mechanism is called extension. It has been continuously improving, and with version 8.3.20, we have introduced some significant changes. The purpose of the article is to describe possible ways to use the extension mechanism and the new functionality introduced in the current version.
What is Good about Extensions?
Extensions offer an alternative to the existing strategy of modifying standard configurations. This alternative strategy dramatically simplifies the maintenance of standard solutions customized to specific conditions or particular customer requirements.
So, how does the current process look like today? There is a standard configuration fully supported by a vendor. It means that the vendor does not allow any modifications to such configuration. From time to time, the vendor releases a new (updated) version of the configuration. In this case, the update process from the old version to the new one is fully automatic. It is convenient and requires no special knowledge or training from customers.
Still, it is not rare that customers want to add something to the standard configuration or customize it to meet specific needs. As a result, the configuration loses the full vendor's support. And a deployment partner or customer's IT specialists should introduce requested changes. From now on, no automatic update of the vendor standard configuration is possible.
Now, the customer needs developers' support for deploying an update. At that, if the configuration contains plenty of modifications, the update process should most likely take plenty of time. Also, a developer overseeing the update in the vast majority of cases should have excellent knowledge of both standard configuration and modified parts.
The extensions introduce a different strategy. If you are unhappy with the standard configuration and intend to customize it, you do not have to touch the configuration at all. Instead, you make all the changes in an extension that basically is also a configuration.
Then, in the 1C:Enterprise mode, you attach your extension to the standard configuration. While running in the 1C:Enterprise mode, the platform automatically merges your extension with the standard configuration. As a result, customers can use a standard solution customized to their needs.
In its turn, when the vendor releases an updated version, the update gets installed automatically as the standard configuration has been remaining intact all this time. And it still has full vendor support. Again, as we start the updated application, the platform automatically merges the standard configuration with your extension. And the customer keeps on using the customized solution.
Where Do We Need Extensions?
The extension mechanism seems to be very attractive due to its versatility. This is why it is essential to understand what it is actually intended for.
To begin with, extensions are a lifesaver for applications running in data separation mode. Consider a service model, where a tenant wishes to have a couple of additional reports, and other tenants wish to keep on using the original configuration.
You can develop an extension specifically for such a tenant, taking care of all declared requests. The tenant attaches the extension and gets a customized configuration, while other tenants keep on using the standard solution. For this reason, extensions get attached and run per the active data separation policy.
Other use cases include modifying the standard configuration for a specific customer during the deployment stage or improving the standard configuration by the customer's IT specialists. With all changes introduced into the extension, the standard configuration retains full vendor support and remains ready for future updates.
You might be tempted to use extensions for building off-the-shelf products, but we strongly recommend against it. First of all, extensions are not designed for it. Second, other platform mechanisms know nothing about extensions. Distribution and support mechanisms are among them.
Just a brief look at the history of extensions shows that configurations have been gradually becoming more and more sophisticated. Nowadays, we see a need for additional support on various levels, including libraries, modules, industries, and others. After a thorough analysis of these needs, we have come to the conclusion that customization of configuration during deployment holds the highest priority.
And this is precisely why we have created the extension mechanism. You, obviously, should see we have made some improvements to respond to other above-mentioned needs, but they are not among priorities and should not lead you astray.
What is the Structure of an Extension?
An extension is similar to a standard configuration. It represents an object tree as well. And approaches for designing configurations entirely apply to extensions.
An important feature of extensions is the ability to use adopted objects. You can adopt any standard configuration object through the context menu:
Still, in some cases, you do not need to adopt objects. The best way to explain the concept is to compare it with a lunch at a restaurant.
Let us start with the case when there is a need for adopted objects.
Imagine you are used to having your lunch in a particular restaurant. You always order their steak and tea. "Why" is not so important. Say, they are top quality there. Or for any other reason. It does not really matter. The important thing is that you want to have the above-mentioned items only.
Then, the restaurant equals a standard information database. You are an extension. The restaurant menu is an expandable standard configuration. The steak and the tea are adopted objects. You have adopted them (just remembered these items are on the menu).
How do we attach an extension to a configuration and make it work? You come to the restaurant and ask for the menu. You see that the steak and the tea are on the list. It means you match adopted objects to the standard configuration objects. Naturally, you stick to object names for this purpose :-). You get your steak and tea, and you happily consume it. In order words, the extension gets attached and just works.
One week later, you come to the restaurant again and find out they have a new menu (there is a new standard configuration installed). Nevertheless, the steak and the tea are still on the menu. And this is precisely what you need. You get those items and enjoy your meal. It means the extension keeps running with the updated standard configuration.
One week later, you come to the restaurant again and find out that the steak and the tea are not on the menu anymore. You get up and leave (the extension failed to attach) because you want nothing else but these items. You have no idea about other dishes (objects). Your developer has not trained you on how to eat escargots or lobsters.
Case #2. You do not need adopted objects.
You come to the restaurant, and you do not care what they have on the menu because you have no intention to eat anything at all. You just want to take pictures of their food. And you know how to take a picture of any dish. You simply get attached to the configuration saying, "bring me all
appetizers you have on the menu (you get a set of documents from metadata). I want to take pictures of them (repost)."
Should we go back to the official IT language, it means we want to adopt objects when
- we need those objects for visual design. Imagine you expand a form and add form attribute type CatalogCurrencies.Reference. Here you certainly need to adopt catalog Currencies to check if this catalog still exists in the standard configuration on an attempt to attach your extension to it.
- we need those objects for our code to work. For example, you want to access attribute Importer in catalog Products with the code in your extension. You need to adopt this attribute to make sure it is available in catalog Products when your extension gets attached to the standard configuration.
You create extensions in Designer. As soon as you complete debugging and checks, you save your file in *.cfe format.
Now you can send the file to your customer. The customer takes it and uploads to its own infobase using the standard function Configuration Extensions Manager in the 1C:Enterprise mode.
As it is possible to handle extensions using the 1C:Enterprise language, you can create your own processor to attach them. To prevent unauthorized modification of extensions, we have an option to administrate configuration extensions.
On import of an extension from a file, it gets stored into respective infobase. At that, it happens in compliance with separation rules active for the current session.
To make the extension work, the session needs to be restarted. On the start of the session, right before calling event SessionParametersSetting, all extensions stored in the infobase and complying with applicable data separation policy get attached.
Thus, if the application runs in data separation mode, extensions become available to users of this particular tenant. If there is no data separation active, the system extensions work for all users of the system.
As mentioned earlier, the system, on an attempt to attach extensions, checks if adopted objects exist in the standard configuration matching them by names.
In addition to it, you can manage the process to a greater detail if needed. Thus, you can check not only objects' existence but the status of individual properties. In our example with the steak in the restaurant, you might want to be sure that the restaurant does not only offers stakes, but they can be rare or extra rare.
And now back to extensions. In the default state, they do not manage the properties of adopted objects. But should you need it, you can put selected properties under control. Imagine your algorithm requires not only that catalog Products exists, but it has code with type string in it.
Later on, should the vendor set the code type to number in this catalog within the standard configuration, your extension identifies it on an attempt to attach to the main configuration and returns an error.
It is also worth mentioning how we handle issues relating to the renaming of objects in a standard configuration. Imagine you are in the restaurant again, and they have changed steak to a beefsteak on the menu. In order words, on an attempt for the extension to get attached to the configuration, it gets an error failing to discover catalog Products because the vendor has changed it to Goods.
With the current version, this situation is not a problem anymore. You do not have to dig through the whole code in the extension to replace Products with Goods, thanks to the mechanism for change of module codes on renaming configuration objects and refactoring mechanism. Simply change the adopted object name to Goods and let the platform introduce further modifications to the extension. It happens automatically or with minimum involvement on your side.
How Extensions Operate.
We might spend much time talking about peculiarities of extensions operation in relation to various objects. Still, this is just a review article and should better focus on the essential and the most meaningful parts.
The 'beauty' of extensions is definitely not about an option to add something to the standard configuration that is not there. Instead, it is about being able to modify something that the standard configuration already has. It means that you can also change adopted object properties as well.
The core idea behind joint use of configuration and extension is this: if there is no "intersection," extensions complement the configuration; and in points of "intersection" extensions take over the configuration.
This approach perfectly works for managed forms. You can adopt a form from the main configuration into an extension and modify it within the extension as you need. Still, merging of form's visual elements and modules requires different strategies.
When we adopt a form into an extension, we take a kind of visual form "snapshot" and put it into the extension. When running in the 1C:Enterprise mode, the platform checks how each element of the visual form in the standard configuration or extension compares to the "snapshot" previously saved in the extension.
If there are no changes, or the platform discovers changes only in the standard configuration, it applies standard configuration parameters. In other cases, the platform uses the extension parameters.
Hence, if you use your extension to add a new command to a form, you should be able to see one together with other form commands. On changing an existing group title, you should see your title even in case the vendor changes this group's title in the standard configuration.
The strategy for form modules is the following. Within your extension, you create a dedicated module for the adopted form. At that, the module contains its own event handlers for all events. When running in the 1C:Enterprise mode, both form modules (one in the standard configuration and the other in the extension) merge within the same context. For this reason, every extension has a specific prefix that gets added to all event handlers in module forms. Thus, we can avoid conflicts with handlers in the standard configuration. The platform calls event and command handlers sequentially and synchronously. It starts with a handler from the extension, then comes a handler from the standard configuration. You can change the sequence or prevent execution of handlers in the standard configuration.
In general, when the configuration and extensions operate jointly in the 1C:Enterprise mode, they share a common namespace. It applies not only to individual modules but metadata trees as well. This makes it impossible when running in the 1C:Enterprise mode to determine whether an object is native to the standard configuration or comes from extensions.
As for other objects that you can use in your extensions, things seem to be easier there.
You can create subsystems in your extension. By utilizing adopted objects, you can expand existing subsystems by adding objects and subsystems that exist either in the standard configuration or in extensions. Nevertheless, you cannot remove elements from existing subsystems.
Also, you can expand roles only by adding to them objects created in extensions. You cannot remove anything from the existing role. The same applies to the command interface.
An Extension is Almost a Configuration.
As mentioned in the beginning, any extension is very much like a configuration. And as we are getting to the final line of this article, we would like to mention how extensions integrate with other platform mechanisms.
Extensions (just like standard configurations) include the main configuration and the database configuration. The configuration comparison and merger mechanism processes extensions the same way it does with standard configurations.
You can export an extension into a file (though it is in *.cfe format) and import it through a file. There is also a support of extension
download/upload in XML format.
UI text global search, replacement, and editing mechanisms work for extensions as well.
There are also some new command-line options designed specifically for extensions and new events for the event log. The main object that handles extensions within the 1C:Enterprise language is ConfigurationExtensionsManager.
Extension Mechanism Improvements in 1C:Enterprise Platform, Version 8.3.20.
We keep improving extensions functionality to enable you to create more sophisticated and feature-rich customizations. With version 8.3.20, you get more useful features. They include:
Support for Defined Types, Chart of Characteristic Types, and Common Attributes.
Starting with version 8.3.20, the platform supports defined types in extensions.
How can it be of use?
Imagine we have a configuration to automate the trade industry. It has a defined type weight (number (10,3)) that serves to record the weight of sold products (accurate to a gram).
Thanks to the support of defined types in extensions, we can build an extension that makes the configuration suitable for jewelry (with weights accurate to one-hundredth of a gram). To achieve it, we add to the extension of the main configuration defined type weight and redefine it as number (10,5).
Extensions also support chart of characteristic types. It is possible to adopt them from a configuration to an extension and redefine them as the task requires.
The same works for common attributes. Add it to your extension from a configuration and redefine it (e.g., set a different type). Nevertheless, this feature is not available for common attributes used for data separation.
Support for Type Sets
Version 8.3.20 offers new functionality in terms of using references to extension objects.
Thus, method Catalogues.AllRefsType().Types() returns an array of all catalog types, both from the main configuration and extensions. The same applies to method Documents.AllRefsType().Types() and similar. Previously these methods returned matching types defined in the configuration only.
Also, it is possible to reference object types defined in extensions through attribute AnyReference. Attributes CatalogReference, DocumentReference, and similar can contain references to matching object types defined in extensions. Previously, attributes referenced to object types defined in extensions would be set to Undefined.
Among other matters, this change should help extension developers nest their extensions into the Standard Subsystems Library mechanisms that utilize sets and defined types.
Support for Predefined Elements in Catalogs
Version 8.3.20 allows adding predefined elements into native extension catalogs. Previously this feature was only available for charts of characteristic types, charts of accounts, and charts of calculation types defined in extensions.