D Connector API

This appendix describtes the XLSTs and XSDs used to transform custom fields for an Exchange 2007 Connector.

This appendix includes the following topics:

D.1 Overview of the Connector API

The Connector API includes:

Terminology

Terms that relate to the API include:

D.1.1 Associated Data

Associated data is connector-defined data that the Hub stores on behalf of connectors. Although this can be data of any type, a connector must ensure that the data conforms to the AssociatedData structure.

An associated data consists of a unique identifier and a collection of groups. Each group, in turn, has a group identifier and an arbitrarily large number of KeyValuePair structures that contain the associated data. Connectors are free to define any number of groups and any number of KeyValuePair structures within each group. For example, the Oracle BDSS Connector for Microsoft Exchange 2007 defines user-level associated data with a identifier of MailboxProperties that contains a single group whose group identifier is also MailboxProperties. This group contains two KeyValuePair structures containing the keys of legacyExchangeDN and msExchHomeServerName and the values are populated with data obtained from Active Directory. Similarly, the Exchange 2007 Connector defines record-level associated data with a identifier of the PIM Record ID that contains three groups with group identifiers of SourceKey, ChangeKey, and PredecessorChangeList. The SourceKey group holds a single KeyValuePair where SK is the key and the value is the Exchange records source key value. The ChangeKey group holds a single KeyValuePair where CK is the key and the value is the Exchange records change key value. The PredecessorChangeList group holds an arbitrarily large number of KeyValuePair structures (each change key in the Exchange records predecessor change list is represented as a KeyValuePair).

Associated Data has the following characteristics:

  • It is opaque to the Hub (that is, unseen by the Hub).

  • It is optional.

  • It is stored in the data store as text.

  • It can be arbitrarily large.

  • In addition to the record-level RTL (Run-Time Library) access APIs, connectors may provide record level-associated data in the result structure of a CreateRecord or UpdateRecord call. The Hub updates the data store with the new associated data.

  • In addition to the RTL record-level access APIs, connectors may provide record level associated data in each UpsertRecord in an ExtractResponse. The Hub updates the data store with the associated data.

D.1.2 Connector Name

The name for a set of configurations for connector instances that service a specified set of PIM server instances.

Note:

The connector name does not change during a given synchronization session. Therefore, stateful connectors may choose to cache the value for a given user and synchronization session and use it when calling the Hub callback or RTL (Run-Time Library) APIs.

D.1.3 Create/Create Conflict

A create/create conflict occurs when two or more records from different systems are extracted during the same synchronization session that have not been previously synchronized and have key fields with matching field values.

D.1.4 Field Class

A field class is a classification of a PIM field that applies additional semantics to a PIM field beyond a data type. Examples of field classes are Phone, Address, Email, Category, To, CC, and BCC. The field class performs the following:

  • Facilitates auto-mapping of fields between connectors.

  • Enables connector implementations to implement logic based on a particular class. For example, a connector may require field information about a field class (such as To, CC, or BCC) to resolve a value (such as an attendee) in its system.

D.1.5 PIM Domain Target

The PIM Domain Target is optional configuration metadata for the location where the PIM data for the domain resides for the given user and a given domain. The PIM Domain Target is available to connectors whose PIM server stores PIM data in different locations for each user. For example, Exchange stores task and contact data in different folders for each user: the Exchange task data is stored in the Task folder (or a subfolder of the Task folder) and the Exchange contact data is stored in the Contact folder (or a subfolder of the Contact folder). The connector implementation interprets the configuration metadata because it is connector-specific. For example:

  • A configuration of a relative path of folders such as \root\calendar\mycalendar would indicate synchronizing against a subfolder of a domain.

  • A configuration of an abstract value such as Root would indicate synchronizing against the default primary folder for a domain.

Some connectors may not have the notion of PIM folders and might specify something else, such Siebel PDQ filter. For example, for the contact domain, the connector identifies a PDQ of Sync List as the domain target. Unlike folder paths, the PDQ does not identify a physical location on the target, but, like folder paths, it identifies the set of records that are targeted for synchronization.

Note:

Because this optional metadata is specified on a per-user, per-domain basis, it is incumbent on administrators to specify the PIM Domain Target for each user and each domain that is synchronized by BDSS. To simplify connector configuration, developers can create a default PIM Domain Target that enables connectors to use a default value if the configuration is not available. For example, a connector may use the default folder for a domain if the configuration is unavailable. Developers can also require a configuration value such as Root to indicate that the connector should use the default folder for a domain. Without a default PIM Domain Target, a connector can require the configuration if it requires the metadata for each user and domain

D.1.6 PIM Record Description

The PIM Record Description is an array of KeyValuePair structures. Each KeyValuePair structure holds a Hub field name as the key and a Hub field value as the value. Connectors must obtain the list of Hub fields configured to be included in the PIM Record Description for each Hub domain by using the RTL (Run-Time Library) API GetConfigurationMetadata.

The configuration of the Hub fields used in the PIM Record Description is contained in the FtsKeyFields profile. The section name of the profile contains the Hub domain name. The parameters in the profile contain such names as KeyFieldX where X is a number that not only distinguishes the row from other rows in the table, but specifies the order in which the field should appear when a connector constructs a PIM Record Description. Connectors must build PIM Record Descriptions (if the configuration is present) and ensure the order that the fields appear in the KeyValuePair array are in the same sequence as specified by the KeyFieldX. For example, the Task Hub domain has the following configuration in the FtsKeyFields profile (listed in Table D-1).

Table D-1 Task Hub Domain Configuration

Profile Section (a Hub Domain Name) Parameter Value

FtsKeyFields

Task

KeyField1

Subject

FtsKeyFields

Task

KeyField2

StartDate


When a connector extracts a record, it constructs a KeyValuePair array containing two elements. The first element (index0) contains a KeyValuePair where the key is Subject and the value is the Hub field value on the record. The second element (index1) contains a KeyValuePair where the key is StartDate and the value is the Hub field value is on the record.

If a Hub record does not have a value for a configured key field, the connector must provide an empty string for that field.

Note:

The connector must provide Hub field names and Hub field values in the record description. Because the connector provides this information, connectors must extract the record from the PIM, transform it to Hub format and then construct the PimRecordDescription. Similarly, the connector must provide Hub field names and values upon a successful Create or Update operation. This is crucial because the Hub uses the PIM Record Description containing these key fields to perform key field matching on PIM records when it evaluates extract responses from multiple PIM servers. The PIM Record Description is also used when logging information about a given operation for a Hub record as it travels through the system.

For Oracle Fusion Middleware 11g release 1 of BDSS, the field designated as a member of the record description cannot be a multivalue type.

D.1.7 PIM Record ID

The PIM Record ID is an identifier used by a connector for uniquely identifying a record on the PIM server. The PIM Record ID should be unique within a PIM server on a per-user, per-domain basis. The connector should ensure that the property used as the PIM Record ID can be used to identify and access the record.

Connectors provide the PIM Record ID to BDSS when:

  • Extracting records from the PIM server

  • Completing a pushed create operation

BDSS provides the PIM Record ID to connectors when pushing an Update or Delete operation to the PIM server.

D.1.8 PIM Record Version ID

The PIM Record Version ID is a connector-defined value that captures the version of a PIM record. It can be any value if it can track a modified PIM record. For example, if a PIM record has a Last Modification Date/Time field, a connector might opt to use it as the PIM Record Version ID because the Last Modification Date/Time field is updated whenever the record is updated. Similarly, if a PIM record has an integer value that is incremented when the record changes, then the connector might use the integer value.

D.1.9 Synchronization Session

A synchronization session is a session in which the Hub synchronizes the data for a Hub user for one or more Hub domains between one or more PIM stores through the BDSS connectors. The session starts when the Hub calls the connector API InitializeUserSyncSession and is identified by a unique identifier called the Synchronization Session ID. The session ends when the Hub calls the EndUserSyncSession API. In between these two calls, the Hub may call the connector APIs:

  • ExtractDomains API: This API is not called on a connector if the Hub configuration is such that the connector is configured for inbound synchronization only for all Hub domains. It is called if the Hub configuration is such that the connector is configured for bidirectional or outbound-only synchronization for at least one Hub domain.

  • CreateRecord, UpdateRecord, or DeleteRecord APIs may be called any number of times during a session.

D.1.10 Synchronization State

The Engine tracks the user's domain records that have been exported successfully from a PIM server using connector-provided data known as the synchronization state. The synchronization state is monitored at the connector domain level.

Connectors define the synchronization state and its format. For example, connectors can use a date/time stamp to indicate the time that they performed an extract query during a prior synchronization session, or they can use a convention defined by the PIM APIs that describe how the connector exchanges data with its PIM server. The Oracle BDSS Connector for Exchange 2007, for example, uses an Incremental Change Synchronization (ICS) binary BLOB. For more information about how connectors manage synchronization state, see Section D.4.3, "CommitCachedSyncState Method API," Section D.4.8, "GetSyncState API," and Section D.4.10, "SaveSyncState API."

Note:

Although this data is opaque to the Engine, the Engine dictates when the synchronization state is saved to the Hub data store.

There is one synchronization state for each connector domain for a user. The synchronization state, which resides in the Hub data store, enables the system to extract all of the records from a domain or just the Create, Read, Update, and Delete operations that have occurred from a prior synchronization state.

Note:

The Engine updates the synchronization state of a connector domain after each synchronization session for a user, but only if all other connectors do not report errors when processing the records they are sent. If the connectors report errors, then the synchronization state cannot be updated, as the system must again extract some records in a future synchronization session (after the errors have been fixed).

D.1.11 Update/Update Conflict

An update/update conflict occurs when a previously synchronized record is updated in multiple systems and is extracted during the same synchronization session.

D.2 Connector Interface

A connector's PIM server synchronization services are exposed as a Web service. Connector developers implement the Web service interface defined in this document. The Engine, test applications, and other Web service clients are consumers of the Connector Interface, which includes the following API:

Note:

The ExtractDomains API is asynchronous. The other APIs are all synchronous.

D.2.1 InitializeUserSyncSession API

The Hub calls the InitializeUserSyncSession API at the beginning of each synchronization session for each user. Connectors should perform any user-based initialization required for a user to enable them to service subsequent requests during the synchronization session identified by the given syncSessionId. Table D-2 lists the parameters of the InitializeUserSyncSession API.

Table D-2 Parameters of the InitializeUserSyncSession API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

[in]

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubUserId

String

[in]

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

[in]

Contains the PIM User ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains a URL that the connector should call if it must obtain metadata from BDSS. This parameter must be non-null and nonempty.

hubDomainArray

DomainInfo []

[in]

Contains an array of DomainInfo structures. The array contains metadata for all configured Hub domains. This parameter must be a non-null array. Each DomainInfo structure must meet the following criteria:

  • pimDomainTarget—This member must be non-null and nonempty.

  • pimFilterCondition—This member must be non-null, but may be empty.

  • hubDomain—This member must be non-null and nonempty.

  • pimDomainSyncState—This member must be non-null, but may be empty.

Connectors should validate the array and return an error if the given DomainInfo array does not meet this criteria.

connectorUrl

String

[out]

An optional parameter. On input, the parameter is NULL. On output, it contains the full URL of the connector that received the call or remains NULL.

The connector that received this call can provide its URL if the connector requires BDSS to call the same connector instance (identified by the URL) when making subsequent calls for the given Hub user during the synchronization session identified by the given synchronization session ID.


Return Value

void

Exceptions

If the connector cannot initialize the user, it should throw an exception and provide a message identifying the problem. This allows the message to be logged by BDSS.

D.2.1.1 Engine Contract

To call the InitializeUserSyncSession API, the Engine must perform the following:

  • Provide the domain metadata for all Hub domains.

  • Call the InitializeSyncSession API before calling ExtractDomains, CreateRecord, UpdateRecord, or DeleteRecord.

    Note:

    The Engine can call GetPimServerEndPoint before calling InitializeSyncSession API.

  • If the connector throws an exception, the Hub considers this an indication that the connector could not initialize the user. Therefore, the Hub does not make any subsequent calls to the connector for the given Hub user and synchronization session.

  • Provide the Connector Run-Time Library URL the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  • Provide the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName.

D.2.1.2 Connector Contract

The connector must perform in response to the Engine's InitializeUserSyncSession API call:

  • Validate each parameter passed in to the API to ensure that it meets the criteria outlined in Table D-2.

  • Perform any required user-based initialization to enable the connector to service subsequent Hub requests. These requests may be for extracting Hub domains, or for creating, updating, or deleting records.

  • Provide the URL of the connector instance that received the call if the connector requires all subsequent calls to be routed to the same connector instance.

  • If a connector must cache any of the parameters passed to this API to service subsequent Hub calls, it may use a combination of the syncSessionId and pimUserId. Most connectors require caching the provided domain information data for subsequent use during the synchronization session. It is considered a connector implementation detail if a stateless connector must maintain state.

  • Use the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

D.2.2 ExtractDomains API

