Nested: Deprecating the notion of space everywhere (not just UI)

Last modified by Ecaterina Moraru (Valica) on 2020/01/28 14:38


Previous alternative proposal: Parent-child + Unique ID + Nested Documents


With the introduction of Nested Spaces, we are simulating our actual goal of achieving Nested Pages and we did that by using the WebHome page inside a Nested Space.

However, this introduced the complexity of dealing with terminal (non-WebHome) and non-terminal (WebHome) pages, which leads to a lot of confusion and cruft.

Here is a proposal for a new API in which you can forget about spaces/documents while still being fully compatible with the "old" API.


  • The objective is not to re-create the model, we want to make a new data access API.
  • This new API could also be seen as a "Helper" rather than an API that replace the old behaviours
  • Retro-compatibility is critical, no changes to existing behavior, with queries we need to extend the query language such that "new" queries are using query syntax which is currently invalid
  • We will not require that HQL has any new changes, we only care about making easy-to-use XWQL
  • Provide an easy-to-use API
    • We don't want to think about internal implementation, is it a Terminal document, is it WebHome, etc etc
    • We want queries to no longer think about WebHome etc
  • all the new APIs must be in new modules, nothing on oldcore. We mostly need two entry point (et probably two corresponding modules): a java side manager, a script service

1.0 aka "new PageReference APIs without stuff we don't agree yet"

The scope of this version is to provide new page oriented API for scripts and Java components but not concentrate on supporting page concept in HQL requests.


New typed EntityReferences

We need new entity types and corresponding reference helpers:

  • PageReference (EntityType.PAGE)
  • PageObjectReference (EntityType.PAGE_OBJECT)
  • PageObjectPropertyReference (EntityType.PAGE_OBJECT_PROPERTY)
  • PageClassPropertyReference (EntityType.PAGE_CLASS_PROPERTY)
  • PageAttachmentReference (EntityType.PAGE_ATTACHMENT)

Model script service

Add new helpers for the new types and deprecate the old ones.

New reference syntax

  • use '/' as separator instead of '.'
  • same separator for all types except for wiki which would remain ':' (to differentiate between Page and Wiki parent)
  • use '.' as current page and '..' as parent page
  • the escaping character stay '\'
  • we also need to introduce syntax for the locale which we still don't have in the current syntax partly because it's very hard to introduce without breaking anything. Ideas:
    1. since EntityReference actually support a map of parameter one idea is to use something close to the URL parameter syntax for references to indicate the locale and prepare the future or any custom reference property need: wiki:space/page;key=value with a special treatment for the locale as the default property like in wiki:space/page;pt_BR (the logic being "not equal means no key meaning it's locale")

Standard explanation challenge:

Unix filesystem path syntax with parameters and optional wiki prefix

Links help

New page: prefix. Use this new prefix in the WYSIWYG.

help Hard to do anything about untyped links which are based on document reference right now except saying "well yeah you need page: prefix".


Add page parameter shortcut taking a page reference but for other types keep leaving with reference/type couple.

DocumentTree macro

Don't touch it and introduce a new PageTree macro


  • add XWikiDocument#getPageReference() and probably also in other places returning DocumentReference when it make sense 
  • support new Page*Reference in XWiki#getDocument() and other methods taking EntityReference

2.0 aka "the database also want to play with pages"

Database help

Things decided so far (first meeting):

  • introduce real page table(s) and duplicate/synchronize automatically what's in document table
  • add field (for example pageId) in Attachment/Class/Object tables to make easier to join them with the Page table
  • fill the holes in the page table with "empty" entries
    • help need to decide between null page content or explicit field to support holes

