Chapter 4. Publishing Concepts

This chapter discusses the concepts around publishing in CMS.

Publishing an item consists of two phases:

  1. Copying the item to create a pending version.

  2. Updating the pending version to live.

Throughout this chapter, when a URL is too long for printing, the \ indicates where a line break has been forced.

4.1. Publishing Process

Publishing begins when the publish(LifecycleDefinition, Date) method is called.

  1. First, applyTag(String)[1] is called. This method tags the versioning log so we know a publish is occurring.

  2. Next, Versions.suspendVersioning()[2] is called. This disables the Versioning service, and changes are no longer being recorded in the versioning log. This is done because a pending or live version of an item is essentially a temporary, read-only copy of the draft item. We don't care about recording changes to this item, and publishing performance improves if we don't.

    CautionCaution
     

    This disables versioning for the duration of the database transaction. Make sure publishing/unpublishing is the last action performed during a transaction, or call Versions.resumeVersioning()[3] once publishing is complete.

  3. Then, LifecycleDefinition.createFullLifecycle(Date, String)[4] is called to create a new instance of Lifecycle[5], using the LifecycleDefinition[6] as a template.

    Each Phase[7] in the Lifecycle is cloned and added to the new Lifecycle. The String argument is the name of a class that implements the LifecycleListener[8] interface. The begin(LifecycleEvent)[9] and end(LifecycleEvent)[10] methods of this class will be called when the Lifecycle begins and ends.

  4. Next, createPendingVersion(Lifecycle)[11] is called, passing in the new Lifecycle just created. This method creates a new, pending version of the item, and is where most of the work of the publishing system is done. It creates a new instance of VersionCopier and calls copyItem(ContentItem, boolean, boolean). The VersionCopier performs a series of steps in order to copy the object and create a pending version:

    1. Create a new instance of ContentItem[12] with the same concrete class and object type as the object being copied. This automatically assigns the new object a unique ID.

    2. Copy all scalar attributes from the original object to the new object. This includes attributes declared in the base type and all super-types.

    3. Copy all [1..1] and [0..1] associations (i.e., non-collection associations).

    4. Copy all collection ([0..n]) associations, including link attributes.

    5. Set the version to pending and add this new pending item to the draft (master) item's VERSIONS collection.

    Steps c. and d. could result in additional, recursive copying of objects. An association may be copied by reference (updating the pending version to be associated with an existing object), copied by value (creating a copy of the object and updating the pending version to point to the copy), or deferred for top-level item links. When being copied by value, steps a. through e. are applied to the new copy if the item is an instance of ContentItem. If the new object is not a ContentItem, then step e. is omitted, and the new object (of the same type as the source object) is not an instance of ContentItem as stated in step a. The rules for when each one happens are demonstrated in Figure 4-1. follows:

    Figure 4-1. Publishing Process

    Each time an association is copied by value, all of the associations of the target object (object B in Figure 4-1) must also be copied, and the VersionCopier goes through the same process outlined above when deciding how to handle the association. This has the potential to cause a large number of recursive copy operations when publishing a single item in a highly-connected object graph.

    For each association to a top-level item which is deferred until the item is made live, a PublishedLink object is created to store the metadata necessary for recreating this association. The PublishedLink class is package-visible, and is not a public class. For each deferred association from object A to ContentItem B in Figure 4-1, the PublishedLink stores a reference the new copy A', a reference to the draft B, a reference to the pending top-level ContentItem being created, and the name of the Property represented by the association.

  5. Once the pending version is created, the publish(LifecycleDefinition, Date)[13] method returns and a complete, pending version of the draft item exists in the database.

  6. The pending version in the database still has to be updated to live. This is done by a background thread managed by the Lifecycle system. This thread periodically polls the database for items with a Lifecycle whose startTime has elapsed but that have not been started yet. It loads these Lifecycles and instantiates the class identified by the listenerClassName that was assigned to the Lifecycle when it was created. It then calls begin(LifecycleEvent) on that class.

  7. All instances of the class ContentItem use the PublishLifecycleListener[14] class as their implementation of the LifecycleListener class. PublishLifecycleListener.begin(LifecycleEvent) has the sole purpose of updating a pending version to live. It retrieves the draft and pending versions of the item and calls draft.promotePendingVersion(pending)[15], which performs the following steps:

    1. Unpublish the current live version, if there is one. If there are any top-level ContentItem associations to or from this item, they are removed, as described in Section 4.2 Handling Deferred Associations With PublishedLink.

    2. Create a new VersionUpdater and call updateItemVersion(pending). The VersionUpdater recursively updates the version attribute of all ContentItem components of the pending item to live.

    3. Then, setLive(ContentItem)[16] is called, which sets the version attribute of the pending item to live. If there are any top-level ContentItem associations to or from this item, they are now created on the new live item, as described in Section 4.2 Handling Deferred Associations With PublishedLink. If this item can be published to the filesystem, this is also done here.

    4. If the ContentBundle of the item is still pending, then the function draftBundle.promotePendingVersion(pendingBundle) is called.

    Once this is complete, the item is live and available to the public.

Notes

[1]

http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/versioning/VersionedACSObject.html\ #applyTag(java.lang.String)

[2]

http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/versioning/Versions.html\ #suspendVersioning()

[3]

http://rhea.redhat.com/documentation/api/ccm-core-6.1.0/com/arsdigita/versioning/Versions.html#\ resumeVersioning()

[4]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/LifecycleDefinition.html#\ createFullLifecycle(java.util.Date, java.lang.String)

[5]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/Lifecycle.html

[6]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/LifecycleDefinition.html

[7]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/Phase.html

[8]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/LifecycleListener.html

[9]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/LifecycleListener.html#\ begin(com.arsdigita.cms.lifecycle.LifecycleEvent)

[10]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/LifecycleListener.html#\ end(com.arsdigita.cms.lifecycle.LifecycleEvent)

[11]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/ContentItem.html#\ createPendingVersion(com.arsdigita.cms.lifecycle.Lifecycle)

[12]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/ContentItem.html

[13]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/ContentItem.html#publish\ (com.arsdigita.cms.lifecycle.LifecycleDefinition, java.util.Date)

[14]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/lifecycle/\ PublishLifecycleListener.html

[15]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/ContentItem.html#\ promotePendingVersion(com.arsdigita.cms.ContentItem)

[16]

http://rhea.redhat.com/documentation/api/ccm-cms-6.1.0/com/arsdigita/cms/ContentItem.html#\ setLive(com.arsdigita.cms.ContentItem)