The Engine calls ExtractDomains, an asynchronous Web service API, to request a connector to extract the given Hub domains. Extraction is the process of pulling and downloading all PIM records from the PIM store that have undergone a change. Connectors should extract all of the PIM records that have been modified since the last synchronization state, which is provided by the Hub for each user and domain at the beginning of the synchronization session when the Hub calls InitializeUserSyncSession. Each PIM record should be converted to a Hub format as defined in Chapter 8, "Mapping Connector Fields to Hub Fields". The Hub-formatted records are provided to the Hub through the ExtractDomainResultsCallback API.

Table D-3 Parameters of the ExtractDomains API

Parameter Data Type Type Description

extractRequest

ExtractRequest

[in]

Contains information related to the user and domains that need extraction. This parameter must not be null.

The ExtractRequest members must meet the following criteria:

  • hubUserId—The member must be non-null and nonempty.

  • pimUserId—This member must be non-null and nonempty.

  • hubDomainArray—This member must not be null. Each element in the array must be a non-null and nonempty string containing a single Hub Domain ID.

hubContext

HubContext

[in]

Contains context information that a connector may require to service the extract request. Must not be null.

The HubContext members must meet the following criteria:

  • engineEndPointURL—This member must be non-null and nonempty.

  • syncSessionId—This member must be non-null and nonempty.

  • connectorRuntimeLibraryURL —This member must be non-null and nonempty.

  • connectorName—This member must be non-null and nonempty.


Connectors must implement this method as a nonblocking asynchronous method. The implementation should ensure data extractions for each domain on a separate connector-owned thread, as opposed to performing the extraction on the thread of the calling Web service.

D.2.2.1 Engine Contract

The Engine performs the following when it calls the ExtractDomains API.

  • Ensures a successful call to InitializeUserSyncSession has been made for the given Synchronization Session before calling this API.

  • Analyzes the ExtractResponses obtained from all connectors; resolve conflicts, and push Create, Read, Update, and Delete operations to other PIM servers through other PIM connectors.

  • Maintains mappings of PIM records that have been exported from one system and imported to another.

  • Ensures that the ExtractResponses provided by a connector are asynchronously processed.

  • Provides the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL. The same URL is provided in each subsequent call to the connector during the same synchronization session.

  • Provides the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName.

Note:

The array of Hub domains contained in the ExtractRequest must be a subset of the Hub domains specified in the Hub call to InitializeUserSyncSession during the same synchronization session.

D.2.2.2 Connector Contract

The connector responds as follows to the ExtractDomains API:

  1. Extracts all records from the PIM store belonging to a domain for the given PIM User ID and PIM Domain Target since the last synchronization state. Connector implementations should extract each domain in the given domain array on separate threads and make asynchronous callbacks to the Engine using the callback URL contained in the given HubContext structure. The ExtractResponse should not include the following types of updated PIM records:

    1. Any records in the same PIM Domain Target that are not part of the domain must be ignored. For example, it is possible for an Exchange E-mail item (IPM.Note domain) to reside in the Task folder (IPM.Task). In this case, the Exchange 2007 Connector must ignore the IPM.Note item when extracting Task.

    2. Any records that are filtered out by the PIM Filter Condition.

  2. Provides ExtractResponses to the Hub for each Hub domain specified in the request. For each PIM record that has been modified since the last synchronization state, there should be one UpsertRecord containing a Hub representation of the modified PIM record. There should also be one PIM Record ID for each record that has been deleted from the PIM server since the last synchronization state.

  3. Each connector has a BDSS profile parameter configuration called Extract Response Batch Size. The value of this parameter contains the maximum number of records that each ExtractResponse can have. Connectors should be written to provide a series of ExtractResponses where each ExtractResponse contains this maximum number of records. The Engine uses the receipt of these batches to reset internal timeouts used for determining connector failures, such an abnormal termination of a connector. For example, if a connector must extract 5,000 calendar records and the connector's configured batch size is 100, then the connector performs at least 50 callbacks to the Engine.

    Note:

    For Oracle Fusion Middleware 11g release 1, BDSS does not support receiving multiple ExtractResponses for each Hub domain. Therefore, the connector configuration for the Extract Response Batch Size should be large enough such that extraction of any domain for any user results in a single ExtractResponse.

  4. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  5. Constructs a PIM Record Description for each extracted record.

  6. If extraction of any record fails, the connector should terminate the extraction and notify the Hub through the ExtractDomainResultsCallback API. The connector must provide an indication of the error by setting the result code to indicate an error and providing a error description string so the Hub can log information about the failure.

  7. As indicated in the PIM Filter condition definition, the connector must ensure to evaluate the configured filter to each record extracted to determine whether the record should be synchronized.

    Note:

    For Oracle Fusion Middleware 11g release 1 of BDSS, connectors should include which PIM date field is used for comparisons against the PIM Filter Condition in the software code. If the PIM record does not contain a value for the PIM date field that is used in the comparison, then the record should be included in the ExtractResponse.

    For more information about how connectors apply filters, see Section D.2.2.3.3, "Preventing the Download of Incorrect Records."

  8. For every inbound record extracted, the connector must convert it from the native PIM API format to an XML message that conforms to a PIM XML schema (XSD file) defined for the PIM domain. After the PIM XML message is constructed, the connector must then transform the PIM XML message to a Hub XML message that conforms to a provided Hub XML schema (XSD) using XSL transformations. Because the connector does not know which PIM field is mapped to which Hub PIM, nor how the data is to be translated, it cannot convert directly from PIM API format to Hub XML format. See also Section 8.1, "Overview of Data Transformation."

  9. Perform echo suppression and remove all echoes from the collection of records extracted from the PIM server before providing the record set to the Hub through the ExtractDomainResultsCallback API. If any echoes are removed, then the connector must set the echoesSuppressed flag member of the ExtractResponseMetadata to TRUE when providing the echo-less record set to the engine.

  10. Some connectors may be required to maintain state across BDSS calls while others may not. Regardless of whether a connector maintains state, it must meet the contractual agreements with BDSS related to saving synchronization state. Therefore, the following APIs are provided to facilitate saving of synchronization state for stateful and stateless connectors:

    1. If the connector is stateless, it should cache the synchronization state through CacheTempSyncState as soon as it collects the final batch of modified records from the PIM server and just before providing the batch to BDSS. When the Hub completes the domain synchronization, it calls EndDomainSynchronization and indicate whether the synchronization state must be saved. If so, the connector must commit the cached synchronization state by calling CommitCachedSyncState.

    2. If the connector maintains state information between BDSS calls, it should use only the SaveSyncState API to directly save the synchronization state when BDSS calls EndDomainSynchronization and indicates that the synchronization state should be saved.

  11. Delete Detection.

    The Hub provides support for the following two delete use cases for connectors:

    1. Use Case 1: A connector cannot natively detect delete operations. In this case, connectors can determine which records have been deleted from their PIM server by building an array containing all the PIM Record Identifiers for the given user and domain. (This array should contain record identifiers for modified and unmodified records.) The connector can provide this array of record identifiers to the Connector Run-Time Interface method GetDeletesByIds to obtain an array of record identifiers that identify deleted records. The connector can then add these record identifiers to the deleteRecordIdArray of the ExtractResponseData member of the ExtractResponse. If the connector does not have the ability to query for all the record identifiers, then the connector cannot synchronize delete operations.

    2. Use Case 2: A connector cannot natively detect deletions of records created by BDSS when an end user deletes the record before a subsequent synchronization session.

      Because the synchronization state tracks the records that have been successfully exported from the PIM, some connectors cannot detect the deletion because the just-created record is deleted from the PIM store before being exported from the store (that is, the record has been imported to the store, but never exported, so the synchronization state may not detect the deletion).

      This use case is the equivalent of an end user creating a record and then deleting it in the PIM whereby both operations occur outside the scope of a synchronization session. For example, if BDSS synchronizations occur every 5 minutes, then a user could use Outlook to create and delete a record in Exchange before the 5 minutes elapses. When that user is synchronized, the synchronization state would not capture the record as having been created and then deleted. In other words, the synchronization state is not necessarily a historical record of operations done on the PIM store. In the context of BDSS, the only difference is that BDSS performs the record creation.

      The connector must be able to identify echoes to leverage this feature. In this case, as the connector performs echo suppression, the connector builds an array containing PIM Record Identifiers that identify the echoes and then calls the GetDeletesByPendingCreateEchoes to obtain the record IDs of deleted records. The connector can then add these record identifiers to the deleteRecordIdArray of the ExtractResponseData member of the ExtractResponse.

  12. This API is asynchronous. The connector implementation should do as little preprocessing of the request as possible and return control to the Hub. That is, the API should post the extract request (or metadata about the request) to a connector-owned thread and then return control to the Hub. In this way, the more time-consuming operation of extracting PIM data occurs on a connector-owned thread. If the connector successfully receives the Web service call, it is free to throw exceptions. However, it should only throw exceptions if the preprocessing fails. After the API returns, the threads that performs the extraction should provide the Hub with an ExtractResponse for each Hub domain that indicates success or failure through the ExtractDomainResultsCallback API.

  13. Use the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library. Both the RTL URL and the connector name are provided in the HubContext structure.

Return Value

void

Exceptions

If the connector cannot post the extract request to a connector-owned thread, it should throw an exception and provide a message identifying the problem. This action enables BDSS to log the message.

D.2.2.3 Best Practices for ExtractDomains

This section describes the best practices for ExtractDomains. Topics include:

D.2.2.3.1 Economical Extracts

Connectors should predetermine whether there are any changes that require extraction for a given domain, because performing a PIM extract where no changes exist is a resource-intensive and time-consuming operation. For example, when the Engine calls the connector to extract a domain, the connector then associates the user to a connector application and then allocates numerous MAPI resources, only to discover that there are no changes. As a more economical approach, the connector associates the user with an application whose only function is issuing a WebDAV request to the Exchange server that queries for changes since the last synchronization state.

D.2.2.3.2 Caching PIM Field Definitions

Connectors should obtain PIM field definitions and other domain-related configuration information through the Connector Run-Time Interface method, GetPimDomainMetadata, and cache them for use during the extract cycle.

D.2.2.3.3 Preventing the Download of Incorrect Records

When extracting the calendar and task domains, apply the pimFilterCondition in a manner that prevents records from being downloaded from the server if they fail to the meet the criteria of the filter. For example, a connector could do a brute force method of filtering records by first downloading all changed records from the server and then evaluating every record against the filter to determine if it should be included in the extract result set. A better method is to apply the filter in a manner that prevents those records from being downloaded from the PIM server at all. For example, MAPI restriction constructs are used for the Exchange 2007 Connector to prevent the downloading of old records.

D.2.3 EndDomainSynchronization API

The Hub calls this EndDomainSynchronization interface to end the domain synchronization for a given user. This interface may be called to terminate a synchronization session gracefully (or not gracefully) for a user's Hub domain.

Table D-4 Parameters of the EndDomainSynchronization API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

[in]

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains the URL to the connector run-time interface that the connector should use for the given synchronization session.

hubDomain

String

[in]

Identifies the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

[in]

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

[in]

Contains the PIM User ID. This parameter must be non-null and nonempty.

saveSyncState

Boolean

[in]

A Boolean value that indicates whether the connector should save the synchronization state

extractResponseCount

Integer

[out]

Contains the number of batches that the connector successfully sent to the Hub for the given domain and user for a particular synchronization session. For Oracle Fusion Middleware 11g release 1 of BDSS, this parameter is either 0 or 1.


D.2.3.1 Engine Contract

The Engine performs the following when it calls the EndDomainSynchronization API:

  1. Calls this method at the conclusion of processing the given domain.

  2. Indicates whether the connector should save the synchronization state. Sets the flag to False if:

    • The domain was never extracted during the current synchronization session.

    • The domain was extracted and the connector provided an ExtractResponse containing 0 records and an echoesSuppressed flag of false. In this case, no records were extracted (echoes or otherwise).

      Note:

      The connector sets the echoesSuppressed flag in the ExtractResponse indicating whether the ExtractResponse had echoes removed. For Oracle Fusion Middleware 11g release 1 of BDSS, the Hub does not support receiving multiple ExtractResponses for a single Hub domain.

  3. Uses the extractResponseCount for cleaning up ExtractResponses that may have been received by the Hub when errors occur.

  4. Provides the Connector Run-Time Library URL used by the connector for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL

  5. Provides the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName.

D.2.3.2 Connector Contract

A connector responds as follows when the Engine calls the EndDomainSynchronization API:

  1. Cleans up any domain-level resources related to the user, if appropriate.

  2. If saveSyncState is true, the connector saves the domain synchronization state to the Hub data store through a Connector Run-Time Interface API as indicated in the connector contract section of the ExtractDomains API.

  3. Ensures that no further ExtractResponses are sent to the Hub even in a scenario where the Hub calls the API to terminate the synchronization session non-gracefully.

  4. Ensures that extractResponseCount is always populated with the correct number of successfully sent ExtractResponses to the Hub for the given Synchronization Session.

  5. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  6. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Note:

The connector should perform a do-nothing operation (no-op) on this call if the Hub calls it for a user session of which the connector is unaware. This may occur, for example, if the Hub decides to terminate a synchronization session due to another connector failure. This helps to simplify the Hub logic when the Hub must terminate a synchronization session abruptly.

Return Value

Integer

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

D.2.4 EndUserSyncSession API

