Content sharing allows a business user to convey access to CMS objects within a repository (target repository) that is not the owning repository (source repository) of these objects. This works by enabling access from the target repository to the source repository of the CMS objects, further called sharing. This implies that all objects contained in the source repository are shared into the target repository. There is no individual sharing on object level.
Repositories where CMS objects can be shared from/to are Master-, Channel-, and Application-Repository. Via partner channel it is also possible to select Master-Repository of other partners (i.e., partner organization). It is possible to share from Master-Repository to Channel-Repository, from Channel-Repository to Application-Repository and also directly from Master-Repository to the Application-Repository.
Content sharing is of explicit nature, meaning that nodes and leafs do not implicitly have access to content objects that have been shared to their parents in the sharing path. E.g., (as depicted in the diagram below) although PrimeTech-MasterRepository is shared to PrimeTech- PrimeTechSpecials and PrimeTech-PrimeTechSpecials is shared to B2CWebShop-Repository, it does not automatically mean that content objects residing in the PrimeTech-MasterRepository are accessible to B2CWebShop. This can be enabled individually.
Since an application can access multiple parent repositories if enabled (see in the diagram below how two repositories are shared to B2C Webshop), an ordering is needed to decide which objects of which repository take priority at rendering time.
Example: Assume there is a system-managed homepage object existing in every repository (because the PageEntryPointDefinition
is visible in all contexts). Now, a business user can assign page variants to every homepage object. At the end the homepage is rendered in the context of B2CWebShop application. In which order should the page variant lookup combine page variants assigned to homepage object when they can be found following two (or more) separate paths?
As depicted in the diagram below, this ordering is achieved by calculating and using a position attribute for the sharing relation. It is determined automatically by the position of the source repository in the organizational hierarchy compared to the target repository. The rule is that the more specialized CMS objects take priority over the ones coming from other repositories depending on the position that has been calculated. Using the diagram below, CMS objects are prioritized in this order: B2CWebShop-Repository > PrimeTech-PrimeTechSpecials > PrimeTech-MasterRepository.
Technically, the content sharing relations between content (repository) domains are represented by proxy repository objects with a newly introduced type code of 27, meaning that this is a content sharing proxy repository. As stated in the sections above, these repository objects have to define an ordering on its own. This is achieved by a Position custom attribute of type integer which is set at creation time of the sharing relation. This is achieved automatically by determining the position by the organizational hierarchy level of the source repository compared to the target repository.
Developers get access to detect and manage existing sharing relations by using the following interfaces/classes.
ContentSharingProvider
The ContentSharingProvider
is the main access point to detect and manage existing sharing relations (see the API for further details). The following ways exist to get an instance of ContentSharingProvider:
GetContentSharingProvider
injecting:
@Inject ContentSharingProvider contentSharingProvider;
asking the NamingMgr
ContentSharingProvider contentSharingProvider = NamingMgr.getProvider(ContentSharingProvider.class);
In comparison to the ContentSharingHelper
described below, it does not contain cached access to calculated sharing paths. If performance matters, use the ContentSharingHelperProvider
to retrieve a ContentSharingHelper
instance.
ContentSharingHelper and ContentSharingHelperProvider
The ContentSharingHelper
is a convenience class acting as a wrapper to ContentSharingProvider
that encapsulates a single sharing path. Such a path is a simple sorted set of Domain
objects. First containing the leaf Domain
, all Domain
objects in between and last the root Domain
.
Use the ContentSharingHelperProvider
to get an instance of ContentSharingHelper
. Internally, the helper provider maintains an LRU cache to save runtime overhead. It is recommended to use the ContentSharingHelper
API instead of directly using above ContentSharingProvider
.
How to get access to a ContentSharingHelper
instance:
@Inject ContentSharingHelperProvider provider; ContentSharingHelper helper = provider.get(); // Answers with the helper instance based on the current application or ContentSharingHelper helper = provider.get(leafDomain); // Answers with the helper instance based on the domain object provided as parameter value
Inside of SQL query files a ContentSharingHelper
is also available to gain access to the embedded Domain
object(s). It needs a Domain
object as input parameter. As of now, this query parameter handler implementation also uses the ContentSharingHelperProvider
to get a hold of the resulting ContentSharingHelper
object. Meaning, when using the query parameter handler access to the resulting ContentSharingHelper
is also cached.
<?xml version="1.0" encoding="UTF-8"?> <parameters> <parameter name="Domain" type="com.intershop.beehive.core.capi.domain.Domain" optional="true"/> </parameters> <processor name="OracleSQL"> <processor-preprocessing output="SharingHelper" input="Domain" processing="ContentSharingHelper"/> </processor> <template type="countedobjects"> SELECT uuid, COUNT (*) over() AS rowcount FROM sometable WHERE <template-if condition="SharingHelper:SharingEnabled"> domainid in ( <template-loop alias="DomainUUID" iterator="SharingHelper:DomainUUIDsAsSet"><loop-statement><template-variable value="DomainUUID"/></loop-statement><loop-separator>,</loop-separator> </template-loop> ) <if-else/> domainid = <template-variable value="Domain:UUID"/> </template-if> </template> </query>
ContentSharingPreparer
The ContentSharingPreparer
is a dbinit preparer. It allows to establish content sharing relations during database initialization. It can be configured via a property file that is provided by the enclosing dbinit definition script.
Add the ContentSharingPreparer
to the dbinit.properties of the cartridge. Use the to-be-created property file as parameter.
ClassXXX = com.intershop.sellside.enterprise.dbinit.preparer.content.ContentSharingPreparer \ com.intershop.ucm.demo.dbinit.data.content.ContentSharing
The property file that is to be created to establish content sharing relations has the following format:
Content.<id>.Source.RepositoryDomainID = <source repository domain id> Content.<id>.Target.RepositoryDomainID = <target repository domain id>
Content.1.Source.RepositoryDomainID = FOO-MasterRepository Content.1.Target.RepositoryDomainID = FOO-BAR