Oracle® Fusion Middleware Administrator's Guide for Oracle Business Data Synchronization Server 11g Release 1 (11.1.1.6.0) Part Number E12319-02 |
|
|
PDF · Mobi · ePub |
This appendix lists the connector APIs, their contractual agreements between the connectors and the Engine, and the data representation structures.
This appendix includes the following topics:
The Connector API includes:
Terminology
Terms that relate to the API include:
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.
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.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.
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.
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 domainThe 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 C-1).
Table C-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.
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.
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.
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.
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 C.4.3, "CommitCachedSyncState Method API," Section C.4.8, "GetSyncState API," and Section C.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).An update/update conflict occurs when a previously synchronized record is updated in multiple systems and is extracted during the same synchronization session.
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:
TheExtractDomains
API is asynchronous. The other APIs are all synchronous.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 C-2 lists the parameters of the InitializeUserSyncSession
API.
Table C-2 Parameters of the InitializeUserSyncSession API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
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. |
|
|
[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
Connectors should validate the array and return an error if the given |
|
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.
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 callGetPimServerEndPoint
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
.
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 C-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.
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 C-3 Parameters of the ExtractDomains API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
|
[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:
|
|
|
[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:
|
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.
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 theExtractRequest
must be a subset of the Hub domains specified in the Hub call to InitializeUserSyncSession
during the same synchronization session.The connector responds as follows to the ExtractDomains
API:
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:
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
.
Any records that are filtered out by the PIM Filter Condition.
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.
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 multipleExtractResponses
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
.Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
Constructs a PIM Record Description for each extracted record.
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.
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 C.2.2.3.3, "Preventing the Download of Incorrect Records."
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."
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.
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:
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
.
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.
Delete Detection.
The Hub provides support for the following two delete use cases for connectors:
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.
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
.
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.
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.
This section describes the best practices for ExtractDomains. Topics include:
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.
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.
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.
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 C-4 Parameters of the EndDomainSynchronization API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the URL to the connector run-time interface that the connector should use for the given synchronization session. |
|
String |
[in] |
Identifies the Hub domain. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
Boolean |
[in] |
A Boolean value that indicates whether the connector should save the synchronization state |
|
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. |
The Engine performs the following when it calls the EndDomainSynchronization
API:
Calls this method at the conclusion of processing the given domain.
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 theechoesSuppressed
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.Uses the extractResponseCount
for cleaning up ExtractResponses
that may have been received by the Hub when errors occur.
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
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
.
A connector responds as follows when the Engine calls the EndDomainSynchronization
API:
Cleans up any domain-level resources related to the user, if appropriate.
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.
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.
Ensures that extractResponseCount
is always populated with the correct number of successfully sent ExtractResponses
to the Hub for the given Synchronization Session.
Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
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
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 C-5 lists the parameters of the EndUserSyncSession
interface.
Table C-5 Parameters of the EndUserSyncSession API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the URL to the Connector Run-Time Interface that the connector should use for the given synchronization session |
|
String |
[in] |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
The Engine performs the following when it calls the EndUserSyncSession
API:
Does not call the connector for the same user until another synchronization session has started.
Calls this API to end the synchronization session identified by the given syncSessionId
.
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.
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.
The connector responds as follows when the Engine calls the EndUserSyncSession
API:
Cleans up all resources related to the user.
Uses the provided Synchronization Session ID, Hub domain and Hub User ID in logging statements.
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.The Hub calls the CreateRecord
interface any time a record must be created in the PIM. Table C-6 lists the parameters of the CreateRecord
interface.
Note:
The Hub can call this API even if the domain has not been extracted.Table C-6 Parameters of the CreateRecord API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
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 |
|
String |
[in] |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
[in] |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
[in/out] |
On input, contains the Hub record in Hub XML format. The
|
The Engine performs the following when it calls the CreateRecord
API:
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)
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.
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.
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
.
The connector responds as follows when the Engine calls the CreateRecord
API:
Creates the record in the PIM store and provide the metadata as indicated in Table C-6.
Translates Hub-formatted XML messages to a format suitable for creating a record in the PIM server.
Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
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
The Engine calls the UpdateRecord
interface anytime that a record must to be updated in the PIM server. Table C-7 lists the parameters of the UpdateRecord
method.
Note:
The Hub can call this API even if the domain has not been extracted.Table C-7 Parameters of the UpdateRecord API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
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 |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
In |
Contains the Hub record and metadata, obtained from the Hub data store, about the record to be updated The |
|
|
Out |
On output, contains updated record metadata, obtained from the PIM Record that includes:
|
The Engine performs the following when it calls the UpdateRecord
API:
The Engine performs the following when resolving conflicts detected when evaluating extract responses:
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.
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.
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.
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.
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.
The connector responds as follows when the Engine calls the UpdateRecord
API:
Updates the record identified by the given PIM Record ID in the PIM server and populates the RecordMetaData structure.
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.)
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).
Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
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
The Engine calls the DeleteRecord
API whenever a record must be deleted from the PIM server. Table C-8 lists the parameters of the DeleteRecord
method.
Note:
The Hub can call this API even if the domain has not been extracted.Table C-8 Parameters of the DeleteRecord API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
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. |
|
|
String |
[in] |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM Record ID of the record to delete. This parameter must be non-null and nonempty. |
|
PIM Record Description |
In |
Contains the PIM Record Description |
The Engine performs the following when it calls the DeleteRecord
API:
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.
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.
The connector responds as follows when the Engine calls the DeleteRecord
API:
Deletes the record in the PIM identified by the given PIM Record ID.
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.
Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
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.
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
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 C-9 lists the parameters of the GetPimServerEndPoint
interface.
Table C-9 Parameters of the GetPimServerEndPoint Interface API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
[in] |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
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. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
Out |
On output, contains a connector-defined endpoint token. This parameter can be NULL. It can also be empty. |
|
Boolean |
Out |
On output, indicates whether the receiving connector can synchronize the given user |
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:
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.
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.
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
.
The connector that receives the GetPimServerEndPoint
API call performs the following:
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.
Uses the provided Synchronization Session ID, Hub domain, and Hub User ID in logging statements.
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
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.
The ExtractDomainResultsCallback
API is asynchronous and returns immediately to the calling connector after the Engine queues the information provided in the given ExtractResponse
. Table C-10 lists the parameters of the ExtractDomainResultsCallback
method.
When the Engine calls the ExtractDomainResultsCallback
API, it queues the ExtractResponse
and returns immediately.
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
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.
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 C-11 Parameters of the GetPimRecordVersions API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String [] |
In |
Contains an array of PIM Record IDs for which the connector wants to retrieve the version ID. |
|
String [] |
Out |
On output, contains the PIM Record Version ID of each record specified in the
When a synchronization session completes without failures, a non-empty Version ID is provided for the ith element in the A connector should echo suppress a PIM record if the The ith element in |
Return Value
Integer:
0 for SUCCESS/OK
Nonzero for ERROR
Exceptions
A RemoteException
is thrown if an irrecoverable error occurs.
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 C-12 Parameters of the CacheTempSyncState API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM Domain Target. This parameter must be non-null and nonempty. |
|
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.
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 C-13 lists the parameters of the CommitCachedSyncState
method.
Table C-13 Parameters of the CommitCachedSyncState API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
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.
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 C-14 lists the parameters of the GetConfigurationMetaData
method.
Table C-14 Parameters of the GetConfigurationMetaData API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
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 C-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 C-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 |
Array has a size of 1 and contains a single
|
Updates the |
Obtain parameter names and values of a section in a profile. The scope is |
Array has a size of 1 and contains a single
Array has a size of 1 and contains a single
|
Updates the |
Get all parameter names and values of all sections in a profile. The Scope is |
An array has a size of 1 and contains a single
Null |
The Each |
Get all parameter names and values of all sections in multiple profiles. The scope is |
The same builds as the |
The same builds as the |
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.
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 C-16 lists the parameters of the GetDeletesByPendingCreateEchoes
API.
Table C-16 Parameters of the GetDeletesByPendingCreateEchoes API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
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. |
|
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. |
|
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.
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 C-17 lists the parameters of the GetDeletesByIds
method.
Table C-17 Parameters of the GetDeletesBylds API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. Must be non-null and nonempty. |
|
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. |
|
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.
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 C-18 lists the parameters of the GetRecordAssociatedData
API.
Table C-18 Parameters of the GetRecordAssociatedData API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. Must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. Must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. Must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. Must be non-null and nonempty. |
|
String |
In |
Contains the connector name. Must be non-null and nonempty. |
|
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. |
|
String [] |
Out |
On output, this array contains the PIM Record Associated Data of each record specified in the There is a positional relationship between the elements of |
|
String [] |
On output, an array consisting of success or error codes. There is a positional relationship between this array and
|
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.
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 C-19 lists the parameters of the GetSyncState
API.
Table C-19 Parameters of the GetSyncState API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM Domain Target. This parameter must be non-null and nonempty. |
|
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.
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 C-20 lists the parameters of the GetUserAssociatedData
API.
Table C-20 Parameters of the GetUserAssociatedData API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains an array of connector-defined user associated data identifiers. |
|
Out |
On output, contains the user-specific associated data. There is a positional relationship between this array and |
|
|
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 |
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.
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 C-21 lists the parameters of the SaveSyncState
API.
Table C-21 Parameter of the SaveSyncState API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String |
In |
Contains PIM Domain Target. This parameter must be non-null and nonempty. |
|
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.
Connectors call the setRecordAssociatedData
API to associate the connector-defined PIM Record associated data to the given record. Table C-22 lists the parameters of the SetRecordAssociatedData
API.
Table C-22 Parameters of the SetRecordAssociatedData API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
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. |
|
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 |
|
|
Integer [] |
Out |
On output, an array error codes. There is a positional relationship between this array and |
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.
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 C-23 lists the parameters of the SetUserAssociatedData
API.
Table C-23 Parameters of the SetUserAssociatedData API
Parameter | Data Type | Type | Description |
---|---|---|---|
|
String |
In |
Contains the Synchronization Session ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub domain. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the Hub User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the PIM User ID. This parameter must be non-null and nonempty. |
|
String |
In |
Contains the connector name. This parameter must be non-null and nonempty. |
|
String [] |
In |
An array of connector-defined users associated data identifiers. |
|
In |
Contains the user-specific associated data. There is a positional relationship between |
|
|
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 |
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.
This section describes the structure of data that is passed between BDSS and the connectors.
The common structures include the KeyValuePair
structure.
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 C-24 lists the members of the KeyValuePair
structure.
The connector interface-related structures include:
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 C-25 lists the members of the DomainInfo
structure.
Table C-25 Members of the DomainInfo Data Structure
Member | Data Type | Description |
---|---|---|
|
String |
Contains the PIM Domain Target. Must be non-null. May be empty. For more information about this member, see Section C.1.5, "PIM Domain Target." |
|
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. |
|
String |
Identifies the Hub domain. This member must be non-null and nonempty. |
|
String |
Contains the PIM synchronization state for the domain. This member must be non-null. This member may be empty. |
The ExtractRequest
structure is passed to the connector when BDSS begins an extraction for a user through the ExtractDomains
API. Table C-26 lists the members of the ExtractRequest
structure.
Table C-26 Members of the ExtractRequest Data Structure
Member | Data Types | Description |
---|---|---|
|
String |
Contains the Hub User ID. This member must be non-null and nonempty. |
|
String |
Contains the PIM User ID. This member must be non-null and nonempty. |
|
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. |
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 C-27 lists the members of the ExtractResponse
structure.
Table C-27 Members of the ExtractResponse Data Structure
Member | Data Types | Description |
---|---|---|
|
|
Contains metadata about the extract response. This member must be non-null and nonempty. |
|
|
Contains the extracted PIM records. This member must be non-null and nonempty. |
The ExtractResponseData
structure contains records extracted from a PIM server. Table C-28 lists the members of the ExtractResponseData
structure.
Table C-28 Members of the ExtractResponseData Data Structure
Member | Data Type | Description |
---|---|---|
|
Boolean |
Indicates if the structure has an upsert record. This array has valid UpsertRecord structures. |
|
UpsertRecord [] |
An array of 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 |
|
Boolean |
Indicates whether |
|
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 |
The ExtractResponseMetaData
structure contains metadata information about a given ExtractResponseMetaDat
a of a domain extraction. Table C-29 lists the members of the ExtractResponseMetaData
structure.
Table C-29 Members of the ExtractResponseMetaData Data Structure
Member | Data Type | Description |
---|---|---|
|
String |
Contains the Synchronization Session ID. This member must be non-null and nonempty. |
|
String |
Contains the Hub domain. This member must be non-null and nonempty. |
|
String |
Contains the Hub User ID. This member must be non-null and nonempty. |
|
String |
Contains one of the |
|
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 |
|
String |
Contains the PIM Domain. This member must be non-null and nonempty. |
|
String |
Contains the PIM User ID. This member must be non-null and nonempty. |
|
String |
Contains the connector name |
|
String |
Indicates whether the |
|
String |
Indicates a sequence number of the The |
The HubContext
structure (described in Table C-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 C-30 Members of the HubContext Data Structure
Member | Data Type | Description |
---|---|---|
|
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. |
|
String |
Contains a session ID. This member must be non-null and nonempty. |
|
String |
Contains the URL used by a connector when it makes calls to the Connector Run-Time Library to read or write metadata. |
|
String |
Contains the connector name. This member must be non-null and nonempty. |
The PimRecordDescription
structure (Table C-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 C-31 Members of the PimRecordDescription Data Structure
Member | Data Type | Description |
---|---|---|
|
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.
|
|
Boolean |
A Boolean value that indicates whether the |
The AssociatedData
structure (Table C-32) enables connectors to associate data with either a PIM record or a PIM user.
Table C-32 Members of the AssociatedData Data Structure
Member | Data Type | Description |
---|---|---|
|
String |
Contains a connector-defined identifier that uniquely identifies the associated data. This member must be non-null. It may be empty if |
|
Boolean |
A Boolean value that indicates if |
|
An array of This member must have size >= 1. If |
The AssocDataElement
data structure contains a group of associated data. Table C-33 lists the members of the AssocDataElement structure.
Table C-33 Members of the AssocDataElement Data Structure
Member | Data Type | Description |
---|---|---|
|
String |
A string identifier that groups associated data contained in |
|
Boolean |
A Boolean value that indicates if |
|
|
An arbitrarily large array of If If |
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.The RecordMetaData
structure contains the metadata about a PIM record extracted from, or pushed to, a PIM server. Table C-34 lists the members of the RecordMetaData
structure.
Table C-34 Members of the RecordMetaData Data Structure
Member | Data Type | Description |
---|---|---|
|
String |
Contains the PIM Record ID. This member must be non-null and nonempty. |
|
String |
Contains the PIM Record Version ID. This member must be non-null and nonempty. |
|
Boolean |
A Boolean value that indicates if record processing failed. If this value is set to true, then both the |
|
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 |
|
Contains the |
|
|
Contains the PIM Record Description. May be null if the |
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 C-35 lists the members of the UpsertRecord
structure.
The enumeration type that defines the result codes of an extract request. Example C-1 illustrates the Enum
definition.
The configuration structures include:
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 C-36 lists the members of the ConfigurationSection structure.
Table C-36 Members of the ConfigurationSection Configuration Structure
Member | Data Type | Description |
---|---|---|
|
String |
Identifies the section name contained in a profile |
|
KeyValuePair [] |
Contains the configuration parameters and values contained in a section of a profile |
The ConfigurationProfile
structure represents a profile. Table C-37 lists the members of the ConfigurationProfile structure.
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."
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.
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.
This section describes methods of the Run-Time Library (RTL).
The Hub contract uses the following methods and capabilities:
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.
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.
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.
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.
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.
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.
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.The following sections provide information on connector contracts related to fanning.
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:
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.
A deletion of any fanned instance in the PIM translates to a EXDATE of the master VEVENT
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.
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.
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.
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).
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 C-38. How the connector deals with each use case is a connector implementation detail.
Table C-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.
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).
The PIM Transport component supports the following:
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.
The PIM Transport uses the Exchange Web Services, the ResolveNames, and ExpandDL, to resolve attendees and distribution list membership.
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.
Table C-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 C-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 |
Table C-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 C-40 Supported Recurrence Patterns
Exchange Pattern | Examples of the ICAL RRule Property Value |
---|---|
Daily |
Daily, every two days, forever.
Daily, every day, for 10 occurrences.
Daily, every 5 days, until the end of July
Daily, every weekday, forever
Daily, every weekday, for 10 occurrences.
Daily, every weekday, until the end of July.
|
Weekly |
Every other week on Monday, Wednesday, and Friday, forever.
Every other week on Monday, Wednesday, and Friday, for 10 occurrences.
Every three weeks on Monday, Wednesday and Friday until the end of July.
|
Absolute Monthly |
The 15th of every other month forever.
|
Relative Monthly |
Last weekday of every month
Last weekend day of every month
First day of every month for 10 occurrences.
Every fourth Thursday of every other month until the end of October in 2010.
Monthly every 3rd Thursday.
The 4th Monday of every three months.
|
Absolute Yearly |
Every year on the 4th of July
|
Relative Yearly |
Every second of July for 10 occurrences
Last weekend day of July until 2018.
|
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.
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.
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.
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.
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).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
.
The following sections describe the processes that result from a CallPIMRecord
method call:
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.
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.
This section describes the following process that occur on a UpdatePIMRecord method call:
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 C-41 describes the actions that the PIM Transport performs when updating a calendar record:
Table C-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
|
True |
False |
Perform update |
False |
True |
Represents a unsupported pattern across synchronization sessions If the original recurrence pattern changed:
If the original recurrence pattern did not change:
|
False |
False |
Represents a supported pattern to unsupported pattern change across synchronization sessions
|
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.
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.
The PIM Transport performs updates as described in Section C.8.2.6, "PIM Record IDs."
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.
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.
The PIM Transport performs deletes as described in Section C.8.2.6, "PIM Record IDs."