The Engine calls the EndUserSyncSession interface at the conclusion of synchronizing all domains for the given user to end the synchronization session identified by the given syncSessionId. Connector implementations can use this opportunity to free any user-specific resources that may have been associated with the given user. Table D-5 lists the parameters of the EndUserSyncSession interface.

Table D-5 Parameters of the EndUserSyncSession API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

[in]

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains the URL to the Connector Run-Time Interface that the connector should use for the given synchronization session

hubUserId

String

[in]

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

[in]

Contains the PIM User ID. This parameter must be non-null and nonempty.


D.2.4.1 Engine Contract

The Engine performs the following when it calls the EndUserSyncSession API:

  1. Does not call the connector for the same user until another synchronization session has started.

  2. Calls this API to end the synchronization session identified by the given syncSessionId.

  3. Provides the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  4. Provides the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName parameter.

D.2.4.2 Connector Contract

The connector responds as follows when the Engine calls the EndUserSyncSession API:

  1. Cleans up all resources related to the user.

  2. Uses the provided Synchronization Session ID, Hub domain and Hub User ID in logging statements.

  3. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

Note:

The connector should perform a do-nothing operation (no-op) on this call if the Hub calls it for a user session of which the connector is unaware. This may occur, for example, if the Hub decides to terminate a synchronization session due to another connector failure. This helps to simplify the Hub logic when the Hub must terminate a synchronization session.

D.2.5 CreateRecord API

The Hub calls the CreateRecord interface any time a record must be created in the PIM. Table D-6 lists the parameters of the CreateRecord interface.

Note:

The Hub can call this API even if the domain has not been extracted.

Table D-6 Parameters of the CreateRecord API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

[in]

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains the URL to the connector run-time interface that the connector should use for the given synchronization session when calling the run-time library

hubDomain

String

[in]

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

[in]

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

[in]

Contains the PIM User ID. This parameter must be non-null and nonempty.

hubRecord

upsert record

[in/out]

On input, contains the Hub record in Hub XML format. The RecordMetadata member must be null. On output, the RecordMetadata is allocated and populated by the connector to contain:

  • PIM Record ID—A required parameter, which must be non-null and nonempty.

  • PIM Record Associated Data— An optional parameter, which may be null. If non-null, at least one of the associated data members must be non-null and nonempty.

  • PIM Record Version ID—A required parameter, which must be non-null and nonempty

  • Optionally, set recordError to true if the connector failed to create the record and specify a recordErrorDescription.

  • PIM Record Description—This parameter (one that is optional and configuration-driven) may be null if no KeyField configuration is available for the Hub domain. If the KeyField configuration does exist for the Hub domain, the array must not be null. Each KeyValuePair in the description array must have a key that is non-null and nonempty and also a value that also must be non-null and nonempty.


D.2.5.1 Engine Contract

The Engine performs the following when it calls the CreateRecord API:

  1. After returning from this connector API call, the Engine must update its data store with the following data contained in the provided RecordMetadata member of the UpsertRecord:

    • The PIM Record ID

    • The PIM Record Version ID

    • The PIM Record Associated Data (if provided)

    • The PIM Record Description (if provided)

  2. In addition to updating the Hub data store to contain the metadata, the Engine must also set the echoPending flag in the store for the given row to TRUE if the record was created successfully.

  3. Provide the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  4. Provide the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName.

D.2.5.2 Connector Contract

The connector responds as follows when the Engine calls the CreateRecord API:

  1. Creates the record in the PIM store and provide the metadata as indicated in Table D-6.

  2. Translates Hub-formatted XML messages to a format suitable for creating a record in the PIM server.

  3. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  4. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Return Value

Integer

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

D.2.6 UpdateRecord API

The Engine calls the UpdateRecord interface anytime that a record must to be updated in the PIM server. Table D-7 lists the parameters of the UpdateRecord method.

Note:

The Hub can call this API even if the domain has not been extracted.

Table D-7 Parameters of the UpdateRecord API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains the URL to the Connector Run-Time Interface that the connector should use for the given synchronization session when calling the run-time library

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

hubRecord

UpsertRecord

In

Contains the Hub record and metadata, obtained from the Hub data store, about the record to be updated

The RecordMetadata member must not be null and should be populated by the Hub with the connector-specific metadata.

updatedMetadata

RecordMetaData

Out

On output, contains updated record metadata, obtained from the PIM Record that includes:

  • PIM Record ID: This is a required parameter. This parameter must be non-null and nonempty.

  • PIM Record associated data: This parameter is optional and may be null. If it is non-null, then at least one of the associated data members must be non-null and nonempty.

  • PIM Record Description: This parameter (one that is optional and configuration-driven) may be null if no KeyField configuration is available for the Hub domain. If the KeyField configuration exists for the Hub domain, then the array must not be null. Each KeyValuePair in the description array must have a key that is non-null and nonempty and a value that is non-null and nonempty.

  • Optionally set recordError to true if the connector failed to create the record and specify a recordErrorDescription

  • PIM Record Version ID (required). This parameter must be non-null and nonempty


D.2.6.1 Engine Contract

The Engine performs the following when it calls the UpdateRecord API:

  1. The Engine performs the following when resolving conflicts detected when evaluating extract responses:

    1. For an Update/Update Conflict, the Hub should provide the losing connector with the AssociatedData from the BDSS store and not the AssociatedData provided in the extracted record when calling this API on the losing connector.

    2. For a Create/Create Conflict, the Hub should use the AssociatedData provided in the extracted record from the losing connector when calling this API on the losing connector.

  2. In addition to updating the data store to contain the metadata, the Engine must also set the echoPending flag in the store for the given row to FALSE if the record was successfully updated.

  3. Provide the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  4. Provide the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connector name.

D.2.6.2 Connector Contract