Things to discuss:

  • help single table or separate tables for default version and translations
  • help allow having both final and non-final page at the same time or disable or choose one of the other (need to decide priority)


  • New "Page" db table, automatically synchronized when you save a document/page and deprecate the old table (which mean they are duplicated).
  • Introduce pageId in object and class properties to make join easy with new table
  • The new API won't support both terminal and non terminal page in the same place but we don't care
  • We apply a fallback when synchronizing Document and Page tables: the Page table contains the non terminal page if any or the terminal page otherwise. So priority goes to non terminal page if the two forms exist.
    • So we'll have a single "Reference" column instead of two columns "Reference" and "Terminal".


  • Fill the holes in the hierarchy right in the Page table (kind of merge Document and Space table in other words)
    • So after the document A.B.C.WebHome is created the page table should contain 3 rows corresponding to A, B and C no matter if the documents A.WebHome and A.B.WebHome exist. In other words the page table should contain all the parents of a page, otherwise we won't be able to display that page in the page tree. So the new page table will deprecate both the documents and the spaces tables.
    • help Need to decide between null page content or explicit field to support holes
      • help We could separate the page fields that are translatable (and related) from the page fields that are shared by all the translations. The page table would contain only the shared fields: reference, parent, hidden (what we have in the spaces table right now). Basically the page table will hold the page hierarchy. The rest of the fields would be stored in a "PageTranslation" table. So a page row can have zero or more rows associated in the page translations table. One of these translations is the default translation. A page with no translation represents a hole in the hierarchy (i.e. a space without a home page). This will allow the page tree to sort the child pages by their translated title using a left outer join (falling back on the default translation, or on the page name when no translation is available).
  • help For the document tree we tried to use a fake Page table that was mapped to a SQL query (the union between the documents and the spaces tables) instead of a real database table. We also tried to use a fake PageTranslation table that was mapped also on a SQL query. The Page entity had a list of PageTranslations. This way we were able to perform a left outer join between the Page table and the PageTranslations in order to sort the child pages by their translated title. The version of Hibernate we're using doesn't support outer joins on unrelated entities. Unfortunately this solution didn't work for the document tree because the queries were too slow. This should not be a problem though if we introduce a real Page table with indexes. The document tree is currently using named native queries, but we can rewrite them as HQL easily when we introduce the new Page / PageTranslation tables.

Future improvements help

Constraints possible future improvements put on the model.

Symlink support

Not a bid deal, just require a "target" column with the reference of the linked page

It imply introducing a new non unique "inode" column in page table and use it as foreign key for all other tables (pagecontent, xobject, attachments, etc.).

help Need to check if it's possible with hibernate (and all the databases engines we support) to use page reference as PRIMARY KEY instead of the number based id we have in document table. That would allow getting rid of the useless unique id column.

  • The id of the xobject and other tables is calculated based on the document reference. Should be manageable by considering this as the main document/page and other "soft hard" links emoticon_smile


  • link supported at request level which means you don't have to think about how to follow links, all the pages really contains the same thing from request point of view
  • a bit less things to modify for a rename: the "inode" does not change so no need to modify other tables (still need to modify reference of the children in the page table and refactor wiki links and other stuff like this which would still be using the reference). Except for the main page which need to go trough the usual refactoring.


  • impossible to directly filter object table by page reference without a join with the page table (or knowing the page "inode")
  • more difficult to synchronize with document table
  • might introduce some security flows caused by the same page content having different access rights


Ideally Fix XWQL issues so that we can forget HQL emoticon_smile

  • dates, subqueries, etc are missing from XWQL - perhaps we need to simply fix this rather than keep supporting (easy to use) HQL
  • we still don't have XWQL in Database List (in XClasses)


Mostly follow the database changes and introduce new PAGE type based on the new Page table.

We should not need to introduce new SOLR types for PAGE children (same as database here again).


Like said in the General section the plan is not to write The New Modelâ„¢ but just to provide to the already existing APIs an easy Page concept oriented access.

  • new class used by hibernate hbm
    • methods for all the fields of the database
    • lazy loaded XWikiPage#getXWikiDocument(XWikiContext) helper to access other stuff like object/attachments/etc. and make easier to reuse and adapt existing code (extending XWikiDocument would make XWikiPage directly expose methods that are not following page concept or that we would want to behave differently for this name). As a bonus if you don't need objects and class properties, getting a XWikiPage would be way faster and take less memory than getting a XWikiDocument.
  • XWiki#getPage(EntityReference)

Future improvements help

  • lazy loaded object and class oriented methods to cover most used XWikiDocument object/class oriented methods (getPageObject(EntityReference), getPageClass(), etc.)
  • returning and taking page elements wrappers (so that you get PageObjectReference when you call getReference(), etc.):
    • XWikiPageObject, XWikiPageClassProperty, XWikiPageAttachment
    • wrapper around "real" database objects (BaseObject, BaseClass, etc)
    • returned by XWikiPage methods (getObjects, getClass, etc.)


We need new events for all the new entity types.


  • REST already uses the URL elements /pages/ but the actual resource only matches URLs containing also /spaces/ element so no conflict here.
  • Need new JAX-RS model for Page instances.
  • Probably need to rewrite most of the model related resources (since the current ones are based on /spaces/... matching URLs) but not a bid deal (mostly means putting stuff in abstracts and a a little plumbing)
  • help Need to think about new search API at wiki level since current ones return Document objects


Need new META tags for current page reference at least.


Do stuff


Created by Eduard Moraru on 2016/07/13 17:47

Get Connected