Kentico CMS 7.0 Integration Guide

Implementation of outbound direction

Implementation of outbound direction

Previous topic Next topic Mail us feedback on this topic!  

Implementation of outbound direction

Previous topic Next topic JavaScript is required for the print function Mail us feedback on this topic!  

At this point you should be decided:

 

which objects and documents you want to synchronize

which data type you want to use

whether you want to use the synchronous or the asynchronous mode

 

Based on this information, you will be able to decide which methods you need to implement. You should also have an operational skeleton of the connector prepared as described in the Creating a connector class topic.

 

Subscribing

 

After initializing the ConnectorName property, the second thing you have to do within the Init() method is to create subscriptions. Subscriptions are classes inheriting from AbstractIntegrationSubscription. The subscription determines the scope of tracked changes to be synchronized. By default, you can use any of the three prepared subscription classes – BaseIntegrationSubscription, ObjectIntegrationSubscription and DocumentIntegrationSubscription.

 

Later, you will see that it is not always necessary to create subscription objects. These only give you the highest level of scope specification granularity.

 

The particular subscription classes provide the following filtering options:

 

BaseIntegrationSubscription

SiteName – string determining the name of he site which the object or document is bound to, e.g. CorpSite. You can also use AbstractIntegrationSubscription.GLOBAL_OBJECTS to subscribe only to global objects.

TaskType – enumeration determining the type of task (create, update, delete, etc.). See Important types -> Enumerations -> TaskTypeEnum for more details.

 

ObjectIntegrationSubscription

ObjectType – string determining the type of the object (e.g. cms.user).

ObjectCodeName – string determining the code name of the object (eg. administrator).

 

DocumentIntegrationSubscription

DocumentNodeAliasPath – string determining the path to the document (e.g. /Home).

DocumentCultureCode – string determining the document’s culture (e.g. en-%).

DocumentClassName – string determining the document's document type (e.g. CMS.MenuItem).

 

You could notice the usage of the percent character (%) above. It is a wildcard representing 0-n arbitrary characters. This wildcard can be used within any of the string parameters. In the culture code example above, it specifies all English cultures (en-US, en-GB, etc.).

 

If you don’t want to constrain some string field, just leave it null in the constructor. If you don’t want to constrain the task type, use the value All.

 

You can either build your own subscription objects and register them, or take advantage of built-in helper methods which will do the job for you.

 

Building your own subscription objects

 

You can use the following examples as an intuition or as a basis for building your own subscriptions.

 

A) Using the following example, you can create two subscriptions. objSub and docSub. The objSub subscription covers objects whose object type starts with poll.poll - both polls themselves and their answers. The docSub subscription covers all actions done with documents on NewSite located under /Home/ in the content tree.

 

ObjectIntegrationSubscription objSub = new ObjectIntegrationSubscription(ConnectorName, TaskProcessTypeEnum.AsyncSnapshot, TaskTypeEnum.CreateObject, "PersonalSite", "poll.poll%", null);

 

DocumentIntegrationSubscription docSub = new DocumentIntegrationSubscription(ConnectorName, TaskProcessTypeEnum.AsyncSimpleSnapshot, TaskTypeEnum.All, "NewSite", "/Home/%", null, null);

 

SubscribeTo(objSub);

SubscribeTo(docSub);

 

B) Using the following example, you can create two subscriptions—customTableSubscription and custTableSubscription. The customTableSubscription subscription covers changes made to a custom table where "customtable.SampleTable" refers to its code name. The custTableSubscription subscription covers the modifications in the data of a custom table where "customtable.SampleTable" refers to its code name.

 

ObjectIntegrationSubscription customTableSubscirption = new ObjectIntegrationSubscription(ConnectorName, TaskProcessTypeEnum.AsyncSimpleSnapshot, TaskTypeEnum.All, null, null, "customtable.SampleTable");

 

ObjectIntegrationSubscription custTableSubscirption = new ObjectIntegrationSubscription(ConnectorName, TaskProcessTypeEnum.AsyncSimpleSnapshot, TaskTypeEnum.All, null, CustomTableItemProvider.GetObjectType("customtable.SampleTable"), null);

 

SubscribeTo(custTableSubscirption);

SubscribeTo(customTableSubscirption);

 

Using the prepared methods

 

You can overload the following methods:

 

SubscribeTo

SubscribeToAllDocuments

SubscribeToAllObjects

SubscribeToDocuments

SubscribeToObjects

 

Please see the IntelliSense tooltips which will help you decide which of the overloaded methods suits you best.

 

SubscribeToObjects(TaskProcessTypeEnum.AsyncSnapshot, PredefinedObjectType.USER);

 

This example show the easy way of subscribing to changes made to user objects.

 

Methods to be implemented

 

The following methods need to be implemented in the connector to ensure synchronization in the outbound direction:

 

ProcessInternalTaskAsync - ensures asynchronous processing of objects or documents (depending on the chosen override).

GetExternalObjectID - used in asynchronous processing for ID translations when synchronized objects or documents reference objects inheriting from BaseInfo.

GetExternalDocumentID - used in asynchronous processing for ID translations when synchronized objects or documents reference documents (TreeNode).

ProcessInternalTaskSync - ensures synchronous processing of objects or documents (depending on the chosen override).

 

ProcessInternalTaskAsync method

 

The method has two overrides. The first one is used for asynchronous processing of objects, the second one for asynchronous processing of documents.

 

IntegrationProcessResultEnum ProcessInternalTaskAsync(GeneralizedInfo infoObj, TranslationHelper translations, TaskTypeEnum taskType, TaskDataTypeEnum dataType, string siteName, out string errorMessage)

 