The connector responds as follows when the Engine calls the UpdateRecord API:

  1. Updates the record identified by the given PIM Record ID in the PIM server and populates the RecordMetaData structure.

  2. If the record is deleted in the PIM server after extraction by BDSS before the connector processes the update, the connector should provide some indication (that is, a log message) that the update was ignored because the record was deleted. (A subsequent extract cycle should detect the delete operation and propagate it to the Engine.)

  3. If the PIM API can detect conflicts that may occur if the PIM record changes just before pushing an outbound update, the connector should resolve the conflict in a "BDSS wins" fashion (that is, the record that BDSS gave to the connector should overwrite the end user's changes).

  4. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  5. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

D.2.7 DeleteRecord API

The Engine calls the DeleteRecord API whenever a record must be deleted from the PIM server. Table D-8 lists the parameters of the DeleteRecord method.

Note:

The Hub can call this API even if the domain has not been extracted.

Table D-8 Parameters of the DeleteRecord API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

 

Contains the URL to the Connector Run-Time Interface that the connector should use for the given synchronization session when calling the Connector Run-Time library.

hubDomain

String

[in]

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

pimRecordId

String

In

Contains the PIM Record ID of the record to delete. This parameter must be non-null and nonempty.

pimRecordDescription

PIM Record Description

In

Contains the PIM Record Description


D.2.7.1 Engine Contract

The Engine performs the following when it calls the DeleteRecord API:

  1. Provides the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  2. Provides the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName parameter.

D.2.7.2 Connector Contract

The connector responds as follows when the Engine calls the DeleteRecord API:

  1. Deletes the record in the PIM identified by the given PIM Record ID.

  2. If a connector needs the PIM Record associated data, it may obtain it through the Connector Run-Time Interface method, GetRecordAssociatedData. Most PIM servers need only the PIM Record ID.

  3. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  4. Returns a non-error code if the PIM record is deleted before sending the delete to the PIM. The connector may log a message indicating that the delete failed because the record had been deleted previously.

  5. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

D.2.8 GetPimServerEndPoint API

The Hub calls the GetPimServerEndPoint interface to obtain the PIM Server Endpoint for a given synchronization-enabled user and uses the returned endPointToken to determine which connector instance in a cluster of connectors should be called when synchronizing a user during a synchronization session. Table D-9 lists the parameters of the GetPimServerEndPoint interface.

Table D-9 Parameters of the GetPimServerEndPoint Interface API

Parameter Data Type Type Description

connectorName

String

[in]

Contains the connector name. This parameter must be non-null and nonempty.

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

rtlUrl

String

[in]

Contains the URL to the Connector Run-Time Interface the connector should use for the given synchronization session when calling the Connector Run-Time Library.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

endPointToken

String

Out

On output, contains a connector-defined endpoint token. This parameter can be NULL. It can also be empty.

canSyncUser

Boolean

Out

On output, indicates whether the receiving connector can synchronize the given user


D.2.8.1 Engine Contract

The Hub calls the GetPimServerEndPoint API only when it must obtain the PIM Server Endpoint for a user. The Hub performs the following when it calls this API:

  1. Uses configuration metadata and the returned endPointToken and the canSyncUser to determine which connector should be called to extract the given user. The Hub should first check the endPointToken. If the endPointToken value is a non-NULL and nonempty string, then the Hub should use the endPointToken value to obtain the connector URL to use to synchronize the user. If it is NULL or is empty, the Hub should then check the Boolean value to determine if the receiving connector that returned the Boolean value can be used to synchronize the user.

  2. Provide the Connector Run-Time Library URL that the connector should use for a given user and synchronization session. If a connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided URL.

  3. Provide the connector name. If the connector must call the Connector Run-Time Library as part of its implementation of this method, it should use the provided connectorName.

D.2.8.2 Connector Contract

The connector that receives the GetPimServerEndPoint API call performs the following:

  1. Resolves the PIM Server Endpoint for the given user. If the connector cannot resolve the given user, it should return an error.

    Note:

    The receiving connector instance may not be the same instance that performs the synchronization of the user (or even in the same cluster).

    The PIM Server Endpoint value (endPointToken) is a connector implementation detail. Developers must document the PIM server endpoint values so that administrators can correctly map the URLs to the endpoints. For example, for Exchange, the connector returns the NetBios name of the Exchange server hosting the given users mailbox. Therefore, an administrator must map these Exchange server NetBios names to the cluster URLs.

  2. Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.

  3. Uses the provided RTL (Run-Time Library) URL and connector name if the connector must call the Connector Run-Time Library.

Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

D.3 Engine Callback Interface API

The Engine Callback Interface is a Web service-based interface consisting of a single method, ExtractDomainResultsCallback, that a connector calls when it wants to provide the Hub with an ExtractResponse.

D.3.1 ExtractDomainResultsCallback API

The ExtractDomainResultsCallback API is asynchronous and returns immediately to the calling connector after the Engine queues the information provided in the given ExtractResponse. Table D-10 lists the parameters of the ExtractDomainResultsCallback method.

Table D-10 Parameters of the ExtractDomainResultsCallback API

Parameter Data Type Type Description

extractResponseData

ExtractResponse

In

Contains a batch of records provided by a connector


D.3.2 Engine Contract

When the Engine calls the ExtractDomainResultsCallback API, it queues the ExtractResponse and returns immediately.

D.3.3 Connector Contract

The Connector performs the following in response to the Engine's ExtractDomainResultsCallback API call:

  • When the connector extracts records from the PIM and builds the given ExtractResponse, it must remove any echoes from the response before calling this API and it must set the echoesSuppressed flag to true if echoes were removed.

  • The connector must specify a sequence number of the ExtractResponse. The first extract response is numbered 1, the second is numbered 2, and so on. For Oracle Fusion Middleware 11g release 1 of BDSS, the sequence number is always 1.

Return Value

void

D.4 Connector Run-Time Interface API

The Connector Run-Time Interface is a Web service-based API that allows connectors to access certain metadata, such as AssociatedData, in the Hub data store. This interface provides services that are common to all connectors, such as saving synchronization state.

This interface is not implemented by connector authors. Connector implementations are the consumers of this interface.

In general, all APIs return an integer to indicate success (0) or failure (nonzero). All APIs can throw a RemoteException when irrecoverable errors occur, such as the inability to read or write to the BDSS store or invalid parameters. Developers should write connectors to account for exceptions and the return value to determine the overall success of the API call.

D.4.1 GetPimRecordVersions API

The GetPimRecordVersions method enables a connector to retrieve the PIM Record Version ID of one or more PIM records stored in the BDSS data store. Retrieving this information enables the connector to determine the last version of a PIM record (or PIM records) that BDSS has synchronized successfully.

Table D-11 Parameters of the GetPimRecordVersions API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimRecordIdArray

String []

In

Contains an array of PIM Record IDs for which the connector wants to retrieve the version ID.

pimRecordVersionIdArray

String []

Out

On output, contains the PIM Record Version ID of each record specified in the pimRecordIdArray. There is a positional relationship between pimRecordIdArray and pimRecordVersionIdArray in that the ith element in pimRecordVersionIdArray contains the Version ID corresponding to the ith element in pimRecordIdArray. The ith element in pimRecordVersionIdArray is a non-null empty string when either of the following conditions are true:

  • The ith element in pimRecordIdArray is not found in the BDSS store.

  • The ith element in pimRecordIdArray is found in the BDSS store but has a null version, which may occur when a failure is detected in a previous synchronization session.

When a synchronization session completes without failures, a non-empty Version ID is provided for the ith element in the pimRecordVersionIdArray.

A connector should echo suppress a PIM record if the GetPimRecordVersions method returns a corresponding Version ID that is identical to the Version ID of the PIM record. As a corollary, a connector should not echo suppress a PIM record if the GetPimRecordVersions method returns the corresponding Version ID as an empty string.

The ith element in pimRecordVersionIdArray is never returned as null for a corresponding ith element in pimRecordIdArray.


Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.2 CacheTempSyncState API

The CacheTempSyncState method saves the given synchronization state to a temporary data location in the BDSS store. Connectors that do not maintain state call this method after extracting the PIM data for the given domain, but before providing the last batch of records to BDSS.

Table D-12 Parameters of the CacheTempSyncState API

Parameter Data Type Type Description

syncSession

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimDomainTarget

String

In

Contains the PIM Domain Target. This parameter must be non-null and nonempty.

pimDomainSyncState

String

In

Contains the synchronization state that is to be cached for the given user, domain, domain target, and server type


Returns Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzerofor ERROR

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.3 CommitCachedSyncState Method API

The CommitCachedSyncState method saves the synchronization state that was previously stored in a temporary location in the BDSS store to a permanent location in the BDSS store. It is intended to be used by connectors that cannot maintain state information across BDSS calls.

A connector must have successfully called CacheTempSyncState during the same synchronization session before calling this method. Typically, a stateless connector calls CacheTempSyncState just before completing an extraction of the data for a particular domain. It then calls this method when the Hub calls EndDomainSynchronization, indicating that the synchronization state should be saved. Table D-13 lists the parameters of the CommitCachedSyncState method.

Table D-13 Parameters of the CommitCachedSyncState API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimDomainTarget

String

In

Contains the PIM Domain Target. This parameter must be non-null and nonempty.


Return Value

Integer

  • 0 for SUCCESS/OK

  • Nonzero for ERROR

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.4 GetConfigurationMetaData API

Connectors call the GetConfigurationMetaData API to get profile configuration metadata. A profile can have one or more sections. Each section can contain one or more parameters and each parameter can have a single value. The profile is conceptually equivalent to a Windows .ini configuration file. BDSS connectors can define their own profiles to store metadata specific to the connector. Table D-14 lists the parameters of the GetConfigurationMetaData method.

Table D-14 Parameters of the GetConfigurationMetaData API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

configMetadataArray

ConfigurationProfile []

In/Out

On input, contains an array of ConfigurationProfile structures populated with profile metadata that is to be obtained. On output, the array is updated to contain the requested profile metadata.


The GetConfigurationMetaData API enables a connector to obtain an arbitrary amount of configuration metadata across multiple profiles in a single call. The connector creates and populates the configMetadataArray parameter, indicating what the connector wants to obtain, and the API populates the configMetadataArray with the requested configuration (if the configuration exists).

Basically, the connector builds an array of ConfigurationProfile structures and populates them in a manner that scopes which configuration is obtained and the GetConfigurationMetaData API finishes populating the structures. Scoping can be done on a profile, session, or parameter basis. For example, if the connector requires an entire section of a profile, it builds a ConfigurationProfile structure and specifies only the intended Profile Name and Section Name and adds the ConfigurationProfile to the configMetadataArray. Similarly, if a connector requires a single parameter of a section of a profile, it builds a ConfigurationProfile that specifies the Profile Name, Section Name, and Parameter Name and adds it to the configMetadataArray.

Table D-15 outlines some common use cases of how a connector builds the configMetadataArray to obtain configuration metadata and how the GetConfigurationMetaData API updates the configMetadataArray.

Table D-15 ConfigMetadataArray Use Cases

Use Case Connector Builds configMetadataArray [in] API Updates configMetadataArray[out]

Obtain a specific parameter value for a particular section in a particular profile

Scope is Profile.Section.Parameter

Array has a size of 1 and contains a single ConfigurationProfile structure that is populated as follows:

ConfigurationProfile:

  • The profile name member is populated.

  • The configSectionArray member is populated with a single ConfigurationSection structure.

ConfigurationSection:

  • The section name member is populated.

  • The paramNameValueArray member is populated with a single KeyValuePair structure.

KeyValuePair:

  • The key member is populated to contain the name of the parameter to be obtained.

Updates the value member of the paramNameValueArray to contain the parameter value. That is, configMetadataArray[0].configSectionArray[0].paramNameValueArray[0].value.

Obtain parameter names and values of a section in a profile. The scope is Profile.Section.

Array has a size of 1 and contains a single ConfigurationProfile structure populated as follows:

ConfigurationProfile:

  • The profile name member is populated.

  • The configSectionArray member is populated with a single ConfigurationSection structure.

ConfigurationSection:

Array has a size of 1 and contains a single ConfigurationProfile structure the is populated as follows:

  • The section name member is populated.

  • paramNameValueArray is an empty array.

Updates the paramNameValueArray member of the ConfigurationSection. (That is, configMetadataArray[0].configSectionArray[0].paramNameValueArray is allocated and populated with all the parameters and values in the section.)

Get all parameter names and values of all sections in a profile. The Scope is Profile.

An array has a size of 1 and contains a single ConfigurationProfile structure populated as follows:

ConfigurationProfile:

  • The profile name member is populated.

  • The configSectionArray member is an empty array.

ConfigurationSection:

Null

The configSectionArray is allocated and populated with a ConfigurationSection for each section in the profile.

Each ConfigurationSection is populated with the section name and the paramNameValueArray is populated to contain the parameter and values of each configuration option in the section.

Get all parameter names and values of all sections in multiple profiles.

The scope is Multiple Profiles.

The same builds as the Profile scope, but the array size is greater than 1 (that is, there is 1 ConfigurationProfile element in the array for each profile requested).

The same builds as the Profile scope, but each ConfigurationProfile member in the array is updated.


Return Value

Integer:

  • 0 for SUCCESS/OK.

  • Nonzero for ERROR.

The GetConfigurationMetaData API returns an error only in cases where it cannot obtain any metadata from the BDSS store because of disruptive circumstances, such as the store not being available or having insufficient memory. It does not return an error if it cannot obtain a particular configuration value, section, or profile. The connector determines whether failure to get a particular configuration metadata value is, in fact, a failure. For example, a connector may want to retrieve the extract response batch size from one of its sections in a connector profile. Assuming that no extraneous events occur, and the customer failed to configure this value, the API returns a SUCCESS/OK error code and leave the corresponding value as it is. (That is, it may be null or empty, depending on the connector configuration values set for the extract response batch size). At this point, the connector decides the severity of the configuration error and handles it appropriately For example, it could log an error or warning message and use a default value even though it does not consider it an irrecoverable error that stops the connector functioning. It could also log an error or warning and consider it an irrecoverable error.

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.5 GetDeletesByPendingCreateEchoes API

A connector calls the GetDeletesByPendingCreateEchoes API if it cannot natively detect deletions of Hub-created records when the delete operation occurs after the Hub creates the record in the current synchronization session and before a subsequent synchronization session after record creation. Table D-16 lists the parameters of the GetDeletesByPendingCreateEchoes API.

Table D-16 Parameters of the GetDeletesByPendingCreateEchoes API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

echoIdArray

String []

In

Contains an array of PIM Record IDs, where each identifies an echo. This parameter must not be null. The array must have a length >= 1. The Hub ignores any entries that are empty strings or -1, as the PIM Record ID. If a connector has no echoes, it must still provide an array. Oracle recommends an array size of 1 (one) that contains an empty string as the PIM Record ID.

upsertIdArray

String []

In

Contains an array of PIM Record IDs, where each identifies a record that has been updated or created in the PIM since the last Synchronization State. Must not be null. The array must have a length >= 1. The Hub ignores any entries that are empty strings or -1 as the PIM Record ID. If a connector has no upsert records, it must still provide an array with a recommended array size of 1 containing an empty string as the PIM Record ID.

deleteRecordIdArray

String []

Out

On output, contains a PIM Record ID for each record identified as being deleted from the PIM. If there are no delete operations detected, the returned array is null.


Return Value

Integer

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.6 GetDeletesBylds API

A connector calls the GetDeletesBylds method if it cannot natively detect deletions from its PIM server. This method queries the Hub store for a list of PIM Record IDs for the given user, the Hub domain, and the connector name that have been synchronized previously. It then compares the Hub store-based array against the connector-provided array to build an array of PIM Record IDs that identify the records that have been deleted. Any PIM Record IDs in the Hub store-based array that are not in the array provided by the connector are considered deletes. Table D-17 lists the parameters of the GetDeletesByIds method.

Table D-17 Parameters of the GetDeletesBylds API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. Must be non-null and nonempty.

recordIdArray

String[]

In

An array containing the PIM Record IDs of all PIM records for the given user, domain, and server type. This parameter must not be NULL. If there are no PIM records in the PIM, the connector should provide an array of size 1 containing an empty string as the PIM Record ID.

deleteRecordIdArray

String[]

Out

On output, contains an array of PIM Record IDs identifying records that have been deleted from the PIM. If none are detected, then the array returned is null.


Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.7 GetRecordAssociatedData API

Connectors call the GetRecordAssociatedData API to obtain the PIM Record associated data that is associated with a record from the Hub data store. This is useful for connectors that associate data with PIM records. For example, a connector can associate some data with each PIM record to help facilitate echo detection and obtain that data using this API. Table D-18 lists the parameters of the GetRecordAssociatedData API.

Table D-18 Parameters of the GetRecordAssociatedData API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. Must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. Must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. Must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. Must be non-null and nonempty.

connectorName

String

In

Contains the connector name. Must be non-null and nonempty.

pimRecordIdArray

String []

Out

An array containing the PIM Record ID of each record whose PIM Record Associated Data is to be retrieved. This parameter must be non-null and have a size > 0. Each element of the array must be non-null and nonempty.

pimRecordAssocDataArray

String []

Out

On output, this array contains the PIM Record Associated Data of each record specified in the pimRecordIdArray.

There is a positional relationship between the elements of pimRecordIdArray and the elements of pimRecordAssocDataArray. The AssociatedData for the ith element in pimRecordIdArray is located in the ith element of pimRecordAssocDataArray. If the ith element in pimRecordIdArray identifies a record that has no PIM Record Associated Data, the ith element in this array contains an empty AssociatedData element (that is, the structure is be allocated but the members of the structure are null).

errorArray

String []

 

On output, an array consisting of success or error codes. There is a positional relationship between this array and pimRecordAssocDataArray. The ith error code corresponds to the success or failure of getting the ith AssociatedData. (

0 = OK, 1 = ERROR, 2 = Data does not exist in DB)


Return Value

Integer:

  • 0 for SUCCESS/OK. If all of the AssociatedData were read from the data store.

  • Nonzero for ERROR/NOTOK. If any of the AssociatedData elements failed to be read. The caller examines errorArray to determine which elements failed to be read and the connector determines the severity of the error. The error codes in the errorArray may contain more explicit error codes.

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.8 GetSyncState API

A connector calls the GetSyncState API to obtain connector-defined synchronization state associated with a domain. This method only returns the synchronization state stored in the permanent data store location. See CacheTempSyncState API, CommitCachedSyncState Method API, and SaveSyncState API for more information about permanent and temporary Synchronization State. Table D-19 lists the parameters of the GetSyncState API.

Table D-19 Parameters of the GetSyncState API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimDomainTarget

String

In

Contains the PIM Domain Target. This parameter must be non-null and nonempty.

pimDomainSyncState

String

In

On output, contains the synchronization state for the given user, domain, domain target, and server type. If no synchronization state exists for the given user, domain, connector name, and domain target, the return value is null.


Return Value

Integer

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

Exceptions

A RemoteException is thrown if an irrecoverable error occurs or if there is no synchronization state.

D.4.9 GetUserAssociatedData API

The connector calls the GetUserAssociatedData API to obtain user level, connector-specific PIM User Associated Data. The API does not prevent multiple threads from accessing a given user's associated data. Table D-20 lists the parameters of the GetUserAssociatedData API.

Table D-20 Parameters of the GetUserAssociatedData API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

assocDataIdArray

String

In

Contains an array of connector-defined user associated data identifiers.

pimUserAssocDataArray

Associated Data []

Out

On output, contains the user-specific associated data. There is a positional relationship between this array and assocDataIdArray. The ith element of pimUserAssocDataArray contains the PIM User associated data of the ith element indicated in assocDataIdArray.

errArray

Integer []

Out

On output, contains an array of error codes indicating the success or failure of getting the PIM User associated data. The ith element in errArray holds the success or failure code of obtaining the ith element indicated in pimUserAssocDataArray.0 = OK, 1 = ERROR, 2 = Data does not exist in DB.


Return Value

Integer:

  • 0 for SUCCESS/OK. (If all of the AssociatedData elements were read from the data store.)

  • Nonzero for ERROR/NOTOK. If Any of the AssociatedData elements failed to be read. The caller examines errArray to determine which elements failed to be read, and the connector determines the severity of the error. The error codes in the errArray may contain more explicit error codes.

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.10 SaveSyncState API

Connectors that maintain state across BDSS calls must call this API to save the connector-defined synchronization state associated with a domain to the Hub store. Connectors that do not maintain state must use CacheTempSyncState and CommitCachedSyncState to save the synchronization state. Table D-21 lists the parameters of the SaveSyncState API.

Table D-21 Parameter of the SaveSyncState API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimDomainTarget

String

In

Contains PIM Domain Target. This parameter must be non-null and nonempty.

pimDomainSyncState

String

In

Contains the synchronization state for the given user, domain, domain target, and server type. This parameter must be non-null and nonempty.


Return Value

Integer:

  • 0 for SUCCESS/OK

  • Nonzero for ERROR/NOTOK

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.11 SetRecordAssociatedData

Connectors call the setRecordAssociatedData API to associate the connector-defined PIM Record associated data to the given record. Table D-22 lists the parameters of the SetRecordAssociatedData API.

Table D-22 Parameters of the SetRecordAssociatedData API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

pimRecordIdArray

String []

In

An array of PIM Record IDs of those records whose PIM record associated data is to be written to the BDSS data store.

pimRecordAssocDataArray

Associated Data []

In

An array containing PIM Record Associated Data of each record to be written to the BDSS data store. There is a positional relationship between the pimRecordIdArray and pimRecordAssocDataArray. The ith PIM Record ID in pimRecordIdArray must have its PIM Record Associated Data located as the ith AssociatedData in the pimRecordAssocDataArray.

errorArray

Integer []

Out

On output, an array error codes. There is a positional relationship between this array and pimRecordAssocDataArray. The ith error code corresponds to the successor failure of setting the ith AssociatedData.0 = OK, 1 = ERROR


Return Value

Integer

  • 0 for SUCCESS/OK. If all of the AssociatedData elements were written to the BDSS data store.

  • Nonzero for ERROR/NOTOK. If any of the AssociatedData elements failed to be written. Caller examines errorArray to determine which elements failed to be written and the connector determines the severity of the error.

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.4.12 SetUserAssociatedData API

Connectors call the SetUserAssociatedData API to save user-level, connector-specific PIM User Associated Data. The API does not prevent multiple threads from accessing a given user's associated data. Table D-23 lists the parameters of the SetUserAssociatedData API.

Table D-23 Parameters of the SetUserAssociatedData API

Parameter Data Type Type Description

syncSessionId

String

In

Contains the Synchronization Session ID. This parameter must be non-null and nonempty.

hubDomain

String

In

Contains the Hub domain. This parameter must be non-null and nonempty.

hubUserId

String

In

Contains the Hub User ID. This parameter must be non-null and nonempty.

pimUserId

String

In

Contains the PIM User ID. This parameter must be non-null and nonempty.

connectorName

String

In

Contains the connector name. This parameter must be non-null and nonempty.

assocDataIdArray

String []

In

An array of connector-defined users associated data identifiers.

pimUserAssocDataArray

Associated Data

In

Contains the user-specific associated data. There is a positional relationship between pimUserAssocDataArray and assocDataIdArray. The ith element of assocDataIdArray has the corresponding PIM User associated data as the ith element in this array.

errArray

Integer []

Out

On output, contains an array of error codes indicating the success or failure of setting (persisting to the BDSS store) the user associated data.There is a positional relationship between this array and assocDataIdArray and pimUserAssocDataArray. The ith element in this array holds an error code for setting the ith element of pimUserAssocDataArray.0 = OK, 1 = ERROR.


Return Value

Integer:

  • 0 for SUCCESS/OK. If all of the AssociatedData elements were written to the BDSS data store.

  • Nonzero for ERROR/NOTOK. If any of the AssociatedData elements failed to be written. The caller examines errArray to determine which elements failed to be written, and the connector determines the severity of the error.

Exceptions

A RemoteException is thrown if an irrecoverable error occurs.

D.5 Data Representation Structures

This section describes the structure of data that is passed between BDSS and the connectors.

D.5.1 Common Structures

The common structures include the KeyValuePair structure.

D.5.1.1 KeyValuePair

The KeyValuePair is a basic structure used to hold metadata in a key/value structure. It is used by many other data structures defined for the connector. Table D-24 lists the members of the KeyValuePair structure.

Table D-24 Members of the KeyValuePair Structure

Member Data Type Description

key

String

Holds the key value of a key/value pair.

value

String

Holds the value value of a key/value pair.


D.5.2 Connector Interface-Related Structures for the BDSS Engine

The connector interface-related structures include:

D.5.2.1 DomainInfo

The DomainInfo structure contains the domain information required by a connector to perform an initialization for a user for a synchronization session. This structure is used only when the Hub calls the connector InitializeUserSyncSession API. Table D-25 lists the members of the DomainInfo structure.

Table D-25 Members of the DomainInfo Data Structure

Member Data Type Description

pimDomainTarget

String

Contains the PIM Domain Target. Must be non-null. May be empty.

For more information about this member, see Section D.1.5, "PIM Domain Target."

pimFilterCondition

String

Contains a PIM filter condition that is applied to the domain extract that filters out records that should not be included in the extract. This member must be non-null. It may be empty.

hubDomain

String

Identifies the Hub domain. This member must be non-null and nonempty.

pimDomainSyncState

String

Contains the PIM synchronization state for the domain. This member must be non-null. This member may be empty.


D.5.2.2 ExtractRequest

The ExtractRequest structure is passed to the connector when BDSS begins an extraction for a user through the ExtractDomains API. Table D-26 lists the members of the ExtractRequest structure.

Table D-26 Members of the ExtractRequest Data Structure

Member Data Types Description

hubUserId

String

Contains the Hub User ID. This member must be non-null and nonempty.

pimUserId

String

Contains the PIM User ID. This member must be non-null and nonempty.

hubDomainArray

String []

An array of Hub domains. This array must be non-null and be sized >=1. Elements in the array must be non-null and nonempty.


D.5.2.3 ExtractResponse

The ExtractResponse structure is used by the connector to propagate record data and status information to the Engine through the Engine Callback interface's ExtractDomainResults callback method. Table D-27 lists the members of the ExtractResponse structure.

Table D-27 Members of the ExtractResponse Data Structure

Member Data Types Description

extractResponseMetaData

extractResponseMetaData

Contains metadata about the extract response. This member must be non-null and nonempty.

extractResponseData

extractResponseData

Contains the extracted PIM records. This member must be non-null and nonempty.


D.5.2.4 ExtractResponseData

The ExtractResponseData structure contains records extracted from a PIM server. Table D-28 lists the members of the ExtractResponseData structure.

Table D-28 Members of the ExtractResponseData Data Structure

Member Data Type Description

hasUpserts

Boolean

Indicates if the structure has an upsert record. This array has valid UpsertRecord structures.

upsertRecordArray

UpsertRecord []

An array of UpsertRecord structures. Each element in the array represents a single PIM record that has been updated or created in the PIM since the last synchronization session.

This array must be non-null and nonempty. If there are no modified records, the array should have a length of 1 and a non-null UpsertRecord containing non-null members. However, the members may have empty strings as members.

This array is ignored if hasUpserts is false.

hasDeletes

Boolean

Indicates whether deleteRecordIdArray has valid string members

deleteRecordIdArray

String []

An array of strings where each element of the array contains the PIM Record ID of a PIM record that has been deleted since the last synchronization session

Must be non-null and nonempty. If there are no deleted records, the array should have a length of 1 and a non-null PIM Record ID that can be empty.

This array is ignored if hasDeletes is false.


D.5.2.5 ExtractResponseMetaData

The ExtractResponseMetaData structure contains metadata information about a given ExtractResponseMetaData of a domain extraction. Table D-29 lists the members of the ExtractResponseMetaData structure.

Table D-29 Members of the ExtractResponseMetaData Data Structure

Member Data Type Description

syncSessionId

String

Contains the Synchronization Session ID. This member must be non-null and nonempty.

hubDomain

String

Contains the Hub domain. This member must be non-null and nonempty.

hubUserId

String

Contains the Hub User ID. This member must be non-null and nonempty.

resultCode

String

Contains one of the ExtractResultCode enumeration values.

extractErrorDescription

String

Contains a description of why an extraction failed. This member must be non-null, but may be empty. It should only be populated when the resultCode is an error code.

pimDomain

String

Contains the PIM Domain. This member must be non-null and nonempty.

pimUserId

String

Contains the PIM User ID. This member must be non-null and nonempty.

connectorName

String

Contains the connector name

echoesSuppressed

String

Indicates whether the ExtractResponse had echoes removed

sequenceNumber

String

Indicates a sequence number of the ExtractResponse. For example, when the connector sends the first ExtractResponse to the Hub, the sequenceNumber is 1. When it sends the second ExtractResponse, the sequenceNumber is 2, and so on.

The sequenceNumber starts at 1 for each domain, user and synchronization session. For Oracle Fusion Middleware 11g release 1 of BDSS, the connector Extract Response Batch Size configuration should be large enough to allow that only a single ExtractResponse is sent to the Hub for a Hub domain.


D.5.2.6 HubContext

The HubContext structure (described in Table D-30) provides the connector with information about which BDSS instance should be called when calling the Run-Time Library or the Engine Callback interfaces.

Table D-30 Members of the HubContext Data Structure

Member Data Type Description

engineEndPointURL

String

Contains the URL of the server hosting the BDSS Web service components that the connectors call. This member must be non-null and nonempty.

syncSessionId

String

Contains a session ID. This member must be non-null and nonempty.

connectorRuntimeLibraryURL

String

Contains the URL used by a connector when it makes calls to the Connector Run-Time Library to read or write metadata.

connectorName

String

Contains the connector name. This member must be non-null and nonempty.


D.5.2.7 PimRecordDescription

The PimRecordDescription structure (Table D-31) contains the PIM Record Description. Connectors must build these descriptions for every upsert record of a given domain if the KeyField metadata is configured for the domain.

Table D-31 Members of the PimRecordDescription Data Structure

Member Data Type Description

descriptionArray

KeyValuePair []

An array of KeyValuePair structures containing the Hub field names and Hub field values that comprise the PIM Record Description. The array must not be null.

  • If KeyFields are configured for the domain, the array must have a size equal to the number of configured KeyFields and hasDescription should be set to true. Each KeyValuePair in the array must be non-null. Each key must be non-null and nonempty. Each value must be non-null but may be empty.

  • If KeyFields are not configured for the domain, the array must have a size equal to 1 and hasDescription should be set to false. The array should contain a non-null KeyValuePair, and the key and value must both be non-null but may both be empty.

hasDescription

Boolean

A Boolean value that indicates whether the descriptionArray has any valid elements. If the flag is set to false, then the given descriptionArray is ignored.


D.5.2.8 AssociatedData

The AssociatedData structure (Table D-32) enables connectors to associate data with either a PIM record or a PIM user.

Table D-32 Members of the AssociatedData Data Structure

Member Data Type Description

assocDataId

String

Contains a connector-defined identifier that uniquely identifies the associated data. This member must be non-null. It may be empty if hasAssocData is false. If hasAssocData is true, must be nonempty.

hasAssocData

Boolean

A Boolean value that indicates if assocDataArray has valid and nonempty AssocDataElement members

assocDataArray

AssocDataElement []

An array of AssocDataElement structures defining the group (or groups) of associated data. This member must be non-null.

This member must have size >= 1.

If hasAssocData is false, the array should have a size of 1 and contain an empty AssocDataElement.


D.5.2.9 AssocDataElement

The AssocDataElement data structure contains a group of associated data. Table D-33 lists the members of the AssocDataElement structure.

Table D-33 Members of the AssocDataElement Data Structure

Member Data Type Description

groupName

String

A string identifier that groups associated data contained in groupAssocDataArray. This member must be non-null. This member may be empty if hasAssocData is false. This member must be unique within a given AssocData.assocDataArray.

hasAssocData

Boolean

A Boolean value that indicates if groupAssocDataArray has valid and nonempty KeyValuePair members.

groupAssocDataArray

KeyValuePair []

An arbitrarily large array of KeyValuePair structures representing a single piece of associated data within a group. This member must be non-null. Must have a size of >= 1.

If hasAssocData is false, the array should have a size of 1 and contain an empty string for both the key and value. The array can be ignored by the recipient.

If hasAssocData is true, then each element must have a non-null and nonempty key and value.


Note:

If the associated data is binary, the connectors can encode the data to base-64 to save it in the database as a non-BLOB. In such a case, it is the connectors' responsibility to chunk and unchunk the associated data.

D.5.2.10 RecordMetaData

The RecordMetaData structure contains the metadata about a PIM record extracted from, or pushed to, a PIM server. Table D-34 lists the members of the RecordMetaData structure.

Table D-34 Members of the RecordMetaData Data Structure

Member Data Type Description

recordId

String

Contains the PIM Record ID. This member must be non-null and nonempty.

versionId

String

Contains the PIM Record Version ID. This member must be non-null and nonempty.

recordError

Boolean

A Boolean value that indicates if record processing failed. If this value is set to true, then both the recordId and the recordErrorDescription must be provided.

recordErrorDescription

String

Describes why an error occurred during the processing of an UpsertRecord. This member must be non-null, but it can be an empty string. It must be populated if recordError is set to true.

assocData

AssociatedData

Contains the AssociatedData

pimRecordDescription

PimRecordDescription

Contains the PIM Record Description. May be null if the KeyField data is not configured for the domain. This member must be null if the KeyField data is configured for the domain.


D.5.2.11 UpsertRecord

The UpsertRecord structure defines the structure of a Hub record extracted from, or pushed to, a PIM server. Deleted Hub records are not represented by this structure. Table D-35 lists the members of the UpsertRecord structure.

Table D-35 Members of the UpsertRecord Data Structure

Member Data Type Description

pimRecordMetadata

RecordMetaData

Contains metadata related to the record. This member must be non-null.

hubRecordData

String

Contains an XML representation of a Hub record. This member must be non-null and nonempty.


D.5.2.12 Enum ExtractResultCode

The enumeration type that defines the result codes of an extract request. Example D-1 illustrates the Enum definition.

Example D-1 Enum Definition

Enum ExtractResultCode
{
FULL_EXTRACT_COMPLETED_OK,
FULL_EXTRACT_COMPLETED_NOTOK,
PARTIAL_EXTRACT_COMPLETED_OK,
PARTIAL_EXTRACT_COMPLETED_NOTOK
};

D.5.3 Configuration-Related Structures

The configuration structures include:

D.5.3.1 ConfigurationSection

The ConfigurationSection structure represents a section of a profile that is conceptually the equivalent of a configuration file or an .ini configuration file. That is, a profile contains a collection of uniquely named sections, each containing a collection of parameters and values. Table D-36 lists the members of the ConfigurationSection structure.

Table D-36 Members of the ConfigurationSection Configuration Structure

Member Data Type Description

sectionName

String

Identifies the section name contained in a profile

paramNameValueArray

KeyValuePair []

Contains the configuration parameters and values contained in a section of a profile


D.5.3.2 ConfigurationProfile

The ConfigurationProfile structure represents a profile. Table D-37 lists the members of the ConfigurationProfile structure.

Table D-37 Members of the ConfigurationProfile Configuration Structure

Member Data Type Description

profileName

String

Identifies the name of a configuration profile

configSectionArray

ConfigurationSection []

Contains an array of ConfigurationSection structures containing information about a section of a profile


D.6 Best Practices for Building Connectors

Developers should divide a connector into at least three packages: the Hub Transport Package, the PIM Transport Package, and the Transformation Package.

  • Hub Transport Package

    The Hub Transport Package contains the components that communicate directly with the Hub. While these components handle all of the details related to communicating with the Hub, they do not perform direct data exchange operations against the PIM store or server. Instead, they communicate with a PIM transport package to exchange data with the PIM store. This component is generic in that it can be reused to communicate with one or more PIM transport packages.

  • PIM Transport Package

    The PIM Transport package contains the components that communicate directly with the PIM server and PIM store. These components never communicate directly with the Hub, but instead handle all of the PIM-related details. There should be a PIM Transport API that facilitates communication between the Hub and PIM Transport Packages.

  • Transformation Package

    The Transformation Package contains the components that perform translations of record data to and from the Hub format to the PIM format.

For more information, see Section 2.2, "Overview of Connectors."

D.7 The Exchange 2007 Connector API

This section uses the following to illustrate how the Exchange 2007 Connector works:

  • A BPEL system that has a users cdickens and tsmythe.

  • An Exchange system that has a user charles.dickens@sample.com and tsmythe@sample.com.

  • A Hub user that maps the cdickens user to the charles.dickens@sample.com user.

  • A user outside of the BPEL server and Exchange organization that has a e-mail address of tom.clancy@microsoft.com.

D.8 Generic Component Support for Calendar Synchronization

Similar to the goals for calendar support in the Hub, the goal for the generic connector components is that they should be able to support calendar synchronization in the same manner that they synchronize other domains. That is, the record data of any domain is irrelevant to the generic components. In addition, the generic components should not implement any domain-specific logic.

The Hub Transport provides delete detection for PIM Transports that are unable to detect deletes. If a PIM Transport component cannot natively detect deletes, then the Hub Transport should invoke a new PIM Transport Interface method after it determines the list of deleted record IDs so that the PIM Transport can determine if a deleted record should appear as a delete in the extract response, or as a exception to a calendar record that is a fanned instance. In the former case, the record ID would remain in the delete list. In the latter case, the record ID would be removed from the delete list and the connector must update the appropriate upsert record so that the master VEVENT contains the start date of the deleted occurrence in the EXDATE list. While the Hub transport might perform this for the Calendar domain, it could do so for every domain, thereby giving PIM Transports the opportunity to modify the Extract Response that ultimately gets sent to the Hub. Such methods as PIMExtractResponse, FinalizeExtractResponse (PIMExtractResponse response) would be an appropriate signature.

Use reflective synchronization to test calendar synchronization. The PIM Transport Interface would need a new method that returns the connector type. The Hub Transport would call this method at some point before reading configuration profiles from BDSS and it would load a profile whose name corresponds to the return value from the new PIM Transport method instead of the profile name corresponding to the connector name.

D.8.1 Calendar Support Methods

This section describes methods of the Run-Time Library (RTL).

D.8.1.1 Hub Contract

The Hub contract uses the following methods and capabilities:

D.8.1.1.1 GetAssocDataIdOfAssociatedData

This method, one included in the Run-Time Library, allows a connector to obtain the associated data ID from an associated data value. The method is similar to the getUserAssociatedData and getRecordAssociatedData in that a connector can provide a collection of associated data values and get a corresponding collection of assocdata IDs along with a status code indicating success, failure, or not-in-database for each requested assocDataID.

For example, if the connector stores assocData in BDSS having an assocDataId of MyCalendarAssocDataZ having a group name of MyGroup containing a collection of associated data key values pairs of {Key1,Value1}, {Key2,Value2},{Key3,Value3}, and the connector wants to later get the value MyCalendarAssocDataZ, it can call this API specifying MyGroup and any or all of {Key1,Value1}, {Key2,Value2} or {Key3,Value3}. The API queries the assoc data table for a row having the specified group name and key/value pairs to obtain the ID. The API must ensure to account for scenarios where the assoc data value is segmented across multiple rows.

D.8.1.1.2 Attendee Support

The Hub provides support for attendee resolution when it calls the connector methods for creating or updating a calendar record by using its user map metadata to provide the PIM User IDs in terms of the targeted system as part of the record metadata that accompanies a CREATE/UPDATE request. For the Hub to provide this metadata during a CREATE/UPDATE operation, a source connector must provide the attendees, in terms of the source system, of a calendar record in an extract response. The BDSS Connector RecordMetadata has a data member that holds the attendee metadata.

For example, when the Hub extracts cdickens' calendar from a BPEl server, the BPEL Task Connector would specify cdickens in the record metadata associated with the upsert record. The Hub then determines that the record must be created in the charles.dickens@sample.com user's Exchange calendar. The Hub performs a lookup for cdickens in its user map and find that cdickens is mapped to charles.dickens@sample.com in Exchange. Because the users are mapped, the Hub would provide charles.dickens@sample.com instead of cdickens in the record metadata associated with the upsert record that the Hub provides when it calls the Exchange 2007 Connector to create the record.

To support this, the BDSS Connector RecordMetadata must be updated to have a data member of type AttendeeMetadata to hold attendee metadata.

D.8.1.1.3 AttendeeMetadata

AttendeeMetada is a WSDL construct in the BDSS WSDL for the connector interface. The class manages attendee information associated with a Hub calendar record.

Given that:

  • A recurring calendar meeting can have exceptions containing different attendees than the master record or other exceptions

  • A target connector that creates or updates a calendar cannot use the attendee information contained within the ICAL (because the attendee information in the ICAL is defined in terms of the source connector)

This class provides a target connector with the ability to determine the attendees associated with each occurrence of the meeting. This implies a map-of-collections construct whereby the map keys off the start date of an occurrence and the collection for a given key contains the attendees associated with the occurrence. If the map has a single entry, this would imply a calendar record with no exceptions. If the map has multiple entries, this would imply a calendar record that has exceptions whereby the exception contains a different set of attendees than the master record.

D.8.1.2 Connector Contract

The following sections define the contractual obligations a connector implementation must adhere to synchronize calendar records using BDSS. Connectors must also adhere to the contractual obligations defined in the connector interface document.

D.8.1.2.1 Federated versus Non-federated

If the calendar system with which the connector exchanges data is a federated PIM, then the connector must abstract the federation model away from the Hub. For example, if a single calendar meeting is similar to the Siebel model and stores calendar records in a relational database such that each record has a unique row ID and that visibility to the calendar record is achieved by adding a foreign key from the calendar record to a user table. When the connector extracts a given calendar record, it can fabricate a PIM Record ID that is the concatenation of the row ID of the Calendar record and the row ID of the attendee for each attendee when each is synchronized. In a subsequent synchronization session, if the connector is directed by BDSS to perform UPDATE or DELETE operations, the Hub would provide the fabricated ID and the connector can parse out the two row IDs and then perform the appropriate operation.

Connectors of a federated system may be required to translate a given BDSS request to a different operation. For instance, assume that the calendar model of the system is such that attendees can only modify meetings that they organize. If BDSS directs the connector to perform an Update operation, but the connector determines that the row ID of the synchronizing user is an attendee and not an organizer, the connector may be able to simply no-op the BDSS call and perhaps log a message. That is, a no-op might be appropriate if the connector determines that the organizer is sync-enabled because the change, if any, would synchronize when the organizer synchronizes. (If the source is a non-federated PIM, then the organizer may not of changed his or her copy of the meeting). A no-op might not be appropriate if the connector determines that the organizer is enabled for synchronization (either because the user is not defined in the organization or the user simply is not added to the BDSS user map for synchronization). Similarly, if BDSS directs the connector to delete a record and the connector determines that an attendee deleted the record, then the connector would remove the attendee from the calendar record instead of deleting the entire record (that is, delete the foreign key identifying the attendee user from the calendar record instead of deleting the entire calendar record). If the connector gets a delete from an organizer, then the calendar record itself could be deleted. Because the order in which users synchronize is not guaranteed, the connector could no-op future deletes if it receives a delete for an attendee sometime after the organizers' delete was synchronized.

It is a connector implementation detail regarding how the abstracting the federation is done, but the implementation must ensure the following behavior:

  • The connector should send a delete for each attendee that has been removed from a meeting when each attendee user synchronizes. For example, if Record A has User A and User B as the organizer and attendee, respectively, and User C was removed, then a delete should be in the extract response when User A synchronizes and a delete should be in the extract response when User B synchronizes.

  • If the calendar record is deleted, as opposed to a deleted attendee, then a delete should be included in the extract for the organizer and each attendee.

  • If the record is converted from a meeting (with attendees) to an appointment (no attendees), then the connector should provide an upsert for the remaining user associated with the calendar record (may or may not be the organizer, depending on the calendar model in the PIM) and a delete for the remaining user(s).

  • The connector should provide an upsert record for each user associated with a calendar record on initial extractions or if the record is updated in ongoing extractions. For example, if Record A has User A and User B as the organizer and attendee, then Record A must be provided in the extract response to the Hub when User A synchronizes for the first time and when User B synchronizes for the first time. Additionally, if Record A is ever updated by a user, it must be provided when User A synchronizes and when User B synchronizes. If the update to Record A was a simple addition of a new attendee, then User C, then Record A must be provided in the extract response for User A, User B and User C.

  • The connector should not propagate an echo for updates done through BDSS by a particular user, but should propagate an update for any other users associated with the record. For example, suppose Record A in the federated system has User A, User B and User C as the attendees and the record is synchronized during Session 1. Then suppose that during Session 2, the connector receives a deleteRecord call to delete User C. The connector would remove User C from the calendar record instead of removing the calendar record. During Session 3, a upsert should appear in the extract responses of User A and User B, indicating the new attendee list (User C is no longer attending). When User C synchronizes, the extract response sent to the Hub should not have a delete for the record because this delete would be considered a delete-echo. In this way, if the attendee mapped to User C deletes the record from the other system, BDSS ensures that the attendees mapped to User A and User B in the other system have their records updated to indicate User C is no longer attending the meeting.

D.8.1.2.2 Attendee Resolution

Even though the Hub provides attendee resolution support, connector implementations should account for the following scenarios:

  • Use Case 1: The user is not configured in BDSS for synchronization. For example, suppose a calendar record originating from a BPEL server has an attendee named tsmythe and that tsmythe has a valid BPEL server and Exchange account, but tsmythe does not want his BPEL data to synchronize through BDSS. The record is then extracted by the BPEL Task Connector. When cdickens synchronizes, it would specify cdickens and tsmythe as attendees in the record metadata. The Hub would be able to provide the Exchange 2007 Connector with charles.dickens@sample.com, but would not be able to provide an Exchange user ID for tsmythe in the record metadata when calling the Exchange 2007 Connector to create the record.

  • Use Case 2: The user is not recognized as someone within the organization. For example, suppose an Exchange user at Microsoft, tom.clancy@microsoft.com, organizes a meeting and invites charles.dickens@sample.com who accepts the meeting and, therefore, has a calendar item in his Exchange folder. Further, suppose tom.clancy@microsoft.com is not defined in the Exchange and BPEL systems. When BDSS synchronizes the Hub user that maps cdickens to charles.dickens@sample.com, the Exchange 2007 Connector would not be able to resolve tom.clancy@microsoft.com as a user within the Exchange organization. It would specify tom.clancy@microsoft.com in the record metadata. When the Hub then pushes the record to the BPEL server, the BPEL Task Connector would also not be able to resolve tom.clancy@microsoft.com to a BPEL user.

  • Use Case 3: The attendee information contained in the record metadata may not be sufficient for a receiving connector when creating or updating the record in the target system. In this case, the connector should use the provided information to attempt to resolve the user. For example, suppose when the Exchange connector creates the calendar record, it has to specify the attendees First Name, Last Name, and the users e-mail address. The connector could specify the e-mail address contained in the record metadata in a query to Active Directory whereby the query returns the First Name and Last Name of the user with a matching e-mail address.

If a connector cannot resolve a given attendee to a user in the connectors' system, then the connector must ensure to provide the unresolved attendee back to the Hub during subsequent extractions. This is to ensure the attendee is not removed from the meeting when the record update is pushed to another connector.

The options that allow the connector to restore unresolved attendees associated with a calendar record when extracting a given calendar record include:

  • Extend the BDSS data model to have a table that would hold attendee metadata and define a new Run-Time Library API that would allow a connector to set or get the metadata.

  • Use the record-level or user-level associated data features of BDSS. If record-level associated data is used, there is the potential of having many duplicate unresolved attendees in the BDSS store. Consequently, user-level associated data might be a better option. If user-level associated data is used, there is still the potential of having duplicate, unresolved attendees in the BDSS store, but the duplicates would be less when compared to using record-level associated data. To avoid duplicates, connectors may create a special BDSS PIM User whose sole purpose is to hold unresolved attendees.

  • Write the unresolvable attendees to the PIM record itself at CREATE/UPDATE time so that when the record is subsequently extracted, the connector can obtain the unresolved attendees. If the system that a connector exchanges data with allows ambiguous values for attendees, the connector can simply write the unresolvable attendees to the attendee field(s). If, however, the system requires the attendee to be unambiguous, the connector should write the unresolvable attendees to a custom field that is not visible by default to end users.

Note:

Maintaining an in-memory cache of unresolved attendees may not be a viable option because a given user may be synchronized by different connector instances of the same connector type. For example, suppose there are two instances of the Exchange 2007 Connector known as Instance 1 and Instance 2 that are deployed on different servers. During synchronization Session 1, charles.dickens@sample.com is synchronized through Instance 1. Because tom.clancy@microsoft.com was not resolvable, the connector decides not to include this attendee when it creates the Exchange record. When an update is made to the meeting and BDSS subsequently performs another synchronization session, charles.dickens@sample.com is synchronized through Instance 2. During this session, Instance 2 would have no simple way of restoring tom.clancy@microsoft.com when the record is extracted (assuming connector instances do not communicate with each other).

Connectors that are unable to persist the unresolvable attendees on the system record itself must either use a BDSS solution (record- or user- associated data) or devise their own method.

If an attendee to a meeting identifies a group of attendees, or Distribution List, the connector must not provide the Distribution List as the attendee in the ICAL. Instead, the connector should provide each member of the group in the ICAL. This distribution list expansion is necessary because a group of attendees in one system may or may not be defined in another system and there is no guarantee that group membership would be the same in cases where a group name or Distribution List name matches across systems. The connector must also ensure to expand the members of all embedded group or Distribution Lists and ensure that no duplicates are contained in the ICAL. For example, if:

  • "Distribution List A" has members User1 and User2

  • "Distribution List B" has members Distribution List A, User1, User2, and User3

  • A calendar record has attendees listed as:

    • "Distribution List A"

    • "Distribution List B"

    • "User3"

then the ICAL should have User 1, User 2 and User 3 only, even though the calendar record has duplicates because of the group membership.

D.8.1.2.3 Recurrence Patterns

Connectors must attempt to support all ICAL recurrence patterns.

During extraction, a connector should convert a recurrence pattern from its native definition(s) to some ICAL equivalent. Similarly, when a connector creates or updates a calendar record, it should convert the ICAL recurrence pattern to an equivalent native pattern.

In some cases, however, a connector may not be able to natively support a given ICAL recurrence pattern. In these cases, the connector should still attempt to satisfy the create/update request made by the Hub. The primary means of resolving this is fanning. This form of fanning, not to be confused with non-federated systems, is the process creating multiple calendar records in a manner that mimics the original pattern.

Connectors should always fan a record to a set of non-recurring calendar records such that each instance has a start date that occurs on a date that the recurrence pattern defines. The connector is responsible for abstracting such operations from the Hub.

Note:

For Oracle Fusion Middleware 11g release 1, BDSS does not support EXRULE.

D.8.1.3 Fanning

The following sections provide information on connector contracts related to fanning.

D.8.1.3.1 Extraction

When the connector extracts a calendar record from its system, it must construct a ICAL representation of the record that conforms to the ICAL RFC.

A connector that has previously fanned a recurrence pattern must coalesce all of the fanned instances into a single ICAL representation containing the original recurrence pattern when the record is subsequently synchronized. When reconstructing the recurrence pattern from fanned records connector implementations should:

  1. Recognize that a change to a fanned instance in the PIM translates to an exception in the ICAL and should be represented as a separate VEVENT per the requirement listed in the Calendar Hub Domain Schema section.

  2. A deletion of any fanned instance in the PIM translates to a EXDATE of the master VEVENT

  3. Fanned instances should be coalesced in to a single ICAL message and the ExtractResponse should be such that fanned instances are not a part of the response. Additionally, the connector must provide an appropriate PIM Record Version.

  4. If fanned instances are updated by the PIM User through a client such that a recurrence pattern is applied to it, the connector must synchronize the fanned, but now recurring, record as a separate record and specify a EXDATE on the original record when performing the extract. It should also account for the use case whereby such an extracted record is in conflict with a corresponding record from another system and looses the conflict. In such a case, the connector would delete the recurring appointment and replace it with the winning record data.

  5. Metadata about each fanned instance should be maintained so that when the extraction is performed the connector can:

    • Determine the set of fanned instances

    • Determine how each fanned instance should appear in the ICAL (that is, master VEVENT, exception VEVENT). This implies the connector must track the state of each fanned instance across multiple synchronization sessions. For instance, suppose there are three fanned records that were synchronized during Session 1 (that is, Record A, Record B and Record C). All of these records must be coalesced in to a single ICAL having some recurrence pattern and the same meeting ID. Then if an update to Record A and a delete of Record C are synchronized during Session 2, Record A would appear in the ICAL as a exception VEVENT per Step 1), Record C should appear in the master VEVENT as a EXDATE per Step 2). During Session 2, suppose Record B is in the extract response and both Record A and Record C are not, the connector would add Record B as an exception VEVENT and must also provide Record A as an exception VEVENT and a EXDATE in the master VEVENT for Record C even though Record A and Record C are not in the extract response.

      As mentioned, the connector must store metadata about the record and each fanned instance to aid in the reconstruction of a recurrence pattern. The connector may store metadata both in the BDSS data store as associated data, or in hidden fields on the PIM record. What the connector stores is a connector implementation detail, one that is not necessarily the same across all connectors.

      If the connector stores record associated data in the BDSS data store and the Run-Time Library returns an error and the individual status codes indicates that the failure occurred because the data was not in the database for all the requested associated data, and that the synchronization state provided is empty/null, then the user has been re-initialized (if the Run-Time Library returns an error and there are individual status code indicating success and some indicating failure due to not being in the database, then this is an irrecoverable error). The connector should account for this use case so it can coalesce the fanned occurrences when performing the initial extract - perhaps by matching records by the Meeting ID.

