Just today I noticed a new flavor of the frequent Change Token problem: "The changeToken refers to a time before the start of the current change log."

As discussed each content deployment job is responsible to update the change tokens for the selected objects defined in the content deployment job. But there is one scenario where a content deployment job fails to update the associated change tokens in the content deployment path.

Assume the following scenario: you create a content deployment job inc1 which deploys the entire site collection rather than using selective deployment.

In such a situation the ExportObjects collection of the content deployment job references the SPSite (listed below as Type="Site") object with it's Url as the whole site collection is being exported:

After running this content deployment job the change token for the selected SPSite object will be listed in the DeploymentStatus field of the content deployment path as follows:

<?xml version="1.0encoding="utf-16"?>
<ArrayOfDeploymentStatus 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <DeploymentStatus>
      <ObjectType>Site</ObjectType>
      <Url>/</Url>
      <Id>0ee6a67e-28b8-4a25-aaef-142a4badd238</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292121851430000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
</ArrayOfDeploymentStatus>

Now lets assume that there is a second incremental content deployment job inc2 for the same path which uses selective deployment and deploys the root site and some sub sites:

The ExportObjects collection for this job looks as follows:

 

As you can see there is now an SPWeb object with the Url "/" listed. That is the root site of the site collection which was explicitly selected in the content deployment job inc2. Futher down you will see the DeploymentObjects for sites with Url /Docs and /Reports which represent the Document Center and the Report site.

If this deployment job is started after some changes were done to the site collection you would expect to see three additional change token in the DeploymentStatus field of the content deployment job, one for each of the selected sites. But what you will see is the following:

<?xml version="1.0encoding="utf-16"?>
<ArrayOfDeploymentStatus 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <DeploymentStatus>
      <ObjectType>Site</ObjectType>
      <Url>/</Url>
      
<Id>0ee6a67e-28b8-4a25-aaef-142a4badd238</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
42a4badd238;634292121851430000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Docs</Url>
      <Id>b0c03aa4-8ee9-44b8-9949-e8d881eb3329</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2371</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Reports</Url>
      <Id>c74252b2-f392-4518-9e66-4612fec333cd</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2371</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
</ArrayOfDeploymentStatus>

As you can see there is the DeploymentObject referencing the SPSite object (ObjectType Site) from job inc1 and the two DeploymentStatus for the Document Center and Reports site (ObjectType Web) of the job inc2. The DeploymentStatus for the root site selected in job inc2 is missing! You can also see that the change token for the SPSite object is older (has a lower number in the last part) as the change tokens of the other two sites.

The problem here is caused by a design limitation in SharePoint which uses the Url part as reference to the selected object. As the root site and the site collection use the same Url only one is stored in the DeploymentStatus field.

The next run of the second incremental deployment job will therefor use the change token of the SPSite object for the root site - which means that content in the root site is deployed over and over again - but that is usually only a minor overhead.

The more critical problem is that - if the first job is not executed anymore - the change token of the SPSite object will no longer be valid after a couple of weeks. As the change token of the SPSite object is not updated when the SPWeb object with the same Url is deployed you will end up with an outdated Change token for the second deployment job.

How can this problem be prevented?

To prevent this problem it is necessary to ensure that the DeploymentStatus for the SPSite object is not written into the content deployment path.

This can be done by defining deployment job inc1 in the following way:

  • Scope: Select "Specific sites within the site collection"
  • For the root site of the site collection use: "Select this site"
  • For each sub site of the site collection use: "Select this branch"

Using this approach the root site is selected as SPWeb object with the same settings as in job inc2 - which means that the ObjectStatus entry can be reused in both jobs.

The result after running job inc1 will then be this:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfDeploymentStatus 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/</Url>
      <Id>06b95c76-2013-4e09-9d91-af5cbb6d2624</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>Content</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Docs</Url>
      <Id>b0c03aa4-8ee9-44b8-9949-e8d881eb3329</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/News</Url>
      <Id>d903ed9c-0db1-49b4-a802-821d169e5cdd</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Reports</Url>
      <Id>c74252b2-f392-4518-9e66-4612fec333cd</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/SearchCenter</Url>
      <Id>58fb7c64-c4ba-462a-b238-eaf0dcda24b2</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/SiteDirectory</Url>
      <Id>95390a8d-dbd9-4682-9df8-7c47b281d1c5</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
</ArrayOfDeploymentStatus>

After executing the job inc2 you will get this:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfDeploymentStatus 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/</Url>
      <Id>06b95c76-2013-4e09-9d91-af5cbb6d2624</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292293204730000;2371</LastExportChangeToken>
      <IncludeDescendants>Content</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Docs</Url>
      <Id>b0c03aa4-8ee9-44b8-9949-e8d881eb3329</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292293204730000;2371</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/News</Url>
      <Id>d903ed9c-0db1-49b4-a802-821d169e5cdd</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/Reports</Url>
      <Id>c74252b2-f392-4518-9e66-4612fec333cd</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292293204730000;2371</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/SearchCenter</Url>
      <Id>58fb7c64-c4ba-462a-b238-eaf0dcda24b2</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
   <DeploymentStatus>
      <ObjectType>Web</ObjectType>
      <Url>/SiteDirectory</Url>
      <Id>95390a8d-dbd9-4682-9df8-7c47b281d1c5</Id>
      <LastExportChangeToken>1;1;0ee6a67e-28b8-4a25-aaef-
142a4badd238;634292267625700000;2370</LastExportChangeToken>
      <IncludeDescendants>All</IncludeDescendants>
   </DeploymentStatus>
</ArrayOfDeploymentStatus>

As you can see the change token for the root site is now correctly maintained for both jobs in the content deployment path.