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 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
@Inject ContentSharingProvider contentSharingProvider;
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 and ContentSharingHelperProvider
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 objects in between and last the root
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
How to get access to a
@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 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.
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