D.8.1.3.2 CreateRecord

When the Hub calls CreateRecord the connector must examine the received ICAL to determine whether the record must be fanned. It should first examine each RRULE, RDATE, and EXDATE across all VEVENTs to determine the final recurrence pattern. If the final recurrence pattern cannot be natively represented, then the connector should fan the record and store whatever metadata it requires to restore the pattern in subsequent sessions.

If a failure occurs when creating any fanned instance, the connector should stop creating the fanned instances and delete any successfully created fanned instance related to the record being fanned and return an error to the Hub. The connector would probably want to log messages (note that such create-then-update in the same session would not be reflected in a subsequent session because both operations occur in the same session).

D.8.1.3.3 UpdateRecord

When the Hub calls UpdateRecord, the connector must determine if the record being updated has been fanned previously. If the record has been fanned previously, it must apply the received ICAL to the fanned instances, potentially having to re-fan the received pattern (if a new pattern was applied to the record and it cannot be natively represented). If re-fanning is done, the connector may have to first delete the old fanned instances and then create the new instances. The connector must also suppress these deletes in the subsequent extraction.

If the connector gets an update to a record it previously fanned and the ICAL has a exception VEVENT whose start date was not within the fanning limit of the original fanning, the connector must create the exception in the PIM.

The connector must account for the following fanning-related use cases listed in Table D-38. How the connector deals with each use case is a connector implementation detail.

