1C:Enterprise 8.3. Developer Guide. Chapter 15. Data Exchange Mechanisms

1C:Enterprise 8.3. Developer Guide. Contents


DATA EXCHANGE MECHANISMS

15.1. GOALS AND OBJECTIVES

Data exchange mechanisms are a set of 1C:Enterprise tools used to arrange data exchange between different infobases and between infobases and external software systems. Data exchange mechanisms can be classified in two levels:

„ Universal data exchange mechanisms

„ Distributed infobases

15.1.1. Universal Data Exchange Mechanisms

Universal data exchange mechanisms can be used together, separately and in different combinations, to arrange data exchange between 1C:Enterprise infobases and other software systems. Other 1C:Enterprise infobases can serve as software systems to exchange data with. In this case infobases that exchange data can generally have different configurations.

Additionally universal data exchange mechanisms can be used to arrange exchanges with software systems that are not based on 1C:Enterprise. The following factors enable this:

„ Data exchange format based on the XML language is a generally accepted means of data representation today.

„ Data exchange tools can be used to arrange multiple data transfer schemas, due to their modular organization and flexibility.

„ Protocols established by the data exchange mechanisms are not complex and can be reproduced in external software systems.

15.1.2. Distributed Infobases

A distributed infobase has a hierarchical structure, consisting of separate 1C:Enterprise infobase nodes that exchange data in order to synchronize configurations and data.

Control mechanisms developed to manage distributed infobases are based on universal data exchange mechanisms, but allow some additional possibilities not accessible through universal mechanisms.

The main difference between distributed infobases and universal data exchange mechanisms is that universal mechanisms allow the construction of open data exchange schemas, whereas distributed infobases are designed with a narrower purpose and a task of configuration change transfer to child nodes.

15.2. UNIVERSAL DATA EXCHANGE MECHANISMS

The following can be classified as universal mechanisms:

„ XML documents read and write tools

„ XML-serialization

„ Exchange plans

15.2.1. XML Documents Read and Write Tools

Data exchange participants are expected to communicate in XML format. This way, reading and writing XML becomes the basis for data exchange.

Tools for reading and writing XML documents give you broad leverage in working with XML documents. This set of tools does not provide the means to represent 1C:Enterprise data in XML format.

1C:Enterprise has the following objects for reading and writing XML documents: XMLReader, XMLWriter and XSLTransform. The platform also enables operations with XML data in FastInfoset format by means of FastInfosetReader and FastInfosetWriter objects.

15.2.2. XML Serialization

The main task of XML-serialization is to support the reading and writing of 1C:Enterprise data objects to and from XML.

The basic tools for reading and writing XML do not provide a sufficient foundation for this task. They do not define 1C:Enterprise data presentation formats in XML and do not allow you to read/write data objects to or from XML in an accepted format.

15.2.2.1. Data Presentation in XML-Serialization

In its final state, each 1C:Enterprise data object is represented as an XML item containing the value of the data object.

In terms of XML representation, value types can be classified as simple or complex.

Simple data types have values represented by the XML-serialization subsystem as text-only XML items.

The values for complex types are represented as XML items containing nested items.

An XML data type is assigned to each corresponding 1C:Enterprise data type with values that can be represented in XML.

Each XML data type is characterized by the type name and the associated namespace.

The XML data type can be:

