Details
-
New Feature
-
Status: Closed
-
Normal
-
Resolution: Fixed
-
None
-
None
-
None
-
Quasar
-
Quasar Sprint 298, Quasar Sprint 300
-
Medium (3-5)
Description
Problem description
When rendering the SiteMap in the Channel Mgr, we need to see a sitemap which is the result of
- The HST sitemap (routes)
- All XPage documents
At this moment, the entire SiteMap is returned to the client (browser). This doesn't scale in case there are many XPage documents (which has been known since the inception of the feature). This is because the entire SiteMap has to be computed and will be recomputed on every request for every Channel Mgr user.
Complexity
What makes it very complex is that
- To 'know' the URL space for XPage documents, the HST needs to find a URL (pathInfo) for every XPage document. This can only be done via the HST linkcreator as the HST sitemap (routes) influence the pathInfo (URL). For this reason, to figure out the hierarchical URL space for all XPage documents, we need to get a URL for all of them, which doesn't scale with increasing amount of XPage documents. Note that the HST sitemap (routes) can be different for different branches of a channel
- The XPage documents URL space needs to be merged with the HST sitemap (routes) which can also have URLs (explicit sitemap (routes) items)
- the CMS user session might not have read access to all XPage documents : as the SiteMap is user specific, caching becomes much harder
Solution
In memory model
Instead of every user rendering its own PageTree (SiteMap) model which is expensive to create, we'll create a service backed by a jcr READ everywhere session which loads the model in memory. Note that these models will be PER channel (and potentially per BRANCH however only when the branch has sitemap changes we should do this)
This model must be kept in sync with fine grained invalidation when a handle node gets
- created
- deleted
- moved
And also when the HST sitemap (routes) gets modified for a channel (branch). Special handling might be needed for the sitemap of a branch in case the sitemap for the branch gets modified.
For this to work, we must add a JCR listener which triggers a reload of the model whenever needed.
When returning the SiteMap model to the user, we cannot return the in-memory SiteMap model as this is rendered by a JCR Session which has read-everywhere.
We need to filter the SiteMap to remove entries which are not readable by the current user
'Resty' model
At this moment, the 'resty' endpoint
_rp/{sitemapUUID}./pagetree
returns the entire SiteMap, regardless of which part is visible.
However instead of returning the entire SiteMap, we can instead return only the visible elements. This means we need extra 'resty' endpoints which will return deeper nested SiteMap structures.
Current Response
The current response for a call like
_rp/{sitemapUUID}./pagetree
is something like
{ "errorCode":null, "message":"Page tree loaded successfully", "reloadRequired":false, "success":true, "data":{ "id":"/", "name":"home", "pageTitle":null, "pathInfo":"/", "renderPathInfo":"/site/v1/channels/brxsaas", "experiencePage":false, "children":[ { "id":"about", "name":"about", "pageTitle":"About", "pathInfo":"about", "renderPathInfo":"/site/v1/channels/brxsaas/about", "experiencePage":true, "children":[ ] }, { "id":"articles", "name":"articles", "pageTitle":null, "pathInfo":"articles", "renderPathInfo":"/site/v1/channels/brxsaas/articles", "experiencePage":false, "children":[ ] }, { "id":"aaa", "name":"Aaa", "pageTitle":null, "pathInfo":null, "renderPathInfo":null, "experiencePage":false, "children":[ { "id":"bbb", "name":"Bbb", "pageTitle":null, "pathInfo":null, "renderPathInfo":null, "experiencePage":false, "children":[ { "id":"ccc", "name":"Ccc", "pageTitle":null, "pathInfo":null, "renderPathInfo":null, "experiencePage":false, "children":[ { "id":"mydoc", "name":"MyDoc", "pageTitle":"bar", "pathInfo":"test/test/foo/bar", "renderPathInfo":"/site/v1/channels/brxsaas/aaa/bbb/ccc/mydoc", "experiencePage":true, "children":[ ] } ] } ] } ] } ] } }
With the above, the UI shows for the sitemap something like
/ + about + articles + > Aaa
in which the > Aaa starts with '>' to indicate that it can be expanded. NOTE that in the example above > Aaa does have a 'renderPathInfo' of NULL. The result is that it can be expanded but a click on it won't load the page for 'Aaa' as there is no such page.
New 'Resty' endpoint
We'll add
__rp/{sitemapUUID}./sitemapitem
Instead of the above response, when being the homepage, the response will be:
{ "errorCode":null, "message":"Page tree loaded successfully", "reloadRequired":false, "success":true, "data":{ "id":"/", "name":"home", "pageTitle":null, "pathInfo":"/", "renderPathInfo":"/site/v1/channels/brxsaas", "experiencePage":false, "children":[ { "id":"about", "name":"about", "pageTitle":"About", "pathInfo":"about", "renderPathInfo":"/site/v1/channels/brxsaas/about", "experiencePage":true, "expandable":false }, { "id":"articles", "name":"articles", "pageTitle":null, "pathInfo":"articles", "renderPathInfo":"/site/v1/channels/brxsaas/articles", "experiencePage":false, "expandable":false }, { "id":"aaa", "name":"Aaa", "pageTitle":null, "pathInfo":null, "renderPathInfo":null, "experiencePage":false, "expandable":true } ] } }
With the above response. the FE can also draw
/ + about + articles + > Aaa
When clicking in the FE on 'Aaa', the FE must invoke
__rp/{sitemapUUID}./sitemapitem/aaa
which will return 'aaa' and the direct children of 'aaa' and the FE will include the response in the UI,. The response will contain again for the children whether they are expandable, and if so, eg
_rp/{sitemapUUID}./sitemapitem/aaa/bbb
can be invoked for the next level.