Table D-38 Fanning Use-Cases

Pattern in Update Supported Record Previously Fanned Comments

True

True

Represents a unsupported pattern to supported pattern change across synchronization sessions.

True

False

Normal Update. No fanning.

False

True

Represents a unsupported pattern across synchronization sessions.


If a failure occurs when updating existing fanned instances (that is, true updates are being performed on the fanned instances versus delete and refanning), the connector should stop the updating and any successfully updated fanned instance related to the record being updated should be restored and an error should be returned to the Hub. The connector would probably log messages. Such update-then-update-to-restore operations occurring in the same session would be reflected in a subsequent session.

D.8.1.3.4 DeleteRecord

When the Hub calls DeleteRecord, the connector must determine if the record being deleted has been previously fanned. If so, the connector must delete all fanned instances.

If a failure occurs when deleting existing fanned instances before deleting them all, the connector is not required to restore the deleted fanned instances it had successfully deleted as the delete is retried in subsequent sessions because the synchronization state is not saved (assuming the connector stops the deletes and returns an error back to the Hub).

D.8.2 Exchange 2007 PIM Transport Calendar Support

The PIM Transport component supports the following:

D.8.2.1 Organizer and Attendees

Exchange allows for ambiguous names to be listed as attendees. Therefore, the Exchange 2007 Connector writes the list of attendees it obtains from the metadata directly to the Exchange records To, CC and BCC fields.