IntegrationProcessResultEnum ProcessInternalTaskAsync(TreeNode node, TranslationHelper translations, TaskTypeEnum taskType, TaskDataTypeEnum dataType, string siteName, out string errorMessage)

 

This method is used for asynchronous processing of objects (like users, forums, bad words, etc.) or documents. If we consider a basic scenario, your task is to transform the GeneralizedInfo or TreeNode into a corresponding object in the third party system and perform the action specified by TaskTypeEnum. You also have to take into account the TaskDataTypeEnum and the necessity of performing foreign key translations.

 

When you’re done with processing, return the IntegrationProcessResultEnum value and eventually set some error message. The error message is visible through the UI.

 

ProcessInternalTaskSync method

 

The method has two overrides. The first one is used for synchronous processing of objects, the second one for synchronous processing of documents.

 

IntegrationProcessResultEnum ProcessInternalTaskSync(GeneralizedInfo infoObj, TaskTypeEnum taskType, string siteName, out string errorMessage)

 

IntegrationProcessResultEnum ProcessInternalTaskSync(TreeNode node, TaskTypeEnum taskType, string siteName, out string errorMessage)

 

These two methods work similarly as the asynchronous version ProcessInternalTaskAsync(). The only difference is that you are not given the opportunity to use the TranslateColumnsToExternal() method for the foreign key translations. If you want to translate column values, you have to use Kentico CMS API.

 

The following example shows approximate code used for translation of a node’s parent identifier:

 

TreeProvider tree = new TreeProvider(CMSContext.CurrentUser);

TreeNode parentNode = DocumentHelper.GetDocument(node.NodeParentID, tree);

Guid parentGuid = parentNode.NodeGUID;

string parentSiteName = parentNode.NodeSiteName;

 

int newParentId = 0;

 

// TODO: External code which utilizes parentGuid and parentSiteName to find corresponding external document and returns its parent identifier (newParentId)

 

node.NodeParentID = newParentId;

 

Task processing options

 

There are several options how processing of a task can be achieved to synchronize the data:

 

Utilize API of the external system if you add references to its namespaces.

Use CMSConnectionScope and GeneralConnection and perform a query upon the external database.

Push the data to an external endpoint in a format which it is able to consume. This endpoint can be represented e.g. by a web service existing in the external system.

 

You can probably think of some other ways, but you should keep in mind that all ProcessInternalTaskXXX methods have to return the result status so that you are able to determine whether the processing on the external side succeeded or not. Please see Important types -> Enumerations -> IntegrationProcessResultEnum for further details.

 

Translating foreign key values to match the external ones

 

If you chose to use the SimpleSnapshot or Snapshot data type, you probably did it because you want to take advantage of the possibility to translate column values. This can be achieved by calling TranslateColumnsToExternal(), which accepts either an object or a document:

 

TranslateColumnsToExternal(infoObj, translations, <bool processChildren>)

 

The last parameter says whether you want to translate foreign keys of child objects. For the SimpleSnapshot data type, you always pass false. This parameter is useful only when you use the Snapshot data type. E.g. when you are processing an object that does not exist on the target platform yet, you don’t have enough information to translate foreign keys of child objects and you need to process the main object first. So the recommended order of events is the following:

 

1)Call TranslateColumnsToExternal(infoObj, translations, false).

2)Process the main object (save it to database).

3)Call TranslateColumnsToExternal(infoObj, translations, true).

4)Iterate through Children collection of infoObj and process each object.

 

To ensure the method’s proper functionality, it is necessary to implement one or both of the following methods:

 

GetExternalObjectID() – use if synchronized objects or documents reference objects inheriting from BaseInfo.

GetExternalDocumentID() – use if synchronized objects or documents reference documents (TreeNode).

 

GetExternalObjectID method

 

The method has the following signature:

 

int GetExternalObjectID(string objectType, string codeName, string siteName, string parentType, int parentId, int groupId)

 

The method has to be implemented only when you use TranslateColumnsToExternal() upon an object or document referencing an object inheriting from BaseInfo. You are given a set of parameters which should help you to identify the corresponding object in the external system. Once you find it you just return its identifier (integer value).

 

Main parameters:

 

objectType – defines type of object (e.g. “cms.user”), it can match external objects such as “people” or “members”

codename – this is the main identifier

 

Additional parameters:

 

siteName – in case the object belongs to some site, this is its code name

parentType – if the object has any parent, this is its type

parenteId – if the object has any parent, this is its identifier

groupId – if the object belongs to some group, this is its identifier

 

GetExternalDocumentID method

 

The method has the following signature:

 

int GetExternalDocumentID(Guid nodeGuid, string cultureCode, string siteName, bool returnDocumentId)

 

The method has to be implemented only when you use TranslateColumnsToExternal() upon an object or document referencing a document (TreeNode). You are given a set of parameters which should help you identify the corresponding document in the external system. Once you find it, you just return its identifier (integer value).

 

Parameters:

 

nodeGuid – guid part of the identifier.

cultureCode – the culture code of the document (e.g. “en-US”).

siteName – document in Kentico CMS is always bound to some site therefore the site code name is also supplied.

returnDocumentId – determines whether the system requires you to return DocumentID or NodeID value. NodeID is identifier of document independent on culture while DocumentID identifies specific culture version of a document. See the table below for more details.

 

 

Identifier

Alternative identification

Shared document data

NodeID

nodeGuid & siteName

Culture version of a document

DocumentID

nodeGuide & siteName & cultureCode

 

For more information on how Kentico CMS documents are stored in the database, please refer to Developer's Guide -> Content management -> Content management internals and API -> Database tables.

 

Translation flow diagram

 

The following figure illustrates how the translation works:

 

integrationguide_clip0026