- The task at hand
- Interactive exchange
The distributed infobase scenario is a form of universal data exchange.
Attention! If you use the training version of the 1C:Enterprise platform, you will be unable to reproduce this example because distributed infobases are not supported by the training version.
Distributed infobases have identical configurations at all nodes and a tree-like node structure. They support not only exchange of data changes but also exchange of configuration changes.
The distributed infobase scenario employs exchange plans. Exchange plan configuration objects have the Distributed infobase property to support this scenario.
If you set the property to True, it enables the distributed infobase scenario for the exchange plan, and then you can create a distributed infobase using solely interactive means, without writing any script.
However, this feature does not prevent you from managing exchange using 1C:Enterprise script tools as they are also available for distributed infobase operations.
The following example describes both exchange implementation methods in a distributed infobase scenario.
As we have already mentioned above, a distributed infobase should have a clearly defined tree structure. The number of levels in that structure is unlimited. An explicit master-subordinate relationship between each pair of linked nodes is required (fig. 24.18).
Fig. 24.18. Distributed infobase structure
So, each node in that structure can have an unlimited number of subordinate nodes (or none at all). Additionally, each node except one should have a master node, and the root node is the only one with no master. This rigidly defined node structure is essential for specifying the migration pattern for data and configuration changes.
A configuration can only be changed in a node that has no master node (in the root node). Data changes can be made in any node.
Configuration changes are transferred down from the master node to subordinate ones. Data changes can be transferred between any linked nodes.
Collisions are resolved on the basis of master/subordinate relationships as well. If changes are made simultaneously in a master node and in a subordinate one, only the changes to the master node are accepted and changes to the subordinate node are discarded.
For any subordinate node an initial image can be created. An initial image is an infobase created on the basis of the configuration and data of the master node in compliance with the rules specified in the exchange plan. The initial node image creation procedure can be performed repeatedly. Every time it is performed, it deletes all the change records for the subordinate node from the master node infobase. Once an initial image is created, it is ready for exchange with the master node.
Creating an initial image is the recommended method of subordinate node creation in a distributed infobase.
The task at hand
As an example of distributed infobase operations, let us create several departments for Jack of All Trades.
Unlike branches that are located in different cities and act as independent entities with relative independence in how they manage their books, the departments are located in the same city, have no independent legal status, and keep their books in strict compliances with practices of the headquarters.
Therefore, they all use exactly the same configuration as the one used in the headquarters, and if the headquarters make any changes to the configuration, all of those changes should be rapidly disseminated to the configurations of the departments.
To implement this scenario, a distributed infobase is a perfect fit. First let us set up data exchange with departments using exclusively interactive means.
In Designer mode
To set up a distributed infobase, you need to create another Exchange plan configuration object.
- In the configuration object tree, add an ExchangePlan configuration object named Departments.
- In the Object presentation field, enter Department.
- Select the Distributed infobase check box (fig. 24.19).
Fig. 24.19. Specifying Distributed infobase property
- On the Input fields tab, select the Quick choice check box.
This allows selection of exchange plan nodes from a drop-down list. Next let us define the set of objects that participate in the exchange.
- On the Main tab, click the Content button and specify the same data exchange content as the one used in the Branches exchange plan.
Basically you should include all the objects that are not related to accounting and payroll into the exchange. The resulting content of exchange data should look as shown in fig. 24.20.
Fig. 24.20. Exchange data content
- On the Subsystems tab, include the exchange plan in the Enterprise subsystem.
- In the Enterprise subsystem command interface settings window, move the command that opens the Departments exchange plan to the Navigation panel.Important group, after the Branches command, and make it available to the Administrator role only.
- In the Actions panel.Create group, enable visibility of the Department: create command for the Administrator role only.
In 1C:Enterprise mode
Let us create the department infobase.
- Start 1C:Enterprise in the debug mode.
Let us specify the parameters of the central node (which is a predefined item of the exchange plan).
- In the Enterprise section, in the navigation panel, click Departments.
You can see that the list of exchange plans contains a single empty row. This is the predefined infobase node.
- Open that row, enter CI for the infobase code and Central infobase for its description, then click Save and close.
- Create an exchange plan node with Dep for the infobase code and Department for its description.
The created node has three buttons available in the command bar of the exchange plan form: Write changes, Read changes, and Create initial image (fig. 24.21).
Fig. 24.21. Commands for distributed infobase operations
Let us use one of these buttons to create an initial image of the department infobase.
- Create a new directory on the hard disk to store the department infobase.
- In the list of data exchange nodes, click Departments and then click Create initial image.
- In the Create initial infobase image dialog box, specify that the infobase will be located on this computer, and click Create initial image.
- At the next step, click Save and specify the directory that you created for the infobase (fig. 24.22).
Fig. 24.22. Creating an initial infobase image
- Return to the Create initial infobase image dialog box and click Close.
The platform creates the initial image of the department infobase in the specified directory.
Running the department infobase
Let us switch to the department infobase.
- Run 1C:Enterprise.
Then let us add the created infobase to the list.
- In the 1C:Enterprise startup window, click Add, click Adding an existing infobase to the list, and then click Next.
- Enter the infobase name (for example, Department infobase), then click Next.
- Specify the infobase directory where the saved configuration is located (for example, D:\Practical developer guide\department), click Next, and click Ready.
In Designer mode
Let us prepare the department infobase for the exchange.
- Open the department infobase configuration in Designer mode.
- On the Configuration menu, click Open configuration.
You can see that the department configuration is protected from modifications via distributed infobase management tools (fig. 24.23).
Fig. 24.23. Subordinate node configuration protected from modifications via distributed infobase management tools
- On the Administration menu, click Users and create a single user: Administrator with Administrator role.
In 1C:Enterprise mode
Let us enter the values required for data exchange.
- Start the department infobase in the debug mode and open the Departments exchange plan (fig. 24.24).
Fig. 24.24. Nodes of the Departments exchange plan
Note that in the infobase of the subordinate node the subordinate node itself (Department) is a predefined exchange plan node, while the central infobase node is marked by a yellow icon, indicating that it is the master of the department infobase. Additionally, the only available commands for the central infobase are Write changes and Read changes.
Now let us test the data exchange.
- Set the Numbering prefix to DP.
Note. If you completed Lesson 25 (Functional options) prior to lesson 24, some sections might be hidden from the sections panel (for example, the Accounting section). If this is the case, open the General settings form and check the values of the functional options that define section visibility (for example, the Accounting option). Note that functional options are not transferred between nodes, you have to specify their values independently for each node.
- Open the Customers catalog and add a new customer.
- Open the Departments exchange plan, select the Central infobase node (the node where you need to transfer the changes), and click Write changes.
- In the Write message with changes dialog box, click Write and save to file.
- Click Save and specify the message file name (fig. 24.25).
Fig. 24.25. Write message with changes dialog box
- In the Write message with changes dialog box, click Close.
- Start the central infobase in the debug mode, open the Departments exchange plan, click the Department node (the node whose changes you need to transfer to the central infobase), and click Read changes.
- In the Read message with changes dialog box, click Select file and read changes.
- Specify the message file name and click Open.
- In the Read message with changes dialog box, click Close.
- Ensure that the new customer created in the department infobase is now available in the central infobase as well.
- Close the 1C:Enterprise window of the central infobase.
Next, let us test how configuration changes are transferred between the master node and subordinate ones.
- In Designer of the central infobase, create a constant named NewConstant.
- In the Warehouses catalog, add a predefined item named Office with code 000000003.
When you start creating the predefined item, the platform provides 000000002 as the default code value. But the catalog already includes a Retail warehouse with code 000000002, which was created in 1C:Enterprise mode, so you have to change the code to make it unique.
- Update the database configuration and start 1C:Enterprise in the debug mode.
- Open the Departments exchange plan and write the changes for the Department subordinate node.
- Close the 1C:Enterprise window and close Designer of the department infobase.
- Run the department infobase in 1C:Enterprise mode and read the changes from the Central infobase node.
Once the changes are read, the following message is displayed (fig. 24.26).
Fig. 24.26. System message
- Close the 1C:Enteprise window, open Designer of the department infobase, and ensure that the NewConstant constant is now available in the configuration, as well as the Office predefined item of the Warehouses catalog.
In other words, the changes made to the central infobase configuration have been replicated to the configuration of the subordinate node.
Now everything you need to do is update the infobase configuration in the subordinate node.
We should probably say a few words concerning the order of applying changes when a single message contains changes to both the configuration and the data.
In this case, the base configuration is changed first, and then a message is displayed prompting you to update the database configuration.
But at that point the new data is not yet added. For example, the Office predefined item is not yet present in the Warehouses catalog.
Unlike universal data exchange, the distributed infobase scenario is free of the issue related to duplication of predefined data. This is because automatic creation of predefined data is not performed in subordinate nodes of a distirbuted infobase.
After synchronizing the configurations, you have to reread the data, and this time all of the data changes stored in the message are applied. The order of applying changes remains the same regardless of whether the changed data refers to existing configuration objects or new ones.
- Delete the NewConstant object and the Office predefined item of the Warehouses catalog.
All the distributed infobase data exchange activities that you performed manually in the previous part of the lesson can be programmed as well.
Let us create a data processor that performs all these operations for a specified node.
In Designer mode
Let us implement script-based data exchange.
- Open the central infobase in Designer.
- Create a DataProcessor configuration object named DepartmentsExchange.
- On the Forms tab, create a default data processor form.
- In the form editor, on the Attributes tab, add a form attribute named DepartmentTextBox of the ExchangePlan.Departments type.
- Drag the attribute to the form controls pane.
- In the field property palette that is opened, set the field title to Department and keep the default field type (Text box, fig. 24.27).
Fig. 24.27. Editing data processor form
- On the Commands tab, create the following commands: CreateInitialImage, WriteChanges, and ReadChanges.
- For each of the commands, in the property palette, in the Action field, click the Open button and create a client handler.
Do not fill the event handlers for now.
- Click the Form tab and drag all three commands to the form controls pane.
The resulting data processor form should look as shown in fig. 24.28.
Fig. 24.28. Data processor form
- Open the property palette of the CreateInitialImage button and clear the Availability check mark.
When you open the data processor, the button should not be available until you select an exchange plan node in the DepartmentTextBox field. And this button should not be available if you select the predefined node of the infobase. In other words, initial image creation should not be available if the selected node is a predefined one.
Let us implement this button behavior.
- In the data processor form module, create a function that is executed on the server and returns True if the node passed to the function is the predefined one (listing 24.25).
Listing 24.25. PredefinedNode() function
&AtServerNoContext Function PredefinedNode(Node) Return Node = ExchangePlans.Departments.ThisNode(); EndFunctionIn the form controls pane, open the property palette of the DepartmentTextBox item, create the Selection processing event handler, and fill it as shown in listing 24.26.
Listing 24.26. TextBoxDepartmentChoiceProcessing() procedure
&AtClient Procedure TextBoxDepartmentChoiceProcessing(Item, SelectedValue, StandardProcessing) If PredefinedNode(SelectedValue) Then Items.CreateInitialImage.Enabled = False; Else Items.CreateInitialImage.Enabled = True; EndIf; EndProcedureThe procedure sets the availability of the CreateInitialImage button depending on the value of the PredefinedNode() function. This value, in turn, depends on the reference to the selected node passed to the function (SelectedValue).
- Fill the CreateInitialImage command handler as shown in listing 24.27.
Listing 24.27. CreateInitialImage button click handler
&AtClient Procedure CreateInitialImage(Command) Dialog = New FileDialog(FileDialogMode.ChooseDirectory); Dialog.Title = "Specify infobase directory"; If Dialog.Choose() Then CreateInitialImageAtServer(DepartmentTextBox, Dialog.Directory); Message = New UserMessage; Message.Text = "Initial image created."; Message.Message(); EndIf; EndProcedureFirst, the procedure opens the dialog box for selecting the directory to store the infobase image. Then it calls the CreateInitialImageAtServer() procedure, which is executed on the server without context. This procedure calls the CreateInitialImage() method of the ExchangePlansManager object.
This method creates an image of a subordinate distributed infobase node. Its first parameter is a reference to the node (DepartmentTextBox form attribute) for which the initial image is created, and the second parameter is a connection string that specifies the infobase.
- Create the procedure shown in listing 24.28.
Listing 24.28. CreateInitialImageAtServer() procedure
&AtServerNoContext Procedure CreateInitialImageAtServer(Node, ConnectionDirectory) ExchangePlans.CreateInitialImage(Node, "File =""" + ConnectionDirectory + """"); EndProcedure
- Create an event handler for the WriteChanges command (listing 24.29).
Listing 24.29. WriteChanges button click handler
&AtClient Procedure WriteChanges(Command) Dialog = New FileDialog(FileDialogMode.Save); Dialog.Title = "Specify exchange file"; If Dialog.Choose() Then WriteChangesAtServer(DepartmentTextBox, Dialog.FullFileName); Message = New UserMessage; Message.Text = "Writing changes completed."; Message.Message(); EndIf; EndProcedureFirst, the procedure opens the dialog box for selecting the file to store the changes. Then it calls the WriteChangesAtServer() procedure that is executed on the server without context. The first parameter of the procedure is a reference to the node (DepartmentTextBox form attribute) for which the changes are recorded.
The procedure creates an XMLWriter object to work with the file.
Next it creates an ExchangeMessageWriter object that will be used to create an exchange message. The second parameter of the BeginWrite() method is the exchange node for which the message is created.
Then the procedure calls the WriteChanges() method of the ExchangePlansManager object, which writes the changes intended for the selected node to the specified exchange message.
Finally, it ends the exchange message writing and closes the file.
- Create the procedure shown in listing 24.30.
Listing 24.30. WriteChangesAtServer() procedure
&AtServerNoContext Procedure WriteChangesAtServer(Node, FileName) // Creating and initializing XMLWriter object XMLWriter = New XMLWriter; XMLWriter.OpenFile(FileName); // Creating ExchangeMessageWriter object and starting message writing ExchangeMessageWriter = ExchangePlans.CreateMessageWriter(); ExchangeMessageWriter.BeginWrite(XMLWriter, Node); // Writing message body content for the // distributed infobase data exchange message ExchangePlans.WriteChanges(ExchangeMessageWriter); // Ending the writing and closing XMLWriter ExchangeMessageWriter.EndWrite(); XMLWriter.Close(); EndProcedureLearn more! It is worth noting that the WriteChanges method lets you specify the limit of data items stored to a message within a single transaction. By default, all data is stored within a single transaction.
This is the recommended mode because it ensures the consistency of data stored to a message.
However, if a message is created in multiuser mode, lock conflicts may occur between transactions that store data to messages and transactions performed by other users. To reduce the chance of such conflicts, you can adjust the parameter value. The lesser the parameter value, the lesser the chance of conflict, but the higher the chance of storing inconsistent data to the message.
Considering all of the above, the ideal solution is to perform data exchanges in exclusive mode. However, this option is not always available given the way a specific infobase can be set up.
- Create an event handler for the ReadChanges command (listing 24.31).
Listing 24.31. ReadChanges button click handler
&AtClient Procedure ReadChanges(Command) Dialog = New FileDialog(FileDialogMode.Open); Dialog.Title = "Select exchange file"; If Dialog.Choose() Then ReadChangesAtServer(Dialog.FullFileName); Message = New UserMessage; Message.Text = "Reading changes completed."; Message.Message(); EndIf; EndProcedureFirst, the procedure opens the file selection dialog box to select the file to be read. Then is calls the ReadChangesAtServer() procedure that is executed on the server without context.
This procedure creates an XMLReader object to work with the file. Then it creates an ExchangeMessageReader object to read the message stored in the specified file.
Then it uses the ReadChanges() method of the ExchangePlansManager object to read the received message.
Finally, it ends the exchange message reading and closes the file.
- Create the procedure shown in listing 24.32.
Listing 24.32. ReadChangesAtServer() procedure
&AtServerNoContext Procedure ReadChangesAtServer(FileName) // Creating and initializing XMLReader object XMLReader = New XMLReader; XMLReader.OpenFile(FileName); // Creating ExchangeMessageReader object and starting message reading ExchangeMessageReader = ExchangePlans.CreateMessageReader(); ExchangeMessageReader.BeginRead(XMLReader); // Reading message body content ExchangePlans.ReadChanges(ExchangeMessageReader); // Ending the reading and closing XMLReader ExchangeMessageReader.EndRead(); XMLReader.Close(); EndProcedure
- On the Subsystems tab, include the DepartmentsExchange data processor in the Enterprise subsystem.
Then let us set up the main section command interface for Administrator.
- Right-click the root configuration object and then click Open main section command interface.
- Add the commands that open General settings, Data exchange, and Departments exchange forms to the list of main section commands and enable their visibility for Administrator only (fig. 24.29).
Fig. 24.29. Customizing main section command interface for Administrator
Let us add the list forms of Branches and Departments exchange plans to Administrator's home page.
- Right-click the root configuration object and then click Open home page work area.
- For the Departments exchange plan, create a list form.
- Add the list forms of the Branches and Departments exchange plans to the left part of the home page and make them visible to the Administrator role only (fig. 24.30).
Fig. 24.30. Home page settings for Administrator
Then let us test the script-based exchange.
Note. You have to specify the source and target nodes correctly. If data is modified in the central infobase, you have to select the target subordinate node (Department) from the list of exchange plan nodes and then click Write changes. And in the target node infobase you have to select the source node (Central infobase) and then click Read changes.
- Run 1C:Enterprise as Administrator.
This opens the applied solution home page (fig. 24.31).
Fig. 24.31. Home page of a user with Administrator role
- In the Quick menu section, on the Tools menu, click Departments exchange.
- In the Department field, select the Department node (fig. 24.32).
It is the node for which you will create an initial image.
Fig. 24.32. Example of script-based exchange with departments
- Click Create initial image.
- Create a directory for storing the initial image, select it in the directory selection dialog box, and click Select Folder.
- Create a new employee in the central infobase.
- In the Departments exchange form, in the Department field, select Department.
It is the node where you need to transfer the changes.
- Click Write changes and specify the name of the file where you want to store the changes.
- Open the department infobase (based on the initial image that you created in steps 4-5) in Designer.
- On the Administration menu, click Users and create a single user: Administrator with Administrator role.
- Open the department infobase in 1C:Enterprise mode.
- In the Quick menu section, in the Departments exchange form, in the Department field, select Central infobase.
It is the node whose changes you need to transfer to the current infobase.
- Click Read changes and specify the name of the file that stores the changes.
- Ensure that the new employee with a code having the CI prefix is present in the department infobase.
And now we will make a few final observations.
In a distributed infobase scenario four events become available for the ExchangePlanObject.<name>
You can use these events to manage sending and receiving data at the level of individual data items. They are called for each data item included in the message.
You can watch these events in action by adding the following script to the module of the Departments exchange plan object (listing 24.33).
Listing 24.33. Watching the execution of the ExchangePlanObject object events
Procedure OnSendDataToMaster(DataItem, ItemToSend) Message = New UserMessage; Message.Text = "OnSendDataToMaster: " + DataItem; Message.Message(); EndProcedure Procedure OnSendDataToSlave(DataItem, ItemToSend) Message = New UserMessage; Message.Text = "OnSendDataToSlave: " + DataItem; Message.Message(); EndProcedure Procedure OnReceiveDataFromMaster(DataItem, ItemToReceive, SendBack) Message = New UserMessage; Message.Text = "OnReceiveDataFromMaster: " + DataItem; Message.Message(); EndProcedure Procedure OnReceiveDataFromSlave(DataItem, ItemToReceive, SendBack) Message = New UserMessage; Message.Text = "OnReceiveDataFromSlave: " + DataItem; Message.Message(); EndProcedure
The first parameter in all of these events is the data item for which the event is called.
The ItemToSend parameter defines which data is stored to the message. It can have one of the three values:
- Auto. The data item is included in the message. It is the default value.
- Delete. A value indicating that the data item that should be deleted is included in the message.
- Ignore. No data related to the data item is included in the message.
The ItemToReceive parameter defines whether the read data item is recorded to the database. It can have one of the three values:
- Auto. If the data item is received from the master node, it is always recorded. If the data item is received from a subordinate node, it is only recorded if no changes are registered for that data item. It is the default value.
- Accept. A received data item is always recorded.
- Ignore. A received data item is ignored (so it is not recorded).
Data receipt events also have a third Boolean parameter: SendBack. This parameter enables forced registration of changes for the received item in the target infobase.
You might need this feature if an inconsistency is detected in the data received from the source node (for example, an error occurred during data modification in the source node).
If this is the case, you can ignore the received change and set the SendBack flag to force recording the changes of the received data items for the source node in the target infobase.
After the subsequent exchange, the state of that data item in the source node is taken from the target infobase.
Modifying distributed infobase node structure
In conclusion, we need to point out that the distributed infobase feature includes software tools for reconfiguring the node structure.
The SetMasterNode() method of the ExchangePlansManager object is used for this purpose.
A reference to the exchange plan node of a distributed infobase that becomes the master for the current infobase is passed as a method parameter. You can pass the Undefined value to indicate that the current infobase has no master node.
Suppose you need to move one of the subordinate nodes to the root (fig. 24.33).
Fig. 24.33. Reconfiguring node structure
To do so, you have to run the script shown in listing 24.34.
Listing 24.34. Moving Node2 to the tree root
// In the Node2 infobase ExchangePlansManager.SetMasterNode(Undefined); // In the Node1 infobase ExchangePlansManager.SetMasterNode(Node2);
This script deletes all the Node1 configuration change records for Node2 because after its execution the transfer of configuration changes is only allowed from Node2 to Node1. Data change records are not deleted because data exchange between these nodes is still allowed.
In a similar manner you can use the Undefined value of the method parameter to detach an individual infobase or a subtree from the tree structure (fig. 24.34, listing 24.35).
Fig. 24.34. Detaching a subtree from a distributed infobase
Listing 24.35. Detaching a subtree
// In the Node1 infobase ExchangePlansManager.SetMasterNode(Undefined);
In addition, you can assemble a distributed infobase from individual infobases with identical configurations (fig. 24.35, listing 24.36).
Fig. 24.35. Infobase composed of individual infobases with identical configurations
Listing 24.36. Assembling a distributed infobase from infobases with identical configurations
// In the infobases of Node2, Node3, and Node4 ExchangePlansManager.SetMasterNode(Node1);