The BDSS Required Attendees are written to the Exchange To field, the Optional Attendees are written to the Exchange CC field and the Resources are to the Exchange BCC field.

The PIM Transport throws an error if it receives a update request for a meeting for a given user if that user does not appear as a attendee or an organizer.

D.8.2.1.1 Attendee Resolution

The PIM Transport uses the Exchange Web Services, the ResolveNames, and ExpandDL, to resolve attendees and distribution list membership.

D.8.2.1.2 Attendee Cache

A per-user-per-synchronization-session cache of attendees is created for a synchronizing user. The cache is created when the calendar domain extraction begins and populated with attendee metadata as each calendar record in the extract response is processed. When processing the attendees for a given calendar record, the connector looks in the cache for a match. If a match exists, then the information in the cache is used when building the ICAL for the record. If no match exists, then the attendee metadata is added to the cache and then to the ICAL.

D.8.2.2 Record Associated Data and Exchange Metadata

Table D-39 describes the metadata that the PIM Transport stores either in the BDSS data store as record-level associated data or in the Exchange store in hidden fields to enable calendar synchronization.

Table D-39 PIM Metadata Stored by the PIM Transport

Name Value Comments

BDSSFabricatedId

A unique ID

Used to represent an Exchange calendar record. If a record is fanned by the connector, the ID is used to represent a collection of fanned records

BDSS - Stored as the PIM Record ID

Exchange - Each fanned instance in Exchange has this ID written to a hidden field


D.8.2.3 Supported Recurrence Patterns

Table D-40 describes the supported recurrence patterns and gives some examples of each kind. Each sample has a non-ICAL description of the pattern followed by an ICAL RRULE value that represents the pattern. This table does not list all possible patterns.

Table D-40 Supported Recurrence Patterns

Exchange Pattern Examples of the ICAL RRule Property Value

Daily

Daily, every two days, forever.

FREQ=DAILY,INTERVAL=2,WKST=SU

Daily, every day, for 10 occurrences.

FREQ=DAILY;COUNT=10;INTERVAL=1;WKST=SU

Daily, every 5 days, until the end of July

FREQ=DAILY;UNTIL=20090731T173000Z;INTERVAL=5;WKST=SU

Daily, every weekday, forever

FREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU

Daily, every weekday, for 10 occurrences.

FREQ=DAILY;COUNT=10;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU

Daily, every weekday, until the end of July.

FREQ=DAILY;UNTIL=20090731T1730000Z;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU

Weekly

Every other week on Monday, Wednesday, and Friday, forever.

FREQ=WEEKLY;INTERVAL=2;BYDAY=MO, WE, FR;WKST=SU

Every other week on Monday, Wednesday, and Friday, for 10 occurrences.

FREQ=WEEKLY;COUNT=10;INTERVAL=1;BYDAY=MO, WE, FR;WKST=SU

Every three weeks on Monday, Wednesday and Friday until the end of July.

FREQ=WEEKLY;UNTIL=20090731T1730000Z;INTERVAL=3;BYDAY=MO, WE, FR;WKST=SU

Absolute

Monthly

The 15th of every other month forever.

FREQ=MONTHLY;INTERVAL=2;BYMONTHDAY=15;WKST=SU

Relative

Monthly

Last weekday of every month

FREQ=MONTHLY;INTERVAL=3;BYDAY=MO, TU, WE, TH, FR;BYSETPOS=-1;WKST=SU