„ One of the types defined in the "XML Schema Part 2: Datatypes" document from the W3C consortium (namespace: http://www.w3.org/2001/XMLSchema);

„ A predefined 1C:Enterprise type (namespace: http://v8.1c.ru/data);

„ A type produced by 1C:Enterprise configuration metadata (not associated with any namespace).

The XML data type can be expressly set in a data object XML-representation. To set the XML data type, the XML item containing the value representation must contain the type attribute associated with the http://www.w3.org/2001/XMLSchemainstance namespace, whose value is stored in the XML data type.

Another possible way to set the XML data type is using the name of the XML root item containing the value representation. The root item representing the data object need not be specified and can be arbitrary. However, if the root item name is not specified when writing values in XML, then it is assigned according to the type of value recorded. When reading data from XML, the value type can be assigned by the root item name if it is not specified in the type attribute.

In reviewing examples of different XML value representations and in subsequent sections, we will use the following namespace equalities:

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:v8="http://v8.1c.ru/data"

Representation of Simple Type Values in XML

The following 1C:Enterprise types are considered simple from an XML representation standpoint:

„ Number

„ String

„ Date

„ Boolean

„ BinaryData

„ NULL „ UUID

„ ValueStorage

„ All references to database objects

„ References to enumerations, defined in metadata

Number

Description:

The XML decimal data type from the http://www.w3.org/2001/XMLSchema namespace corresponds to the Number type.

Rules for representing values of this type are defined in the "XML Schema Part 2: Datatypes" document.

Example:

<!--  No explicit setting of root item name -->
<decimal>45684.087</decimal>
<!--  Explicit setting of XML root item name -->
<Amount>523</Amount>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="xsd:decimal">64793.01</Data>

String

Description:

The string data type from the http://www.w3.org/2001/XMLSchema namespace corresponds to the String type. String is recorded in XML as is.

Example:

<!--  No explicit setting of root item name -->
<string>This  is a string</string>
<!--  Explicit setting of XML root item name -->
<Name>Jones</Name>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="xsd:string">This is a string</Data>

Date

Description:

Date-type values are represented as YYYY-MM-DDTHH:MM:SS, where:

„ YYYY is the year in four digits;

„ MM is the month in two digits;

„ DD is the day of the month in two digits;

„ T is the letter T;

„ HH is the hour (on a 24-hour clock);

„ MM is the minutes; „ SS is the seconds.

This is an acceptable format according to the "XML Schema Part 2: Datatypes" document.

Example:

<!--  No explicit setting of root item name -->
<dateTime>2008-11-21T12:00:00</dateTime>
<!--  Explicit setting of XML root item name -->
<Started>2001-10-30T19:00:00</Started>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="xsd:dateTime">1980-08-25T10:00:00</Data>

Boolean

Description:

The boolean data type from the http://www.w3.org/2001/XMLSchema namespace corresponds to the Boolean type.

The False value is represented by the false string and the True value is represented by the true string. This format is provided in the "XML Schema Part 2: Datatypes" document.

Example:

<!--  No explicit setting of root item name -->
<boolean>false</boolean>
<!--  Explicit setting of XML root item name -->
<Posted>true</Posted>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="xsd:boolean">true</Data>

BinaryData

Description:

The XML base64Binary data type from the http://www.w3.org/2001/XMLSchema namespace corresponds to the BinaryData type.

Values of this type are represented as binary data, encoded using the Base64 algorithm, described in RFC 2045 (http://www.faqs.org/rfcs/rfc2045.html).

Example:

<!--  No explicit setting of root item name -->
<base64Binary>YWJjZGVm</base64Binary>
<!--  Explicit setting of XML root item name -->
<BinaryData>YWJjZGVm</BinaryData>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="xsd:base64Binary">YWJjZGVm</Data>

NULL

Description:

The XML Null data type from the http://v8.1c.ru/data namespace corresponds to the NULL type. This type has a single value, represented by an empty string.

Example:

<!--  No explicit setting of root item name -->
<v8:Null/>
<!--  Explicit setting of XML root item name -->
<Selected/>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="v8:Null"/>

UUID

Description:

The XML UUID data type from the http://v8.1c.ru/data namespace corresponds to the UUID type.

Values of this type are represented in XML according to generally accepted practice and standards (ISO-11578, DCE 1.1: Remote Procedure Call – Universal Unique Identifier).

Example:

<!--  No explicit setting of root item name -->
<v8:UUID>3294be0f-c039-41a9-bd65-596da0dcfe68</v8:UUID>
<!--  Explicit setting of XML root item name -->
<Id>da035e32-3f7a-4d87-accf7db8cb4b</Id>
<!--  Explicit setting of XML data type ->
<Data  xsi:type="v8:UUID">08839b0b-5ec3-4a53-a9f5-173312316919</Data>

ValueStorage

Description:

The XML ValueStorage data type from the http://v8.1c.ru/data namespace corresponds to the ValueStorage type.

Values of this type are represented in XML as ValueStorage, saved to file and then encoded using the Base64 algorithm.

Example:

<!--  No explicit setting of root item name -->
<v8:ValueStorage>AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</v8:ValueStorage>
<!--  Explicit setting of XML root item name -->
<Data>AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</Data>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="v8:ValueStorage">AQEOAAAAAAAAAO+7v3siUyIsIjHQoSJ9</Data>

References to Database Objects

Description:

Each type of reference to database objects has its own corresponding XML data type. The name of the XML data type for references to database objects corresponds to the name of the 1C:Enterprise reference value type in English.

For example, in the Currency catalog, the English name of the reference type is CatalogRef.Currencies. The name of the XML data type is identical to it.

XML data types for references to database objects are not associated with any namespace.

Reference values are represented in XML as UUID type values, obtained from the references.

Example:

<!--  No explicit setting of root item name -->
<CatalogRef.Banks>911b5b8b-11f5-4993-9673-2c9a7a8995d5</CatalogRef.Banks  >
<!--  Explicit setting of XML root item name -->
<Ref>911b5b8b-11f5-4993-9673-2c9a7a8995d5</Ref>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="CatalogRef.Banks">911b5b8b-11f5-4993-9673-2c9a7a8995d5</Data>

References to Enumerations Defined in Metadata

Description:

Each type of reference to enumeration values defined in the configuration has its own corresponding XML data type. The XML data type name for references to enumeration values corresponds to the name of the 1C:Enterprise type in English.

For example, in the AddressTypes catalog, the English name of the value reference type is EnumRef.AddressTypes. The name of the XML data type is identical to it.

XML data types for references to enumeration values are not associated with any namespace. In XML, references to enumeration values are represented as names corresponding to enumeration values.

Example:

<!--  No explicit setting of root item name -->
<EnumRef.AddressTypes>Legal</EnumRef.AddressTypes>
<!--  Explicit setting of XML root item name -->
<Ref>Legal</Ref>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="EnumRef.AddressTypes">Actual</Data>

Representation of Complex Type Values in XML

The following 1C:Enterprise types that can be represented in XML are classified as complex.

„ Type

„ TypeDescription

„ ConstantValueManager.<Constant name>

„ All database objects

„ Sets of register records, sequences and recalculations

„ ObjectDeletion

Type

Description:

The XML Type data type from the http://v8.1c.ru/data namespace corresponds to the Type type. The XML item representing a value of this type contains text providing the name of the XML type corresponding to the 1C:Enterprise data type.

At first glance, Type appears to be a simple data type rather than complex, since the item representing the value of this type does not contain nested items. However, this is not the case. There really are no nested items. However, the item text containing the name of the XML data type, contains the prefix for the type namespace which must be defined in this item or in one of the parent items, making the item text not entirely self-sufficient. Therefore, this type is not considered simple.

Example:

<!--  No explicit setting of root item name -->
<v8:Type>v8:ValueStorage</v8:Type>
<!--  Explicit setting of XML root item name -->
<Tp>xsd:string</Tp>
<!--  Explicit setting of XML data type-->
<Data  xsi:type="v8:Type">v8:ValueStorage<Data>

TypeDescription

Description:

The XML TypeDescription data type from the http://v8.1c.ru/data namespace corresponds to the TypeDescription type. The root item representing the TypeDescription type value, includes a set of nested items, each containing a component of the type description.

The nested Types item from the http://v8.1c.ru/data namespace represents separate types entered into the type description. The NumberQualifiers item from the http://v8.1c.ru/data namespace contains qualifiers for numerical values. The StringQualifiers and DateQualifiers items from the same namespace contain qualifiers for string and date, respectively.

Example:

<v8:TypeDescription>
<v8:Types>
<v8:Type>v8:UUID</v8:Type>
<v8:Type>CatalogRef.Banks</v8:Type>
<v8:Type>xsd:boolean</v8:Type>
<v8:Type>xsd:boolean</v8:Type>
</v8:Types>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
<v8:StringQualifiers>
<v8:Length>30</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
<v8:DateQualifiers>
<v8:DateFractions>Date</v8:DateFractions>
</v8:DateQualifiers>
</v8:TypeDescription>

ConstantValueManager.<Constant name>

Description:

Each of the ConstantValueManager.<Constant name> types has a corresponding XML data type (ConstantValueManager.<Constant name>), not associated with any namespace.

Example:

<ConstantValueManager.OrganizationName>
<Value>Mobius  LLC</Value>
</ConstantValueManager.OrganizationName>

Database Objects

Description:

Database objects are represented in XML as a combination of attribute values and tabular sections. The name of the XML data type corresponding to the database object is defined as the name of the 1C:Enterprise value type in English. XML data types for database objects are not associated with any namespace. The list of XML items nested in the root item is defined by the type of object as well as the list of attributes and tabular sections.

Each attribute is represented by an XML item, whose name corresponds to the name of the attribute. If the attribute value type cannot be defined from the metadata, then the XML item representing the attribute contains the xsi:type attribute which indicates the XML value type.

Each tabular section is represented by an XML item with a corresponding name.

Each row from the tabular section is represented by an XML item named Row.

Tabular section attributes are represented by XML items nested in the Row item.

Example:

XML representation for a Document.CustomerOrder object:

<DocumentObject.CustomerOrder>
<Ref>8d106783-9726-11d7-9334-0050ba8480bd</Ref>
<DeletionMark>false</DeletionMark>
<Date>2008-04-15T12:00:00</Date>
<Number>00000006</Number>
<Posted>true</Posted>
<CompanySubdivision>
317f130d-5a08-11d7-9324-0050ba8480bd</CompanySubdivision>
<OperationalUnit  xsi:type="CatalogRef.CompanyCashRegisters">
317f12f4-5a08-11d7-9324-0050ba8480bd</OperationalUnit>
<Contractor>12952ac7-5a08-11d7-9324-0050ba8480bd</Contractor>
<ContractorLegalEntityPerson  xsi:type="CatalogRef.LegalEntities">
0aadfe81-5a08-11d7-9324-0050ba8480bd</ContractorLegalEntityPerson>
<DocumentCurrency>
029156b4-5a08-11d7-9324-0050ba8480bd</DocumentCurrency>
<DocumentRate>1</DocumentRate>
<AccountForVAT>true</AccountForVAT>
<AccountForIT>true</AccountForIT>
<AmountInclVAT>false</AmountInclVAT>
<AmountInclIT>false</AmountInclIT>
<Comment/>
<DocumentAmount>44077.14</DocumentAmount>
<OperationType>InvoiceForPayment</OperationType>
<SettlementAgreement>
b0401f23-6e84-11d7-932c-0050ba8480bd</SettlementAgreement>
<CompanyWarehouse>
317f1317-5a08-11d7-9324-0050ba8480bd</CompanyWarehouse>
<PriceType>317f1311-5a08-11d7-9324-0050ba8480bd</PriceType>
<PaymentDate>2008-04-15T00:00:00</PaymentDate>
<AutoReserve>false</AutoReserve>
<AutoPlacement>false</AutoPlacement>
<SettlementRate>33.4209</SettlementRate>
<DiscountExtraChargeType>
00000000-0000-0000-0000-000000000000</DiscountExtraChargeType>
<Organization>317f1308-5a08-11d7-9324-0050ba8480bd</Organization>
<ShipmentDate>2008-04-15T00:00:00</ShipmentDate>
<Responsible>
4ff40e0b-5ac5-11d7-9325-0050ba8480bd</Responsible>
<DocumentFrequency>1</DocumentFrequency>
<SettlementFrequency>1</SettlementFrequency>
<Goods>
<Row>
<Nomenclature>
297c6534-5a08-11d7-9324-0050ba8480bd</Nomenclature>
<UnitOfMeasure>
297c6535-5a08-11d7-9324-0050ba8480bd
</UnitOfMeasure>
<Price>4537.56</Price>
<Sum>13612.68</Sum>
<VATRate>VAT20</VATRate>
<VATSum>2722.54</VATSum>
<ITRate>1ac73736-5a08-11d7-9324-0050ba8480bd</ITRate>
<ITSum>0</ITSum>
<NomenclatureCharacteristic>
00000000-0000-0000-0000-000000000000
</NomenclatureCharacteristic>
<Placement  xsi:nil="true"/>
<Factor>1</Factor>
<Count>3</Count>
<DiscountExtraChargePercent>0</DiscountExtraChargePercent>
</Row>
<Row>
<Nomenclature>
317f12d8-5a08-11d7-9324-0050ba8480bd</Nomenclature>
<UnitOfMeasure>
317f12d9-5a08-11d7-9324-0050ba8480bd
</UnitOfMeasure>
<Price>4915.55</Price>
<Sum>19662.2</Sum>
<VATRate>VAT20</VATRate>
<VATSum>3932.44</VATSum>
<ITRate>1ac73736-5a08-11d7-9324-0050ba8480bd</ITRate>
<ITSum>0</ITSum>
<NomenclatureCharacteristic>
00000000-0000-0000-0000-000000000000
</NomenclatureCharacteristic>
<Placement  xsi:nil="true"/>
<Factor>1</Factor>
<Count>4</Count>
<DiscountExtraChargePercent>0</DiscountExtraChargePercent>
</Row>
</Goods>
<Returnables/>
</DocumentObject.CustomerOrder>

NOTE

This example and others given in this chapter use long strings (e.g.,

<UnitOfMeasure>317f12d9-5a08-11d7-9324-0050ba8480bd</UnitOfMeasure>). Due to book format limitations, these strings are wrapped to the next line(s). In practice, these strings are each written on a single line.

Record Set

Description:

The XML representation of a record set includes the filter used to retrieve the record set and the records. Filter values represented in the nested XML item named Filter are not associated with any namespace. All records comprising a set of records are represented in the nested Records item that is also not associated with any namespace. Records are represented by Record XML items nested in the Records item. The name of the Record item is also not associated with any namespace.

Example:

Below is an XML representation for a record set of the CompanyProductInventory accumulation register:

<AccumulationRegisterRecordSet.CompanyProductInventory>
<Filter>
<Recorder  xsi:type="DocumentRef.Goodsales">
1725f36e-6f35-11d7-932d-0050ba8480bd</Recorder>
</Filter>
<Records>
<Record>
<Recorder  xsi:type="DocumentRef.Goodsales">
1725f36e-6f35-11d7-932d-0050ba8480bd</Recorder>
<Period>2008-04-13T17:45:39</Period>
<MovementType>Expense</MovementType>
<Active>true</Active>
<Nomenclature>
297c6556-5a08-11d7-9324-0050ba8480bd</Nomenclature>
<CompanyWarehouse>
317f1317-5a08-11d7-9324-0050ba8480bd</CompanyWarehouse>
<Order  xsi:nil="true"/>
<RetailPrice>0</RetailPrice>
<NomenclatureCharacteristic>
00000000-0000-0000-0000-000000000000
</NomenclatureCharacteristic>
<Count>2</Count>
<CompanySubdivision>
317f130d-5a08-11d7-9324-0050ba8480bd
</CompanySubdivision>
</Record>
<Record>
<Recorder  xsi:type="DocumentRef.Goodsales">
1725f36e-6f35-11d7-932d-0050ba8480bd</Recorder>
<Period>2008-04-13T17:45:39</Period>
<MovementType>Expense</MovementType>
<Active>true</Active>
<Nomenclature>
297c6558-5a08-11d7-9324-0050ba8480bd</Nomenclature>
<CompanyWarehouse>
317f1317-5a08-11d7-9324-0050ba8480bd</CompanyWarehouse>
<Order  xsi:nil="true"/>
<RetailPrice>0</RetailPrice>
<NomenclatureCharacteristic>
ac47d77e-5ec7-11d7-9329-0050ba8480bd
</NomenclatureCharacteristic>
<Count>2</Count>
<CompanySubdivision>
317f130d-5a08-11d7-9324-0050ba8480bd
</CompanySubdivision>
</Record>
</Records>
</AccumulationRegisterRecordSet.CompanyProductInventory>

ObjectDeletion

Description:

The XML ObjectDeletion data type from the http://v8.1c.ru/data namespace corresponds to the ObjectDeletion type. The root item of the XML-representation for the ObjectDeletion type value contains a nested Ref item from the http://v8.1c.ru/data namespace which contains a presentation of a database object reference.

Example:

Below is an example of XML representation of an ObjectDeletion object:

<v8:ObjectDeletion  xmlns="http://v8.1c.ru/data">
<v8:Ref  xsi:type="CatalogRef.Banks">
60c5cec3-7f6f-4ec3-9620-e757fe3614ca</v8:Ref>
</v8:ObjectDeletion>

15.2.2.2. Access to XML-Serialization Tools From 1C:Enterprise Script

Two global methods are used for working with XML representations of simple type values: XMLString() and XMLValue().

The XMLString() method has one parameter – the value for which XML representation is needed. This value must be a simple type in XML serialization terms. Otherwise an exception is raised. If complete successfully, the function returns a string that can be used as XML item text representing simple type values.

The XMLValue() method performs the opposite task. This method has two parameters:

„ The value type to be received from the string

„ The string itself

To convert a 1C:Enterprise data type into an XML data type and vice versa, use XMLType() and FromXMLType() methods. The XMLType() method has one parameter – the type for which the corresponding XML data type is needed.

If the corresponding XML data type is defined, then the method returns the XMLDataType value. If there is no corresponding XML data type, then the method returns the Undefined value.

The FromXMLType() method has two call variants. In the first variant, the method has a single XMLDataType parameter. The second option has two parameters: the XML type name and the namespace. In both cases, this method returns the 1C:Enterprise data type to the corresponding XML data type, if available; otherwise it returns the Undefined value.

Two global methods can be used to read and write various values to and from XML: WriteXML() and ReadXML().

The WriteXML() method has two required parameters. The first parameter is the XMLWriter type object used to write XML, while the second is the value which needs to be written in XML. Optional parameters make up three different variants for calling this method.

In the simplest case, there are three parameters and the third parameter specifies the XMLTypeAssignment enumeration value and creates the need to specify the XML data type explicitly in the xsi:type attribute of the XML root item.

The next variant uses a string value as the third parameter, indicating the name of the XML root item. This implies that the namespace is not defined. The fourth parameter is a XMLTypeAssignment value that requires explicit setting of the XML data type.

Finally, the last variant includes, after the parameter for the XML root item name, an additional parameter – a string value indicating the namespace associated with the root item. The last parameter still has the XMLTypeAssignment type.

...
Val  = "A string";
WriteXML(Wr,  Val);
WriteXML(Wr,  Val, "Root", XMLTypeAssignment.Explicit);
WriteXML(Wr,  Val, "Root", "urn:some-namespace");
...

The code above results in the following XML fragment:

...
<string>A  string</string>
<Root  xsi:type="xsd:string">A string</Root>
<d1p1:Root  xmlns:d1p1="urn:some-namespace">A string</d1p1:Root>
...

If a type value that cannot be represented in XML is passed as a value to be placed in XML, an exception is raised.

The ReadXML() method can be used to read values from XML. This method has one required parameter, the XMLReader object, from which the value must be read. A value type that needs to be read from XML can be specified as the second parameter. If the value type is explicitly assigned in XML, then Undefined can be used as the second parameter or it can be omitted altogether. In this case the ReadXML() method attempts to define the type of value being read based on the xsi:type attribute or, if the xsi:type attribute is missing, based on the item name. If you cannot successfully establish the type or the value of the specified type cannot be read from XML, an exception is raised. Upon successful completion the ReadXML() method returns the value it has read.

Please note how constant value managers, database objects and record sets are read. A successful reading using the ReadXML() method returns the value read from XML, but this value has not yet been recorded in the database. If, for example, a catalog item has been read, then in order to record the it in the database the Write() method has to be used, just like when "standard" modified objects are recorded. It also applies to other database objects, constant record managers and record sets.

When reading a database object from XML, objects with the same reference value are searched for. If such an object is found, its reading from XML looks like it has been read from the database; then the values of its attributes, tabular sections, etc. are replaced with values received from XML. If the object is not found by reference, reading from XML looks like creating a new object, specifying reference values and filling it with values read from XML.

The CanReadXML() method defines whether it is possible to read a value from the XMLReader object located in the current position of the XML document. The XMLReader object is passed to this method as a parameter. If the method returns True, reading is possible; if False is returned, the value cannot be read.

The GetXMLType() method can be used to retrieve the XML data type corresponding to the current XML document position from the XMLReader object. This method also has one parameter – XMLReader.

15.2.3. Exchange Plans

Exchange plans constitute a center around which other data exchange tools are grouped. Any number of exchange plans can be defined in a single configuration. Each exchange plan defines the set of data for which the exchange is planned. With this data set, specific data presentation formats can also be defined.

Data formats are intended to be based on XML, but because of the flexibility of the XML language and availability of different tools for working with XML in 1C:Enterprise, you can be creative in presenting data. In exchange plans, two important components can be singled out:

„ Message infrastructure

„ Change registration service

Exchange plan data items are called exchange plan nodes. This is similar to a catalog structure where catalog data items are catalog items. Each exchange plan node designates a data transfer participant for a particular exchange plan. One of the nodes corresponds to the infobase and the rest correspond to other participants with which this infobase can exchange.

Data are transferred between nodes through messages. The tools for working with messages constitute the message infrastructure. Each message is associated with a specific exchange plan and has a defined sender node and recipient node. A message cannot be sent to or received from an unknown node. Each message has its own (integer) number.

Change registration service is used to register data changes effected by 1C:Enterprise in order to provide the opportunity of transferring just the changes and not all the data during data exchange.

Therefore, exchange plans define the set of tools used to organize data exchange. We will review these tools in more detail.

15.2.3.1. Exchange Plan Nodes

When creating a new exchange plan, one node is automatically created – this is a node or an exchange plan node which corresponds to a particular infobase. All the other nodes that are available to the current node for data exchange are not automatically created as part of an exchange plan.

A unique code must be defined for each node to identify it during data exchange.

Node codes are specified for the exchanging parties to "recognize" each other.

NOTE

An exchange plan must contain the code and the name. In other words, you cannot set the length equal to 0 for the exchange plan’s standard attributes (Code and Name).

Suppose it is necessary to organize data exchange between two infobases using the RemoteWarehouses exchange plan. One of these infobases carries out the functions of a central office and the other acts as a remote warehouse.

In this case you would need to enter Office in the first infobase as the code value for this node of the RemoteWarehouses exchange plan (if the code length permits, of course) and Warehouse1 in the second infobase. Thus, these nodes are assigned names. But this is not enough; data exchange destination nodes need to be entered. To accomplish this, a Warehouse1 node needs to be created in the RemoteWarehouses exchange plan in the first infobase and an Office node – in the second infobase.

Thus, the first infobase "knows" that it is named Office in the RemoteWarehouses exchange plan and is to exchange data with the Warehouse1 node; the second infobase, on the other hand, knows that it is named Warehouse1 and is to exchange data with the Office node.

15.2.3.2. Message Infrastructure

The most important component of the message infrastructure is the message itself. As was already noted, messages are sent from one node to another within an exchange plan. Each message follows the exchange plan exactly and has one sender and one recipient.

We will go over what this message entails. The message is laid out as an XML document with a defined structure. We will use the following message as an example:

<v8msg:Message  xmlns:v8msg="http://v8.1c.ru/messages">
<v8msg:Header>
<v8msg:ExchangePlan>RemoteWarehouses</v8msg:ExchangePlan>
<v8msg:To>Warehouse1</v8msg:To>
<v8msg:From>Office</v8msg:From>
<v8msg:MessageNo>20</v8msg:MessageNo>
<v8msg:ReceivedNo>15</v8msg:ReceivedNo>
</v8msg:Header>
<v8msg:Body>
<!– Message body -->
</v8msg:Body>
</v8msg:Message>

The entire message is located within the Message XML item that belongs to the http://v8.1c.ru/messages namespace. The message is divided into a header and a body. Accordingly, the Message item contains two nested elements: Header and Body. Both of them are associated with the "http://v8.1c.ru/messages" namespace.

The Header item contains the message header. The header's structure is hardcoded. Header information is represented in several XML items nested in the Header item. All items nested in the Header item are belong to the http://v8.1c.ru/messages namespace.

„ ExchangePlan contains the name of the exchange plan with which the message is associated.

„ To contains the code of the sender node.

„ From contains the code of the destination node.

„ MessageNo contains the number of the message. The message number is a positive integer number assigned by the sender node. The number of each subsequent message is the number of the preceding message incremented by 1.

„ ReceivedNo contains the highest message number that the sender node of the message has received from the recipient node. This value is included in the message header to confirm receipt of the message.

The body of the message is contained in the Body XML item which is associated with the http://v8.1c.ru/messages namespace. The item's content is arbitrary and depends on the application requirements. The message infrastructure does not regulate the message body in any way.

15.2.3.3. Change Registration Service

The purpose of change registration is compiling a list of modified data items. These items are to be transferred to the data exchange destination node in the next message. With each data change, it must be recorded that there are changes to be transferred to all nodes that support the exchange of these data. After receipt of the message containing the changes is confirmed, change registration records are deleted.

Change registration is supported for the following data items:

„ ConstantValueManager.<Constant name>

„ Database objects:

     CatalogObject.<Catalog name>

DocumentObject.<Document name>

ChartOfAccountsObject.<Chart of Accounts name>

ChartOfCharacteristicTypesObject.<Chart of characteristic types name>

ChartOfCalculationTypesObject.<Chart of calculation types name>

BusinessProcessObject.<Business process name>

TaskObject.<Task name>

„ Record sets:

     InformationRegisterRecordSet.<Information register name>

AccountingRegisterRecordSet.<Accounting register name>

AccumulationRegisterRecordSet.<Accumulation register name>

SequenceRecordSet.<Sequence name>

CalculationRegisterRecordSet.<Calculation register name>

RecalculationRecordSet.<Recalculation name>

Each data item has its own change registration table. The tables have different structures depending on which data items the changes are registered for, but all table structures are similar. The structure can be divided into three components:

„ The key of the data item for which changes are registered.

„ The reference to the node to which the change is to be transferred.

„ The number of the message in which the change is first transferred.

The structures of change registration tables for different data have different keys, since keys for various data differ:

„ A constant ID is used as the key for constants.

„ A reference to the object is used as the key for database objects.

„ A reference to the recorder object is used as the key for record sets with a defined recorder.

„ If a recorder is not defined for an information register record set, then a combination of dimensions from the main filter is used as the key. If the information register is periodical and the main filter by period is enabled, then the period is also included in the key.

When a data item is modified, this change must be registered for all nodes to which it is to be transferred. Thus, a data item change must result in N records in the change registration table, where N is the number of nodes for which changes are registered. All records contain the same data item key value and different references to nodes.

Immediately after change registration, the message number reads NULL. When the change is first sent, the number for this message is entered into this field.

When configuring the exchange plan, you must define the content of the exchange plan. Metadata objects are included in the exchange plan content. Entering metadata objects into the exchange plan content shows that data changes corresponding to the metadata object can be registered for the node of this exchange plan. If a metadata object is not in any of the exchange plans, then a change registration table is not created for the object and data change registration does not take place.

The AutoRecord property specifies how metadata objects are entered into the exchange plan. Auto-record can be enabled or disabled. If auto-record is enabled, data change registration is automatic. If it is disabled, change registration can be completed manually.

15.2.3.4. Access to Exchange Plan Mechanisms Using 1C:Enterprise Script

The 1C:Enterprise script offers a set of objects for working with exchange plans.

The ExchangePlansManager object, besides its standard manager functionalities, provides methods for working with the change registration service: RecordChanges(), DeleteChangeRecords(), IsChangeRecorded() and SelectChanges(), as well as methods for creating message reader and writer objects: CreateMessageReader() and CreateMessageWriter().

The most important feature of the ExchangePlanManager.<Exchange plan name> is the ThisNode() method which returns a reference to the node of this exchange plan corresponding to a particular infobase.

ExchangePlanManager.<Exchange plan name> corresponds to the exchange plan node. The SentNo and ReceivedNo properties are described in more detail. The SentNo property contains the number of the last message sent from the infobase to the node corresponding to the ExchangePlanManager.<Exchange plan name> object. The ReceivedNo property contains the highest message number of the messages received by the infobase from the node corresponding to the ExchangePlanManager.<Exchange plan name> object.

Change Registration

As already noted, changes can be registered automatically when a data item is recorded or deleted. Let us review how it is accomplished. Each object whose changes can be recorded by the exchange plan has the DataExchange property with the DataExchangeParameters type. This property can be used only for reading only; it is intended for managing different parameters in data exchanges.

The DataExchangeParameters object has the Recipients property with the NodeSet type. This property stores a list of nodes for which changes are recorded upon data write or delete operations. The list of recipients is automatically filled before either the BeforeWrite() handler (for data writing) or BeforeDelete() handler (for deletion) is invoked. However, auto-fill only takes place if the AutoFill property of the NodeSet object reads True (True is default for the AutoFill property). Auto-filling includes references to all nodes of all exchange plans with the corresponding metadata object in the recipient list provided that the AutoRecord property is set to Enable. It goes without saying that the nodes corresponding to the infobase are not placed on the recipient list. The recipient list is cleared before auto-filling.

In the BeforeWrite() (and/or BeforeDelete()) handler, you can make changes to the recipient list: add or remove node references. However, keep in mind that the recipient list can only contain references to nodes associated with the exchange plans containing the corresponding metadata object.

In the example below, the BeforeWrite() handler excludes a Special node of the RemoteWarehouses exchange plan from the recipient list.

Procedure  BeforeWrite()
Node =  ExchangePlans.RemoteWarehouses.FindByCode("Special");
DataExchange.Recipients.Delete(Node);
EndProcedure

By assigning False to the AutoFill property, you can disable auto-filling for the recipient list. In this case the recipient list can be managed both in the BeforeWrite() handler and in any code fragment, as shown in the example:

Object  = Ref.GetObject();
Node  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
Object.DataExchange.Recipients.AutoFill  = False;
Object.DataExchange.Recipients.Add(Node);
Object.Write();

The ExchangePlansManager object contains a variety of tools for recording changes. First of all, it has the RecordChanges() method. This method allows you to record changes of single data items or entire groups for one or more nodes. The first parameter of this method is a reference to the exchange plan node or an array of references to nodes for which changes are recorded. If the first parameter is a single node reference, then the second parameter can be omitted. In this case change recording takes place for all data items currently existing in the database and supporting change registration for the node.

This can be useful for organizing initial data transmissions to newly created nodes.

Node  = ExchangePlans.RemoteWarehouses.FindByCode("New");
ExchangePlans.RecordChanges(Node);

If the first parameter is an array of references to nodes, then the second parameter must be specified. However, the second parameter can still be used if the first parameter is a single node reference. Depending on how the second parameter is set, changes can be recorded for one data item or all data related to one metadata object.

To record changes for a single item, you can use the data item itself, a reference to the database object or an ObjectDeletion object as the second parameter.

If a data item is indicated, then its change is recorded. If a database object reference is indicated, then the change to this object is registered.

If the second parameter has the ObjectDeletion type, then changes are registered for the database object referred to by ObjectDeletion.

Nodes  = New Array(2);
Nodes[0]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
Nodes[1]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse2");
Data  = Catalogs.Nomenclature.FindByCode("KL00127");
ExchangePlans.RecordChanges(Nodes,  Data);

To record changes for all data related to a metadata object, the corresponding metadata object must be specified as the second parameter.

Nodes  = New Array(2);
Nodes[0]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
Nodes[1]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse2");
ExchangePlans.RecordChanges(Nodes,  Metadata.Catalogs.Nomenclature);

To remove change registration records, ExchangePlansManager has the DeleteChangeRecords() method. It can be used to delete change registration records for all data registered for the node.

Node  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
ExchangePlans.DeleteChangeRecords(Node);

Change registration records can be deleted for a specific data item for one or more nodes.

Nodes  = New Array(2);
Nodes[0]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
Nodes[1]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse2");
Data  = Catalogs.Nomenclature.FindByCode("KL00127");
ExchangePlans.DeleteChangeRecords(Nodes,  Data);

Change registration records can also be deleted for all data related to a metadata object for one or more nodes.

Nodes  = New Array(2);
Nodes[0]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse1");
Nodes[1]  = ExchangePlans.RemoteWarehouses.FindByCode("Warehouse2");
ExchangePlans.DeleteChangeRecords(Nodes,  Metadata.Catalogs.Nomenclature);

In addition, if a single node is used as the first parameter, then the message number can be used as the second parameter. In this case the DeleteChangeRecords() method deletes all records associated with the indicated nodes from the change registration table if their message number is less than or equal to the second parameter value (but not NULL). This method is used for deleting change registration records for which change receipt has been confirmed by the node specified in the first parameter.

To check whether a data item change for a node has been recorded, use the IsChangeRecorded() method. The first parameter of this method is a reference to the node and the second parameter is the Data item, a reference to the database object or ObjectDeletion.

Writing Data Exchange Messages

The ExchangeMessageWriter object is used for writing messages.

The ExchangeMessageWriter object is created using the CreateMessageWriter() method of the ExchangePlansManager object.

The ExchangeMessageWriter object has three methods:

„ BeginWrite()

„ EndWrite()

„ CancelWrite()

The BeginWrite() method has two parameters: the XMLWriter object used to write the message and a reference to the message destination node. The BeginWrite() method calculates the message number by adding 1 to the previous message number and writes the beginning of the XML item containing the entire message, the entire message header and the beginning of the XML item containing the message body. After this you can begin writing the content of the message body.

To successfully complete the message write operation, use the EndWrite() method. This method writes the end of the XML item containing the message body and the end of the XML item containing the entire message. After the XML items that complete the message are successfully recorded, the message is considered submitted and its number is saved as the number of the last message sent from this node to recipient node.

If the message writing operation has to be aborted and the message must not be considered submitted, use the CancelWrite() method.

Below is a typical code fragment which writes a data exchange message.

XMLWriter  = New XMLWriter();
XMLWriter.OpenFile(MessageFileName);
Node  = ExchangePlans.RemoteWarehouses.FindByCode(NodeCode);
MessageWriter  = ExchangePlans.CreateMessageWriter();
MessageWriter.BeginWrite(XMLWriter,  Node);
//  Writing the message body
MessageWriter.EndWrite();

The message body can contain any data represented in XML, depending on the format used for a particular exchange plan. Below is an example of a message containing data with changes registered by the change registration service. To accomplish this, select the registered changes, tab through them and include the XML representations of the data changes in the message.

The SelectChanges() method of the ExchangePlansManager object is used to select changes. This method has two parameters: a reference to the node for which the change is selected and the number of the message into which the changes must entered. The SelectChanges() method returns a ChoiceData object which contains the keys of the data with changes registered for the node passed as the first parameter. Additionally the SelectChanges() method enters the message number passed as the second parameter into the corresponding fields of the selected change registration table records if these fields contain the NULL value.

If the change was already selected in the last cycle, then the message number in the corresponding record of the change registration table is not modified; however, if the change has not yet been selected, the system saves the number of the first message with the selected changes.

To tab through change selections, use Next() and Get() methods. When the Next() method is called, the next key in the selection comes up. The first time the Next() method is called, the first key comes up. When the Get() method is invoked, a data item corresponding to the current selection key is selected from the database. Here it is worth making a separate comment on deleted database objects. If a database object change was recorded as a result of deletion, then the Get() method does not return the database object, but rather an ObjectDeletion type object.

XML data items can be placed into the message using the global context WriteXML() method.

Below is a code fragment in which a message is generated and recorded data changes are placed into its body.

XMLWriter  = New XMLWriter();
XMLWriter.OpenFile(MessageFileName);
Node  = ExchangePlans.RemoteWarehouses.FindByCode(NodeCode);
MessageWriter  = ExchangePlans.CreateMessageWriter();
MessageWriter.BeginWrite(XMLWriter,  Node);
Selection  = ExchangePlans.SelectChanges(Node, MessageWriter.MessageNo);
While  Selection.Next() Do
Data = Selection.Get();
WriteXML(XMLWriter, Data);
EndDo;
MessageWriter.EndWrite();

Reading Data Exchange Messages

The ExchangeMessageReader object is designed for reading data exchange messages.

This object can be created by using the CreateMessageReader() method of the ExchangePlansManager object.

The ExchangeMessageReader object has three methods:

„ BeginRead()

„ EndRead()

„ CancelRead()

The BeginRead() method has two parameters: the XMLReader object that reads messages and the AllowedMessageNo enumeration value.

The BeginRead() method reads the beginning of the XML item containing the entire message, reads the message header and checks whether it is valid:

„ If the exchange plan for this message is defined; „ If the sender and recipient of the message are correct; „ If the message has a valid number.

The message number validity is defined by the second parameter value. If the second parameter has the AllowedMessageNo.Any value, then the message being read can have any number. If the value of the second parameter is AllowedMessageNo.Next, then the message number must have the highest number of all the previous messages incremented by 1. If the second parameter uses the AllowedMessageNo.Greater value, then the message number must simply be greater than the highest number of the previous messages. The default value for the second parameter is AllowedMessageNo.Greater.

After this, the beginning of the XML item containing the message body is read. If the message is not valid or a reading error occurs, an exception is raised. If no issues arise, you can start reading the body of the message.

To complete message reading successfully, use the EndRead() method. This method reads the end of the XML element item the item body and the end of the XML item containing the entire message. If everything is okay, then the message is considered received and the message number is saved as the highest number of the received messages if it is greater than the previous highest number.

The CancelRead() method allows you to cancel message reading at any time.

Below is a typical code fragment showing the use of the ExchangeMessageReader object.

XMLReader  = New XMLReader();
XMLReader.OpenFile(MessageFileName);
MessageReader  = ExchangePlans.CreateMessageReader();
MessageReader.BeginRead(XMLReader,  AllowedMessageNo.Greater);
//  Reading the message body
MessageReader.EndRead();

As was earlier noted, the body of the message can, in principle, contain any information, but in this case the body of a data change message is read. Sample code fragment for reading a data change message is provided below.

XMLReader  = New XMLReader();
XMLReader.OpenFile(MessageFileName);
MessageReader  = ExchangePlans.CreateMessageReader();
MessageReader.BeginRead(XMLReader);
ExchangePlans.DeleteChangeRecords(
MessageReader.Sender, MessageReader.MessageNo);
While  CanReadXML(XMLReader) Do
Data = ReadXML(XMLReader);
Data.DataExchange.Sender = MessageReader.Sender;
Data.DataExchange.Load = True;
Data.Write();
EndDo;
MessageReader.EndRead();

The DeleteChangeRecords() method of the ExchangePlansManager object is designated for deleting registration records whose receipt has been confirmed. After reading the body of the message, readable data are read using ReadXML(). Before writing the data in the database, two properties of the DataExchangeParameters object belonging to the object representing the data read from XML are modified. In the Sender property, the data sender node is specified in order to avoid recording changes for communications with the node from which these data have just been received. Assigning the True value to the Load property signifies that the record is produced within data loading rather than a standard writing operation. In this case some checks are omitted when writing. Guaranteed Message Delivery

In the above examples of reading and writing data exchange messages it is expected that some sent messages may be lost for one reason or another. Therefore, all recorded changes, including those that have been sent, but no receipt confirmation has been received, are entered into the messages.

A received message is valid if its number is greater than the highest number of the earlier received messages. Deletion of change records occurs only for the messages with receipt confirmation.

MessageReader.BeginRead(XMLReader);
ExchangePlans.DeleteChangeRecords(
MessageReader.Sender, MessageReader.ReceivedNo);

This logic is typical for data exchange. However, it is possible for message delivery to be guaranteed. In this case change registration deletion must occur immediately after successfully writing the message in order to avoid resending the changes. A message can only be received if its number is the maximum number of the previously received messages incremented by 1.

In this case the code fragment that records the message will look like the following:

XMLWriter  = New XMLWriter();
XMLWriter.OpenFile(MessageFileName);
Node  = ExchangePlans.RemoteWarehouses.FindByCode(NodeCode);
MessageWriter  = ExchangePlans.CreateMessageWriter();
MessageWriter.BeginWrite(XMLWriter,  Node);
Selection  = ExchangePlans.SelectChanges(Node, MessageWriter.MessageNo);
While  Selection.Next() Do
Data = Selection.Get();
WriteXML(XMLWriter, Data);
EndDo;
MessageNo  = MessageWriter.MessageNo;
MessageWriter.EndWrite();
ExchangePlans.DeleteChangeRecords(Node  ,MessageNo);

The code fragment in which the message is received looks like the following:

XMLReader  = New XMLReader();
XMLReader.OpenFile(MessageFileName);
MessageReader  = ExchangePlans.CreateMessageReader();
MessageReader.BeginRead(XMLReader,  AllowedMessageNo.Next);
While  CanReadXML(XMLReader) Do
Data = ReadXML(XMLReader);
Data.DataExchange.Sender = MessageReader.Sender;
Data.DataExchange.Load = True;
Data.Write();
EndDo;
MessageReader.EndRead();

Please keep in mind that the organization of guaranteed message delivery is quite complicated and in most cases it is preferable to simply send changes repeatedly until their receipt has been confirmed. Collision Resolution

In the above examples of reading and writing messages, we did not take into account that in data exchange one item could be modified in two data exchanging nodes at the same time. In this case it is impossible to tell which change should be accepted in the end. This situation is called a collision.

One of the ways to resolve collisions is by defining one of the nodes as a master and the other as a slave. In this situation the change made in the master node must be accepted and the change made in the slave node – rejected.

To implement this, upon receiving the message and before recording the data find out whether the change of these data has been recorded and, depending on the role of the node in this sender-recipient pair, make the decision as to whether data must be written or not.

An example of using the "master-slave" strategy in reading messages is provided below. Here, to save the role of the node in the exchange plan, the Master attribute with the Boolean type has been defined.

XMLReader  = New XMLReader();
XMLReader.OpenFile(MessageFileName);
MessageReader  = ExchangePlans.CreateMessageReader();
MessageReader.BeginRead(XMLReader);
ExchangePlans.DeleteChangeRecords(MessageReader.Sender,  MessageReader.MessageNo);
Sender  = MessageReader.Sender;
Master  = Sender.Master;
While  CanReadXML(XMLReader) Do
Data = ReadXML(XMLReader);
If Master Or
Not ExchangePlans.IsChangeRecorded(Sender, Data)
Then
Data.DataExchange.Sender = MessageReader.Sender;
Data.DataExchange.Load = True;
Data.Write();
EndIf;
EndDo;
MessageReader.EndRead();

Name Space Mapping

When a message is written using the BeginWrite() method of the ExchangeMessageWriter object, no namespace mappings are defined. At the same time, a set of namespaces can be used multiple times for recording separate data items. In this case defined mappings of these namespaces occur multiple times in the body of the message. Therefore, it is important to enter several lines of code to define the mappings for the most commonly used namespaces after starting to record the message, but before recording the message body.

An example is provided in the fragment below:

XMLWriter  = New XMLWriter();
XMLWriter.OpenFile(MessageFileName);
Node  = ExchangePlans.RemoteWarehouses.FindByCode(NodeCode);
MessageWriter  = ExchangePlans.CreateMessageWriter();
MessageWriter.BeginWrite(XMLWriter,  Node);
XMLWriter.WriteNamespaceMapping("xsd",  "http://www.w3.org/2001/XMLSchema");
XMLWriter.WriteNamespaceMapping("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
XMLWriter.WriteNamespaceMapping("v8",
"http://v8.1c.ru/data");
Selection  = ExchangePlans.SelectChanges(
Node,
MessageWriter.MessageNo);
While  Selection.Next() Do
Data = Selection.Get();
WriteXML(XMLWriter, Data);
EndDo;
MessageNo  = MessageWriter.MessageNo;
MessageWriter.EndWrite();
ExchangePlans.DeleteChangeRecords(Node  ,MessageNo);

In some cases this approach can help to significantly reduce the size of the XML document containing the data exchange message.

15.3.         DISTRIBUTED INFOBASES

15.3.1. General Principles

A distributed infobase is a set of 1C:Enterprise infobases (nodes of the distributed infobase) that support configuration and data synchronization. A distributed infobase has a hierarchical structure. Each node of a distributed infobase can have one master node and any number of slave nodes. The main node or the node which does not have a master node is called the root node of the distributed infobase (see the Main database on fig. 305). Each node can only exchange data with its "neighbors": its master and slave nodes.

Fig. 305. Distributed Hierarchical Database

Any changes to the configuration are allowed only in the root node. Subsequently, they are distributed over the hierarchy, from the root node to its subordinates, etc. In this manner, the distributed infobase management tool assures the same configuration for all nodes of the distributed infobase.

Data change is allowed in each node of the distributed infobase. Data synchronization takes place through the distribution of data changes made in one node to all structures of the distributed infobase.

When configuring document sequence functions in a distributed infobase, note that a document's membership in a document sequence makes sense only in a single node of a distributed infobase. It can be a node where the document was created or some other node, but in any case only one. Violating this rule may result in various problems while you are working with the system, such as failure to restore the document sequence.

If complete configuration duplication is supported in the framework of all the distributed infobase, then complete data duplication is not required. The content of data for which changes are transferred in the framework of the distributed infobase can be regulated "vertically" (by defining multiple metadata objects for which data are exchanged) or "horizontally" (by assigning conditions for change transmission and receipt at the level of individual data items).

15.3.2. Exchange Plans

Exchange plans play a central role in managing distributed infobases. To make an exchange plan suitable for organizing distributed infobases, set its Distributed Infobase property at the configuration stage.

The data in the distributed infobase is transferred by means of messages provided by the message infrastructure. As opposed to universal data exchange mechanisms, the contents of a message transferred between nodes of a distributed infobase cannot be arbitrary, but rather are regulated by exchange protocols for distributed infobases.

The data whose changes are exchanged in a distributed infobase is defined by the exchange plan content. Occurrence of a metadata objects in the exchange plan content shows that data changes corresponding to the metadata object can be registered for nodes of this exchange plan. As opposed to universal data transfer mechanisms, data that can be exchanged within a distributed infobase is highly limited by the content of its corresponding exchange plan.

To record data changes in a distributed infobase, use the change registration service. Data items are placed into the message using XML-serialization. In addition to data exchange between nodes of the distributed infobase, configuration changes and some additional auxiliary information can be transferred. Recording configuration changes and their transfer in the distributed infobase is completely automatic and is not accessible for users and configuration developers.

As opposed to universal data exchange mechanisms, data exchange message generation and receipt in a distributed infobase takes place "in a single act", i.e. the contents of the message are generated using a single 1C:Enterprise script method. Similarly, message content is read using a single method. In order to manage the composition of data entered into the message as well as data read from the message and entered into the database, the following event handlers can be defined at the level of individual data items in the exchange plan module:

„ OnSendDataToSlave

„ OnSendDataToMaster

„ OnReceiveDataFromSlave

„ OnReceiveDataFromMaster

In this way, universal data exchange mechanisms are nearly completely applied in the distributed infobase; however, distributed infobases provide some additional opportunities.

15.3.2.1. Master and Slave Nodes

As explained above, each node of the distributed infobase can have one master node and any number of slave nodes (see fig. 306). A node is considered a slave in relation to its master node and, accordingly, a node is a master node in relation to its slave nodes. A node that does not have a master node is called the root node of the distributed infobase.

IMPORTANT!

The root node of the distributed infobase is the only place where you can make changes to the infobase configuration.

A distributed infobase can be based on several exchange plans with the Distributed Infobase property set. Interaction in each "master-slave" node pair is based on one of the exchange plans defined in the configuration. There are no restrictions set for using a given exchange plan in a given infobase node.

Each distributed infobase node only "knows" its "neighbors" (its master and slave nodes), just like in the universal data exchange mechanisms. In this way, the complete distributed infobase schema has more than two levels unknown to any node.

15.3.2.2. Collision Resolution

A typical procedure for handling collisions in distributed infobases is based on the "master-slave" relationship. This is carried out automatically upon receiving a message. Data item changes made in the master node have a higher priority than changes made in slave nodes. Therefore, if the message from the slave node contains a data item with modifications registered for that slave node, no action is perform – this item is not entered into the database and the change registration record is not deleted.

If the message from the master node contains a data item with changes that have been registered for the master node, then this data item is recorded in the database and the change registration record is deleted.

15.3.2.3. Initial Image of Distributed Infobase Node

Usually in distributed infobases slave nodes originate from the master node. In other words, a new infobase is created on the basis of the configuration and data contained in the master node and corresponding to the slave node defined in the exchange plan. This infobase is called an initial image of the distributed infobase node.

The following activities occur when creating the initial image:

„ The unchanged configuration is transferred to the initial image from the master node.

„ Node objects are created in the initial image's source exchange plan; they are initialized in a way that makes additional settings unnecessary before starting data exchange between the master and slave nodes.

„ Data are transferred from the master node to the initial image according to the rules defined in the exchange plan (the content of the exchange plan and the OnSendDataToSlave event handler's results).

The procedure for creating an initial image for one node can be repeated over and over. This is useful in cases when the infobase of a slave node is permanently lost. When creating an initial image, all change registration records for the corresponding node are deleted and the history of this slave node starts from the beginning.

15.3.2.4. Data Exchange Messages in Distributed Infobases

Data exchange messages provided by the message infrastructure are used to transfer data and configuration changes in a distributed infobase. When using universal data exchange mechanisms, the configuration developer specifies what and how is entered into the message body; for distributed infobases, however, the structure and data content entered into the message body are specifically defined.

Let us go over the structure of a data exchange message used in a distributed infobase. Below is a sample message.

<v8msg:Message  xmlns:v8msg="http://v8.1c.ru/messages">
<v8msg:Header>
<v8msg:ExchangePlan>RemoteWarehouses</v8msg:ExchangePlan>
<v8msg:To>Warehouse1</v8msg:To>
<v8msg:From>Office</v8msg:From>
<v8msg:MessageNo>20</v8msg:MessageNo>
<v8msg:ReceivedNo>15</v8msg:ReceivedNo>
</v8msg:Header>
<v8msg:Body>
<v8de:Changes  xmlns:v8de="http://v8.1c.ru/dataexchange">
<v8de:Signature>
7b4d5320-f69c-4a7b-9273-ff56607fc8ab</v8de:Signature>
<v8de:Config  xmlns:v8md="http://v8.1c.ru/metadata">
<!–  Modified configuration objects -->
<v8de:Digest1>88d3f3a6ba3f4df03c7ec00f154837fc</v8de:Digest1>
<v8de:Digest2>00cf636b02a488103a64c7a2cf81069e</v8de:Digest2>
</v8de:Config>
<v8de:Nodes>
<v8de:Node>
<!–  Master node data -->
</v8de:Node>
<v8de:Node>
<!–  Slave node data -->
</v8de:Node>
</v8de:Nodes>
<v8de:Data>
<!–  Modified data items -->
</v8de:Data>
</v8de:Changes>
</v8msg:Body>
</v8msg:Message>

As you can see from the example, all the differences in the data exchange message are concentrated in the body of the message. The body of the message (the Body item, associated with the http://v8.1c.ru/messages namespace) contains a single XML item – Changes belonging to the http://v8.1c.ru/dataexchange namespace. All data transferred during data exchange in the distributed infobase is contained within this element:

„ The Changes item can contain four nested items associated with the same namespace.

The Signature item contains the "signature" of the exchange plan used to receive the message.

The Config item contains configuration changes as well as data that identify the status of the configuration.

The optional Metadata items nested in Config contain changes of individual configuration objects. If configuration changes are not transferred in the message, then the Metadata items are not used. These items can only be included in messages transferred from the master node to the slave node. The Digest1 and Digest2 items contain numerical signatures for configuration changes transferred in the message and for the entire configuration except modifications. The Digest1 and Digest2 items are included in all messages sent from the master node to the slave mode and vice versa.

„ The Nodes item can only be included in messages transferred from the master node to the slave node. This item contains two nested Node items, the first containing data for the master node (sender) and the second – for the slave (recipient).

„ Finally, the Data item contains data item changes transferred in the message.

Data items are entered into the message using XML-serialization.

15.3.2.5. Exchange Plan Configuration for Work with Distributed Infobase

As was mentioned above, in order to use the exchange plan to organize distributed infobases, its Distributed Infobase property must be set.

When configuring the exchange plan used for organizing the distributed infobase, the content of the exchange plan must be defined in order to define the data for which changes are to be recorded and which can be transferred via data exchange in the distributed infobase.

Please note that if a metadata object is included in the exchange content of a working distributed infobase configuration, it does not cause any automatic change registration for data items corresponding to this metadata object. Thus, if a new object is added to the content of an exchange plan and the already existing data needs to be transferred to other nodes, this must be dealt with separately.

15.3.2.6. Exchange Plan Event Handlers

If necessary, the following event handlers can be assigned to the ExchangePlansObject.<Exchange plan name> object: OnSendDataToSlave,

OnSendDataToMaster, OnReceiveDataFromSlave, OnReceiveDataFromMaster. These can manage entries in a message and read individual data items from the message.

The OnSendDataToSlave event handler can be activated by entering the data item into the message sent to the slave node of the distributed infobase. The first parameter contains the data item itself. The value of the second parameter, upon handler activation, is DataItemSend.Auto, but this value can be modified by the handler. If the value of the second parameter is still DataItemSend.Auto after the handler has been executed, this refers to the default behavior (the data item is entered into the message). If the DataItemSend.Delete value is used for the second parameter, then an object corresponding to the deleted data item is included in the message. For database objects, this is an ObjectDeletion object initialized by the reference to the deleted database object; for record sets – this is an empty record set. The constant record manager is the only place where DataItemSend.Delete behavior is identical to DataItemSend.Auto. But if the second parameter is assigned the DataItemSend.Ignore value, then the message includes nothing that corresponds to the data item transferred in the first parameter.

The OnSendDataToMaster event handler differs from the previous one only in that it is used when entering a data item into a message sent to the master node.

The OnReceiveDataFromSlave handler is used after reading a data item from the message and before recording it in the database. The first parameter contains the data item read from the message. The second parameter, upon handler invocation, has the DataItemReceive.Auto value corresponding to the default behavior. If no data item changes have been registered in this node for the sender node, then the item is recorded in the database. If there have been recorded changes, then the item is not recorded in the database. The value of the second parameter can be modified by the handler. If the second parameter is assigned the DataIt- emReceive.Accept value, then the data item is recorded in the database regardless of whether the changes have been registered for the sender node. If changes have been registered, then the corresponding change registration record is deleted. If the second parameter is assigned the DataItemReceive.Ignore value, then nothing happens (the item is not recorded in the database and no actions are performed with the change registration records). The third parameter manages data item change recording for the sender node. When the handler is invoked, this parameter is False. If the handler does not modify this value, then no additional actions are performed. If the True value is assigned to the parameter in the event handler and no data item changes have been recorded for sender node, registration takes place.

The OnReceiveDataFromMaster event handler has the same set of param-

eters as the previous handler, but differs from it in that it is used when reading messages received from the master node of the distributed infobase. Accordingly, there are several different activities carried out when receiving data items. The DataItemReceive.Auto and DataItemReceive.Accept values of the

second parameter produce a similar effect since with the accepted collision resolution strategy dictates that the slave node data item read from the message must be recorded in the database regardless of whether its changes have been registered. All the other parameter values and activities are similar to those described above.

15.3.3. Working with Distributed Infobase

Working with a distributed infobase comprises the following main activities:

„ Creating an initial image for the distributed infobase slave node;

„ Writing a data exchange message to be sent to another node of the distributed infobase;

„ Reading a data exchange message sent from another node of the distributed infobase.

Contrary to features provided by universal data exchange mechanisms that cannot be accessed without the 1C:Enterprise script, the activities listed above can be executed using the 1C:Enterprise script, the All actions menu of the exchange plan list form or other tools defined at the configuration stage.

Additionally a master node can be set and, therefore, retrieved for each node of the distributed infobase. This operation cannot be classified as the main operation in a distributed infobase, that is why it has no corresponding interactive action.

15.3.3.1. Working with Distributed Infobase from 1C:Enterprise Script Creation of Initial Image for Distributed Infobase Slave Node

The ExchangePlansManager object containing the CreateInitialImage() method can be used to create an initial image for a slave node in a distributed infobase.

The first parameter of this method must be either the value of the ExchangePlansRef.<Exchange plan name> type representing a reference to the slave node of the distributed infobase or the value of the ExchangePlansObject.<Exchange plan name> type representing the node itself.

The second parameter must contain a connection string identifying the infobase where the slave node initial image is placed . The infobase used for creating the initial image must be empty or non-existent.

As was noted above, the configuration of the infobase is applied to the initial image without change. Data corresponding to metadata objects that are not in the exchange plan are not included in the initial image. Additionally the OnSendDataToSlave event handler is called for each data item transferred to the initial image. Accordingly, only data that correspond to the exchange plan rules can be included in the initial image.

Two nodes (master node and "this" node) are created and initialized in the infobase of the initial image, in the exchange plan associated with this initial image. Therefore, immediately after creating the initial image, the slave node infobase is ready to exchange data with its master node.

All operations of data transfer to the initial image take place within a single database transaction of the master node. This is necessary for data agreement in the initial image. However, if other users use the master node infobase intensively to modify data, conflicts can occur between the initial image creation transaction and transactions of other users. In this case an exclusive mode should be set for the infobase of the master node before creating an initial image.

NOTE

Infobase operation in the exclusive mode does not switch the MS SQL database to the single user mode.

Writing Data Exchange Messages in Distributed Infobase

As was shown, a data exchange message in a distributed infobase differs from a general data exchange message in its specific body content. The same differences can be seen between the procedure for writing data exchange messages in a distributed infobase and the general message writing procedure.

The exchange plan manager containing the WriteChanges() method can be used to write the body of a data exchange message in a distributed infobase. Its first parameter is the ExchangeMessageWriter object that is used to write the message. This object must have its BeginWrite() method called and its EndWrite() method still non-invoked.

The optional second parameter specifies the maximum number of data items to be entered into the message within a transaction. If 0 is entered as the parameter value (used by default), then the entire message is generated in one transaction. This mode provides the best compatibility for data entered into the message, but conflicts with transactions of other users are possible. With fewer items processed in a transaction, the probability of transaction conflicts is smaller, but there is a greater probability of data incompatibility. Therefore, we recommend that you only use the default value for the second parameter.

The WriteChanges() method writes the XML Changes item in the body of the data exchange message, entering all the necessary information as described above. Configuration objects and data items with changes registered for the message recipient node are entered into the corresponding message fragments. The data items are actually entered into the message by the OnSendDataToMaster (OnSendDataToSlave) event handler called by the ExchangePlansObject.<Exchange plan name> object representing the message recipient node.

A typical code fragment is given below showing how a data exchange message is written in a distributed infobase.

XMLWriter  = New XMLWriter();
XMLWriter.OpenFile(MessageFileName);
Node  = ExchangePlans.RemoteWarehouses.FindByCode(NodeCode);
MessageWriter  = ExchangePlans.CreateMessageWriter();
MessageWriter.BeginWrite(XMLWriter,  Node);
ExchangePlans.WriteChanges(MessageWriter);
MessageWriter.EndWrite();

Reading Data Exchange Messages in Distributed Infobase

The exchange plan manager containing the ReadChanges() method can be used to read the body of data exchange messages in a distributed infobase.

Its first parameter is an ExchangeMessageReader object used to read the entire message. This object must have its BeginRead() method called and its EndRead() method still non-invoked.

TIP

We strongly recommend that you either leave the second parameter blank or use the default value (AllowedMessageNo.Greater) when using the BeginRead() method of the ExchangeMessageReader object.

This is all based on the principles for distributed infobases where separate data exchange messages can be lost, but the same message cannot be received more than once.

The maximum number of data items read from the message and entered into the database in one transaction can be used as the optional second parameter. The default parameter value is 0, it signifies that all message reading takes place in a single transaction. If message reading occurs in a single transaction and errors occur, it is not possible for only part of the data items to be read from the message and entered into the database. But it could be that there are too many database changes that need to be completed in one transaction. There is also an increased probability of conflicts between the message reading transaction and transactions of other users. To avoid these problems, the number of data items processed in a single transaction can be limited. But if this is not absolutely necessary, we recommend using the default mode to read all data items in one transaction.

The following could be a sequence of activities carried out by the ReadChanges() method:

„ The exchange plan "signature" is read and checked to ensure that the message was received from the expected exchange plan with the expected configuration.

„ Configuration changes are read from the message. The numerical signature of the configuration is checked to avoid any possibility that incompatible configurations are located in the sender node and the current node of the distributed infobase. For each changed configuration object that was read, the system checks to see if this configuration object has been actually changed. As a reminder, modified configuration objects can only be contained in messages sent from the master node to its slave.

„ Change registration records for messages with confirmed receipt are deleted. As a reminder, the maximum number of messages accepted by the sender node is given in the message header and is accessible through the ReceivedNo property of the ExchangeMessageReader object.

„ If it can be established, through checking the numerical signature, that the configuration in the current node of the distributed infobase is different than the configuration of the sender node, then there are two possible actions:

If the current node is the master node in relation to the sender node, then it is not possible to receive this message in the future under any circumstances.

If the current node is the slave node in relation to the sender node, then before continuing to receive the message, the configuration of the database must be refreshed to the configuration of the sender node. In updating the configuration database, configuration objects previously received, saved and changed are transferred. In both cases an exception is raised, with a corresponding error message. If the message cannot be read in the first case, then in the second case the same message can be successfully read and received after updating the database configuration which can be accomplished in the Designer mode.

„ If a data exchange message sent from the master node of the distributed infobase is being received, then the current node data and the sender node data are brought into compliance with the data about these nodes contained in the data exchange message. If the data exchange message has been received from the slave node, then these data should not be there (for more information see page 2-775).

„ Data items are read from the message and recorded in the database. The message can only contain data items corresponding to metadata objects entered into the content of the exchange plan associated with this message. For each of the data items read from the message, the OnReceiveDataFromMaster (OnReceiveDataFromSlave) event handler is called for the ExchangePlansObject.<Exchange plan name> type object. Future activities in each of the data items are defined by the handler operation results (for details see page 2-777).

Receiving and Setting the Master Node in Distributed Infobase

The root node in a distributed infobase does not have a master node. All the other nodes do, however. In a typical distributed database scenario, setting a master node is not mandatory. In some cases, however, it may be useful. For example, the need may arise to assign one of the sub-trees of the distributed infobase to an independent infobase or to reassign one of the nodes of the distributed infobase.

The SetMasterNode() method from the ExchangePlansManager object has been designated for setting the master node in a distributed infobase. This method has one parameter. If the ExchangePlansObject.<Exchange plan name> or ExchangePlansRef.<Exchange plan name> type value is used as the first parameter, then the Distributed Infobase property must be defined for the exchange plan with the associated reference or object. In this case the master node will be set for the given infobase. If Undefined is entered as the parameter value, then master node setting is cancelled.

To execute this method successfully, there must not be other active users in the infobase, including in the Designer mode.

The MasterNode() method from the ExchangePlansManager object is used for receiving the master node. If the current infobase is not a distributed infobase node or if the master node is not defined (the infobase is the root node), the method returns Undefined. If the master node for the infobase is defined, the method returns the ExchangePlansRef.<Exchange plan name> type value.

NOTE

Master node assignment for an infobase can be cancelled specifying the /ResetMasterNode parameter in the command bar in the Designer startup batch mode.

15.3.3.2. Interactive Work with Distributed Infobase

As noted above, many of the common actions in a distributed infobase can be completed interactively using the More (All actions) menu in the exchange plan list form (or the icons of the list form command bar). The corresponding commands are inserted in the menu through AutoFill.

Fig. 306. List of Exchange Plans

To execute each of these commands, select the exchange plan node the command is to be applied to in the list and click the corresponding More (All actions) menu option.

The More – Create initial image (All actions – Create initial image…) command can be used to create an initial image of the slave node in a distributed infobase. After using this menu point, a dialog appears asking you to select the location type of the infobase and its parameters (if the image is to be created in the client/server mode). After clicking the Create initial image button, the initial image is created. The procedure for creating an initial image interactively is not different from the procedure used by the CreateInitialImage() method of the Exchan- gePlansManager object.

The More – Write changes… (All actions – Write changes…) command is used to write the data exchange message to a file. After using this menu point, a dialog appears. It prompts the user to enter the number of data items to be processed in one transaction. After this, click Write and save to file. It opens the exchange file selection dialog box. Select the file and click Open to start data download.

The More – Read changes… (All actions – Read changes…) command is used to read data exchange messages from a file. After using this menu point, a dialog box appears. It prompts the user to enter the number of data items to be processed in one transaction. After this, click Select file and read changes. It opens the exchange file selection dialog box. Select the file and click Open to start data upload.

All data download/upload operations (including creation of an infobase initial image) are performed on the 1C:Enterprise server side.

15.3.4. Data Exchange Scenarios in Distributed Infobase

The OnSendDataToSlave, OnSendDataToMaster, OnReceiveDataFromSlave and OnReceiveDataFromMaster event handlers allow sufficient flexibility in managing data exchange in a distributed infobase. A greater variety of scenarios is available when using these handlers. We will go over some of these scenarios in this section.

15.3.4.1. Default Behavior

The default behavior of a distributed infobase is the simplest scenario. This scenario is characterized by the following:

„ Each data item change made in each of the nodes of the distributed infobase is distributed throughout all nodes.

„ Collisions are resolved based on the "master – slave" node relationship.

For this scenario, all handlers must not modify the parameters transferred to them or the handlers can be left undefined altogether.

15.3.4.2. Data Distribution in Slave Nodes

This scenario implies that the following takes place for certain data items:

„ The entire set of data items exists in the master node.

„ The presence of a data item in a slave node is determined by comparing several data item attributes with attributes of the exchange plan slave node.

„ Collisions are resolved based on the "master – slave" node relationship.

For this scenario, you must ensure that data items that must not exist in the slave node do not end up in the data exchange message written in the master node.

Furthermore, if the data item attribute values can be modified in the slave node, then you must ensure that change recording in the master node takes place for those objects which must not be in the slave node according to their attribute values.

To get a greater level of detail, assume an Invoice document is used as a data item type this scenario is applied to. This document has a Warehouse attribute of the CatalogRef.Warehouses type. The data exchange is organized according to the Warehouses exchange plan. This exchange plan also has a Warehouse attribute of the CatalogRef.Warehouses type. This exchange plan has been used as a basis for a distributed infobase where the central office is the root node and the warehouses are the slave nodes. Each of the slave nodes in the exchange plan has the Warehouse attribute value set so as to indicate each warehouse corresponding to that node. All of the Invoice documents must exist in the root node. They can also exist in the slave nodes provided that the Warehouse attribute values in the document and the exchange plan node are equal.

In order for Invoice documents not to end up in the wrong slave nodes, the OnSendDataToSlave event handler must look like the following:

Procedure  OnSendDataToSlave(DataItem, ItemSend)

DataType = TypeOf(DataItem);
If ValueType = Type("DocumentObject.Invoice") Then

If DataItem.Warehouse <> Warehouse Then

ItemSend = DataItemSend.Delete;
EndIf;
EndIf;
EndProcedure

In the example above, the handler analyzes the data item type and if it is equal to DocumentObject.Invoice, then the Warehouse attribute value of the document is compared with the Warehouse attribute value of the exchange plan. If the attribute values are equal, you do not have to modify the ItemSend parameter value (upon invocation, this parameter has the DataItemSend.Auto value). In this case the document's XML-representation is entered into the message. If, however, the attribute values do not match, the ItemSend parameter is assigned the DataItemSend.Delete value. In this case an XML representation of the ObjectDeletion object is placed in the message and initialized with a reference to an appropriate Invoice document.

It may seem strange that when the Warehouse attributes are not equal, the DataItemSend.Delete value is assigned to the ItemSend parameter instead of the DataItemSend.Ignore value, as with the DataItemSend.Delete value selected XML-representation of the ObjectDeletion object is placed into messages sent to all slave nodes except the node the document is sent to. Therefore, most of the time ObjectDeletion is sent to the nodes where the document to be deleted has never existed.

This is accurate, but this is the most ordinary case. If, for example, you know that the Warehouse attribute value of the Invoice document can be set only when creating the document and cannot be changed in the future, then the DataItemSend.Ignore value could have been assigned to the ItemSend parameter in this handler.

If the Warehouse attribute value of the Invoice document can be modified in the slave node, then the OnReceiveDataFromSlave event handler must be defined in the exchange plan as follows:

Procedure  OnReceiveDataFromSlave(DataItem, ItemReceive, SendBack)

DataType = TypeOf(DataItem);
If ValueType = Type("DocumentObject.Invoice") Then

If DataItem.Warehouse <> Warehouse Then

SendBack = True;
EndIf;
EndIf;
EndProcedure

In the example above, the handler analyzes the data item type and if it is equal to DocumentObject.Invoice, then the Warehouse attribute value of the document is compared with the Warehouse attribute value of the exchange plan. If the attribute values are equal, then the values of the ItemReceive and SendBack parameters do not have to be modified, assigning the default behavior upon receiving the data item. If the attribute values are not equal, then the SendBack parameter is assigned the True value. In this case registration of document changes is guaranteed and the ObjectDeletion object is sent to the slave node with the message if, of course, the Warehouse attribute is not modified in the master node so that it is equal to the value of the Warehouse attribute corresponding to the exchange plan node.

If the value of the Warehouse attribute in the Invoice document cannot be modified after creating the document, then the OnReceiveDataFromSlave handler do not have to be defined.

15.3.4.3. Non-Standard Collision Resolution

This scenario implies that the following takes place for certain data items:

„ Each data item change made in each of the nodes of the distributed infobase is distributed throughout all nodes.

„ Collisions are resolved based on the "master – slave" relationship, with the slave node having a higher priority.

This situation is explained in the above examples with the Invoice document and the Warehouses exchange plan.

In this case you must define the OnReceiveDataFromSlave and OnReceiveDataFromMaster event handlers. The OnReceiveDataFromSlave handler will look like the following:

Procedure  OnReceiveDataFromSlave(DataItem, ItemReceive, SendBack)

DataType = TypeOf(DataItem);
If ValueType = Type("DocumentObject.Invoice") Then

ItemReceive = DataItemReceive.Accept;
EndIf;
EndProcedure

This handler is quite simple: the data item type is checked and if the data item is of the right type, then the DataItemReceive.Accept value is assigned to the ItemReceive parameter to unconditionally receive data items regardless of whether its changes have been registered.

The OnReceiveDataFromMaster event handler looks like the following:

Procedure  OnReceiveDataFromMaster(DataItem, ItemReceive, SendBack)

DataType = TypeOf(DataItem);
If ValueType = Type("DocumentObject.Invoice") Then

If ExchangePlans.IsChangeRecorded(Ref,DataItem)
Then

ItemReceive = DataItemReceive.Ignore;
EndIf
EndIf;
EndProcedure

This handler is slightly more complicated. If the data item belongs to the required type, a check is run to see if the changes in the data item have been registered in the message sender node. If the changes are have been registered, then the DataItemReceive.Ignore value is assigned to the ItemRecieve parameter. As a result, the data item read is not recorded in the database, but the change recording is saved to allow you to enter the data item in the message sent to the master node.

15.3.4.4. Other Scenarios

The situations described above are only a few of the possible scenarios for organizing data exchange in a distributed infobase. Many scenarios are available based on handlers described above. Some of these can be combinations of methods described in this chapter, while others can be fundamentally different.

Leave a Reply

Your email address will not be published.

 

1C:Enterprise Developer's Community