Last weekend day of every month

FREQ=MONTHLY;INTERVAL=1;BYDAY=SU, SA;BYSETPOS=-1;WKST=SU

First day of every month for 10 occurrences.

FREQ=MONTHLY;COUNT=10;INTERVAL=1;BYDAY=SU, MO, TU, WE, TH, FR, SA; BYSETPOS=; WKST=SU

Every fourth Thursday of every other month until the end of October in 2010.

FREQ=MONTHLY;UNTIL=20101028T183000Z;INTERVAL=2;BYDAY=4 TH;WKST=SU

Monthly every 3rd Thursday.

FREQ=MONTHLY;COUNT=10;INTERVAL=1;BYDAY=3 TH;WKST=SU

The 4th Monday of every three months.

FREQ=MONTHLY;INTERVAL=3;BYDAY=4 MO;WKST=SU

Absolute

Yearly

Every year on the 4th of July

YEARLY;INTERVAL=1;BYMONTHDAY=4;BYMONTH=7;WKST=SU

Relative

Yearly

Every second of July for 10 occurrences

RRULE:FREQ=YEARLY;COUNT=10;INTERVAL=1;BYDAY=SU, MO, TU, WE, TH, FR, SA;

BYMONTH=7;BYSETPOS=2;WKST=SU

Last weekend day of July until 2018.

FREQ=YEARLY;UNTIL=20180729T190000Z;INTERVAL=1;BYDAY=SU, SA;BYMONTH=7; BYSETPOS=-1;WKST=SU


D.8.2.4 Time Zones

An Exchange CalendarItemType has two time zone-related properties: a TimeZone and MeetingTimeZone. The TimeZone property is read-only and provides a test-only description of a time zone for a calendar record. The MeetingTimeZone property is the property that should be set on new calendar or updated calendar items.

The PIM Transport must convert the ICAL VTIMEZONE value to a MeetingTimeZone equivalent when creating or updating a calendar record and vice-versa when extracting.

D.8.2.5 Date Time Values

Exchange Web Services store all date and time values in coordinated universal time (UTC). The connector must examine the form of ICAL date time values and convert it to UTC if needed. This should be simple enough to do since the ICAL is also required to have VTIMEZONE information.

D.8.2.6 PIM Record IDs

There are cases where the Exchange 2007 server may cause a given calendar record to have a new PIM Record ID when the record is updated by a user (see Microsoft Support at http://support.microsoft.com/ for more information). Therefore, the PIM Transport must store both the ItemIdType the MeetingId as record level associated data for every calendar record it creates or extracts.

Anytime the PIM Transport must extract, update or delete an Exchange record, it must take in to account that a given operation may fail because of this record recreation process that Exchange does on certain calendar records.

In general, the PIM Transport accomplishes this by first attempting a given operation using the available ItemIdType. If the operation fails and the result code indicates that the failure occurred because the record no longer exists in the Exchange store, then the connector must determine if this error occurred because the end user really deleted the record or it occurred because of the exchange record recreation process. The connector determines this by querying Exchange for the ItemIdType of a calendar record containing the same MeetingId as that contained in the record associated data provided in the metadata that accompanies the update record call. If the query returns a match, then the record was re-created by Exchange, otherwise, the record was deleted by the user. If the record was re-created by Exchange, the operation is retried using the new ItemIdType returned from the query.

The following sections describe additional details regarding what the Exchange PIM Transport must do to account for changing PIM Record IDs when extracting, creating, updating and deleting records from Exchange.

D.8.2.7 ExtractDomain

Using the, GetAssocDataIdOfAssociatedData method, which is within the Run-Time Library, the Exchange PIM Transport can be updated to not implement the DeleteUnaware interface as it can perform the necessary translation from a ItemIdType to the PIM Record ID stored in the BDSS data store. Switching to performing delete detection in the PIM Transport saves an additional query to the Exchange server.

The connector extracts the domain following the same logic as other domains. However, it must take additional steps to coalesce any previously fanned instances into a single PIMUpsertRecord containing a single ICAL message.

D.8.2.7.1 Fanning Logic

If the extract response contains any fanned instances, the connector must identify all related fanned instances both in the extract response those not in the extract response as those not extracted may have been updated or deleted in prior sessions and determine how each fanned instance should be represented in the single ICAL message having the original recurrence pattern.

As part of the reconstructing process, the connector must have a master VEVENT that contains the original record data and original recurrence pattern. Since the connector must get all fanned instances of a record and coalesce them in to a single ICAL, the connector could attempt to use a fanned instance whose FanningState is "Fanned" as this state indicates the initial state of a fanned record. This option, however, fails in the use case where each fanned instance has undergone a change (this is equivalent to a recurring pattern having an exception on each occurrence). Therefore, the PIM Transport stores the master VEVENT as record-level associated data.

For example, suppose during Session 1, the Engine calls CreateRecord for a record having a pattern of "The first day of every three months for four occurrences" and that Exchange does not support this pattern. The PIM Transport would fan this pattern to four non-recurring instances that fall on the first day of every three months. Before Session 2, the Outlook user changes the start date of the first fanned instance and deletes the second fanned instance. When Session 2 occurs, the connector would re-construct the ICAL such that the RRULE pattern is "The first day of every three months for four occurrences" and the extract response would have one upsert containing the calendar record whose date was changed and one delete containing the record id that was deleted. The master VEVENT would be obtained either from record associated data or from the Exchange record and the upsert would appear in the ICAL as a exception VEVENT. The delete would appear in the ICAL as a EXDATE of the master VEVENT. Before Session 3, assume the user updates the third fanned instance by changing the start time on the record. Then when Session 3 occurs, the extract response contains only the third fanned instance, but it must obtain the other instances so that the pattern reflects the changes made during Session 2. The connector must query Exchange for the other records and reconstruct the pattern such that the master VEVENT has a EXDATE for the second occurrence (because it was deleted in Session 2); and two exception VEVENTs - one for the first fanned instance (whose date was changed) and one for the third fanned instance (whose time was changed).

For cases when a user adds a recurrence pattern to a fanned instance, the connector treats the fanned instance as a deleted occurrence of the original pattern and keep the record in the extract response as a separate record instead of including it in the coalesced ICAL. A receiving connector would hide the occurrence of the original pattern due to the EXDATE and create a new recurring record for the fanned exception record.

Note:

The ICAL RFC indicates any VEVENT can have any number of RRULEs, RDATEs, EXRULEs and EXDATEs. While it is simple to represent an exception as having a recurrence rule, it is difficult to represent a exception having a recurring pattern which also has exceptions (and this exception containing a recurring pattern which can have its own exceptions pattern could recurse infinitely).

D.8.2.7.2 Changed PIM Record ID Logic

Since Exchange can change the PIM Record ID, the connector must determine if a given PIM Record ID contained in the Extract Response has been changed. This can be achieved by detecting a mis-matched ItemIdType value of the fanned instance extracted and the ItemIdTypes stored as BDSS record associated data for a given original start date (also stored in a hidden field on the Exchange record and as associated data). If a change in id is detected, the connector should update the record associated data to contain the new ItemIdType.

D.8.2.8 CreatePIMRecord

The following sections describe the processes that result from a CallPIMRecord method call:

D.8.2.8.1 Fanning Logic

The PIM Transport evaluates all RRULE, RDATE, and EXDATE properties contained in each VEVENT of a calendar record to determine if the record must be fanned.

If fanning is required, the connector is required to provide BDSS with a single unique ID for the collection of fanned records. Since the PIM Transport essentially does this for other domains by providing a given records' PR_SOURCE_KEY, the connector provides the PR_SOURCE_KEY of the first fanned instance as the PIM Record ID to represent the collection of fanned records.

Each fanned instance created in Exchange has the following hidden fields as described below:

  • OriginalStartDate—contains the start date of the fanned instance. This value never changes for the life of the record.

  • BDSSFabricatedPIMRecordId—contains the record id that is provided to BDSS as the PIM Record ID. It is the PR_SOURCE_KEY of the first fanned instance as mentioned above.

    Note:

    The first fanned instance does not have this hidden field value. The connector accounts for this difference when coalescing related fanned records into a single instance.

  • Potentially the master VEVENT data, pending open issue.

  • MeetingId—the meeting id of the Exchange record.

In addition to the hidden Exchange fields, the PIM Transport has the following record-level associated data that is associated with the fabricated record ID:

  • FannedState—One for each fanned instance.

  • OriginalStartDate—One for each fanned instance.

  • ItemIdType—One for each fanned instance.

  • Potentially the master VEVENT data.

If the PIM Transport must fan the record, it calculates the start date for each occurrence and, based on the fanning limit configuration value, create a collection of records that represent the received pattern.

The PIM Transport fans the record if:

  • The collection of RRULEs cannot be represented by a supported recurrence pattern.

  • If there are any RDATEs in the ICAL.

D.8.2.8.2 Changed PIM Record Id Logic

For record creation, a change to the PIM Record ID does not affect the connector, because the record does not exist in Exchange until the method creates it. It must, however, provide record-level associated data so that when the record(s) are modified and extracted, the extraction code can determine whether Exchange has changed the PIM Record ID.

For the Calendar domain, as with all other domains, the Exchange PIM Transport provides a given records' PR_SOURCE_KEY value as the PIM Record ID and store the Exchange Web Service ID, or ItemIdType, as record associated data. The connector must ensure to specify the ItemIdType anytime it interacts with the Exchange record and the PR_SOURCE_KEY anytime it interacts with BDSS.

D.8.2.9 UpdatePIMRecord

This section describes the following process that occur on a UpdatePIMRecord method call:

D.8.2.9.1 Fanning Logic

The PIM Transport determines if the record being updated has been previously fanned by examining the associated data that is provided in the record associated data when the UpdateRecord is called.

The PIM Transport determines if the received ICAL can be natively represented in Exchange by examining the collection of RRULE, RDATE, and EXDATE attributes.

Table D-41 describes the actions that the PIM Transport performs when updating a calendar record:

Table D-41 PIM Transport Update Actions

Pattern in Update Supported? Record Previously Fanned? Actions

True

True

Represents a unsupported pattern to supported pattern change across synchronization sessions

  • Delete fanned instances

  • Create new record with supported pattern

  • Keep old assocdata related to fanned instances for subsequent extraction so the delete echoes can be removed from the extract response

  • Ensure the created record has the fabricated id as a hidden field

True

False

Perform update

False

True

Represents a unsupported pattern across synchronization sessions

If the original recurrence pattern changed:

  • Delete fanned instances

  • Create new fanned instances

  • Keep old assocdata related to fanned instances for subsequent extraction, ensuring to set the FannedState to Refanned

  • Set the echo flag for each created record

  • Ensure each fanned instance has the same fabricated id provided as the PIM Record Id in the update

If the original recurrence pattern did not change:

  • Correlate any exceptions in the received ICAL to existing fanned instances and update the fanned instance with the exception data

  • Apply master VEVENT data, excluding recurrence pattern data, to the remaining fanned instances

  • Set the echo flag for each updated fanned instance

False

False

Represents a supported pattern to unsupported pattern change across synchronization sessions

  • Delete recurring record

  • Create new fanned instances

  • Delete old assocdata

  • Create new assocdata holding the fanning metadata


If the PIM Transport receives an update and finds that it previously fanned the pattern and a given fanned instance has a FannedState of RecurringException, but the master VEVENT does not have a EXDATE matching the original start date stored in associated data then the connector must assume that a conflict occurred and Exchange lost. In this case, the connector should delete the fanned record(s) having a FannedState of RecurringException and update the associated data. These delete(s) are propagated to other connector(s) in the subsequent synchronization session to delete the recurring record that was synchronized separately due to the fanned exception having a recurrence pattern.

D.8.2.9.2 Meeting Id Processing

The connector stores the MeetingId contained in the ICAL to a hidden Exchange field on each updated record and not update the MeetingId of the existing calendar record. When extraction is performed, the MeetingId from the hidden field is placed in the ICAL instead of the one on the record. The MeetingId stored in the hidden field may or may not be the same as the actual MeetingId stored on the record for the meeting. The case where they are the same implies either BDSS or an Exchange client has created the record. Where they are different implies that the update is the result of a conflict and Exchange lost. In either case, it should not be an issue as the connector returns the MeetingId that is contained in the ICAL during the update in subsequent sessions to the Hub. By returning the MeetingID, the connector does not inadvertently break the meeting management performed by Exchange itself or by Exchange clients.

D.8.2.9.3 Changed PIM Record Id Logic

The PIM Transport performs updates as described in Section D.8.2.6, "PIM Record IDs."

D.8.2.10 DeletePIMRecord

The Exchange PIM Transport always has to obtain the record associated data from the BDSS RTL when performing a delete operation for any domain because it always specifies a fabricated Id, also known as the PR_SOURCE_KEY, for the record but must specify the ItemIdType when performing the delete in Exchange.

D.8.2.10.1 Fanning Logic

The PIM Transport deletes all fanned instances of a record if the record had been previously fanned by obtaining the record associated data for the record and deleting each instance.

D.8.2.10.2 Changed PIM Record Id Logic

The PIM Transport performs deletes as described in Section D.8.2.6, "PIM Record IDs."