Amidst a number of successful PoCs, experiments and even productized work (MCTP), this concept aims at formalizing early support for content types in Magnolia, and help feature development move on from there.

Requirements

There's general consensus about the following:

[Magnolia needs] a formal definition for a type of content [...] including the fields that type may contain, and its relationships to other types of content.
Based on this definition, other things can be created with little or no work such as a content app, an editing dialog, and REST endpoints.

—via Content Types

Initial action plan / Spike 0

Based on a registry on one hand, and starting off with a field-based model on the other hand, we could start implementing a minimal user story with few concrete actions.

Status

MGNLCT-9 - Getting issue details... STATUS

MGNLCT-10 - Getting issue details... STATUS

MGNLCT-11 - Getting issue details... STATUS

MGNLUI-4246 - Getting issue details... STATUS

MGNLUI-4238 - Getting issue details... STATUS

MGNLREST-93 - Getting issue details... STATUS

PRs were created, yet they're not deemed to be in a "productized" state atm. Still a bit too reminiscent of the previous PoC efforts.


1. Configuration

Registry

At this stage, the format does not matter as much as what we're going to do with it.
It's also unclear why our YAML format should be considered a misfit—we've been pushing it all around the place—or for what use cases it falls short, concretely.

Either way, Magnolia needs awareness of content types. Covering that with a ContentTypeRegistry is a natural starting point, implying a ContentTypeDefinition as well.

With Magnolia 5.4+ config & resource-loading APIs, this is trivial to set up. We get significant value out of the box:

  • light-module conventions
  • visibility inside the definitions app
  • problem reporting
  • familiar YAML format

Should we hit the wall with the registry or format, and get an alternative on par with benefits above, nothing is set in stone. It just allows us to move on with downstream technical challenges.

Status

CT01. Pick ContentTypeRegistry + ContentTypeDefinition into a new module

MGNLCT-8 - Getting issue details... STATUS

  • Module will sit above core & config, but below UI
  • Move registry <-> config-source bindings to the new module class
  • tentatively YAML-only to start with

Definition outlook

—what does a content-type consist of?

This is also a never-ending topic. We should start small, and add more aspects/features as we go.
As per the high-level vision at the top of this page, the most prominent part of a content-type is its model, its fields.

In fact, there is potential for many existing Magnolia features to shift under the umbrella of content types, eventually.

Content type all-the-things :allthethings:

Just for reference, here's a non-exhaustive list of aspects a content type could specify:

  • data source (envisioning an evolution of content-connectors, without the Vaadin bits)
    • kind
    • coordinates
    • workspace / table / collection name
    • node types
  • model / fields
    • relationships, 1-to-1, 1-to-many, etc.
    • evolution, content version-handling
  • locales
  • folder-support
  • tagging
  • versioning
  • publication
  • personalization
  • renditions / URI bindings / previews
  • cache policies
  • naming / id strategy
  • ownership model / security
  • consistency model
    • all consistent against latest schema (hence content migration)
    • vs. mixed-model version w/ compatibility
  • ...


2. Fields

Modeling

As foreseen, content-types are shifting upstream of apps, that is upstream of any UI/UX consideration.

On the one hand, modeling purists advocate for a strict, dry representation of the model, with almost exclusively primitive property types.
On the other hand, Magnolia has always provided users with pretty loose modeling, driven by field-definitions. The author experience comes first, the data model is deduced from it.

There may be some middle-ground there. With few key improvements, we can keep our familiar field-definitions, while decoupling them from UI/UX considerations.

Again, nothing set in stone. This in turn helps progressing towards generation of content apps and endpoints.

Status

We start simple, with a plain map of named fields. We make FieldDefinitions less UI/UX-bound / more UI-agnostic.

CT12. Infer field-types vs. types both ways

MGNLCT-10 - Getting issue details... STATUS

  • setting "fieldType": FieldDefinition impls have hard-coded types (already)
  • setting "type": infer a simple field type upon form creation (dialog, app)

CT13. Detach Validators from Vaadin

MGNLUI-4246 - Getting issue details... STATUS

  • boilerplate: must implement:
    • Vaadin Validator
    • Magnolia ValidatorFactory
    • Magnolia ValidatorDefinition
  • switch towards standard Bean Validation (well supported by Vaadin too)
  • provide config short-hands for standard bean validators (max-length, range, etc.)
    • validator-registry?
Under the radar (unranked)
  • Support semi-structured content types (leveraging the content-editor)
  • Defining & resolving references to other content-types (leaving linking out first)
  • Groups of fields and/or 1:n relationships

UI bits

In addition to making fields more UI-agnostic, we seek to maintain presentation flexibility on app & form level.

Under the radar

CT11. Once CT gives us a flat list of fields, layout can be configured on app level

MGNLUI-4245 - Getting issue details... STATUS

  • ditch TabDefinitions in favor of an optional layout config


3. Data source

CT21. Reuse automatic workspace creation

MGNLCT-9 - Getting issue details... STATUS
MGNLCT-11 - Getting issue details... STATUS

CT22. Connect an existing app or sub-app descriptor to a ContentTypeDefinition

MGNLUI-4247 - Getting issue details... STATUS

  • experimented in Sang's PoC, via plain contentType reference id
Status

To be discussed / defined.

DEV-617 - Getting issue details... STATUS


4. Content apps

App generation

We seem to have consensus against re-introducing definition builders maintained by hand (like those we reverted before 5.0)

  • A. Either verbosely build/nest configured definitions w/ plain constructors (no new def code)
  • B. And/or we give a shot at leveraging Sasha's code-generation efforts for this
Status

CT23. Generate apps on-the-fly, upon app startup

MGNLUI-4238 - Getting issue details... STATUS

  • AppDescriptorRegistry listens/delegates fluently to the ContentTypeRegistry
  • broadly speaking, CTR is a source for apps
  • resolve a placeholder DefinitionMetadata
  • use a dynamic DefinitionProvider building the app on-the-fly from the type
Options under the radar
  • Support a new, less-boilerplate app descriptor type, conveying higher-level semantics, leveraging content-types
  • Definition-less app on the fly; dynamically built based on CT definition features.
  • Either way, both would cause major changes to app sub-components (e.g. workbench, actions, all presenters heavily relying on defs atm; views hardly usable standalone)

App defaults

  • yet to formalize config patterns, actions, columns, labelling...
  • crud, publishing, import-export
  • different stock apps have different flavors of actionbar section availability
  • even the groovy generator is not fully "canonical", vs. M5 UX guidelines
Status

To be formalized.

Under the radar
  • Composing mixin configuration defaults per content-types capabilities


5. Consuming content

REST endpoint defaults

Status

We have a productized, JCR-based, basic delivery endpoint. Currently this is just one "global" endpoint, taking the workspace name as path parameter.
Therefore at the moment, there's no such thing as one endpoint per content type (might come again later), so nothing extra to register.

MGNLREST-93 - Getting issue details... STATUS

Options under the radar
  • Side-by-side endpoint implementations for CT-based vs. JCR-based.
  • Single endpoint registrations (more content-semantic APIs than with the generic one)
REST improvements will be covered in more details in a separate concept.





  • No labels

8 Comments

  1. Thanks Mika, this looks like a good and practical path forwards.

  2. We had this issue which would be useful when you implementing Content type support because by default you would not be able to publish it properly and version it properly. Please read below use case, problems and solutions for more detail.

    cc: Christoph Meier for documentation update as customer suggestion.

    Versioning and publication with different nodetypes

    -- from SUPPORT-9207

    Use case

    Customer has a custom app which are using custom node types as below:

    • The app allows folders
      • folders inside folders are also allowed
    • Inside a folder a custom nodetype is allowed:
      • bulletin 
    • A bulletin can consist of 0...n contentBlocks
    <nodeType name="bulletin" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
      <supertypes>
        <supertype>mgnl:content</supertype>
      </supertypes>
    </nodeType>
    <nodeType name="contentBlock" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
      <supertypes>
        <supertype>mgnl:contentNode</supertype>
      </supertypes>
    </nodeType>

    Similar to our mgnl:page, mgnl:folder and mgnl:component, mgnl:area types - Here is his JCR content structure example 

    https://jira.magnolia-cms.com/secure/attachment/49049/jcrStructureExample.png

    Problem with activation

      • The editor sees only the bulletins 
      • So this contentBlock subnodes are hidden to the editor
        • (similar as the area/component node structure in the pages app)
      • The publish/publish recursive is called by the editors for the folders and for bulletins
        • (but never for the contentBlocks)
      • I tried both: activate and activateRecursive for bulletins --> but the contentBlocks are not published together with the bulletin 
        • Also activateRecursive called on folder:
          • it publishes the bulletings below, but not the contentBlocks inside the bulletins
      • How is the supertype effecting versioning/publish command?
        • So what is the difference if supertype is mgnl:content or mgnl:contentNode is used?
        • From the description https://documentation.magnolia-cms.com/display/DOCS57/Node+types I think, we use it in the right way (as a contentBlock is like an area in pages)
        • But unfortunatly I cannot find the correct configuration to work as we expect.

    Solution for publication

    The configuration point which could help you include your custom nodetypes into publication process is "itemTypes" under your activation command. An example is here

    /modules/personalization-integration/commands/default/personalizationActivation@itemTypes=mgnl:contentNode,mgnl:componentVariants

    In the example, when a customer publish a personalized content node, its 'componentVariants' get published also.

    So in this case, you would be expected to include your custom nodetypes into your 'itemTypes' property of the command, please use comma separated format without any space.

    Problem with versioning

    When I use itemTypes with empty value and change the contentBlock to be child of mgnl:content, all nodes are published (need to use the recursive=true also for bulletins).

    But the versions are not good for me: 

    • A bulletin and it's contenBlock are edited in one mask, so for the editor it is one "unit"
    • E.g. bulletin.name = aaa, contentBlock.text=aaa
      • Publish --> everything goes to public --> ok
      • Editor changes: bulletin.name=bbb, contentBlock.text=bbb
      • Now he restores the published version
      • Resulting in: bulletin.name=aaa, contentBlock.text=bbb --> WRONG
    • I have also seen in /magnolia-core-5.6.6.jar!/mgnl-nodetypes/magnolia-nodetypes.xml
      • The area (also component) uses mgnl:contentNode as supertype, I think from the usecase we have a similar one
        • our bulletin --> like a page --> the object which is visible for the editor
        • our contentBlock --> like an area/component --> the editor does not see, that these are separated nodes in jcr
        • publish: only page is published, areas/components are published implicitly
        • version: the version consists of the "full" state of the page, so somehow the areas/components are versioned together with the page 
      • <nodeType name="mgnl:area" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
          <supertypes>
            <supertype>mgnl:contentNode</supertype>
          </supertypes>
        </nodeType> 
    • so we would need the same logic as for pages - at least I hope that would solve our problem

    Solution for versioning

    Referencing to restoreAllChildren function of 'RestorePreviousVersionCommand' class here https://nexus.magnolia-cms.com/content/sites/magnolia.public.sites/ref/5.7.1/magnolia-core/apidocs/index.html, you can see that you need to set 'itemTypes' in that command parameters and setting 'parentNodeTypeOnly' to false - which is set to 'true' by default in '/modules/pages/apps/pages/subApps/browser/actions/restorePreviousVersion@parentNodeTypeOnly'

    Finally it works with this itemTypes: mgnl:contentNode,mgnl:metaData,mgnl:resource,contentBlock

    --> thus extending the default of this with our custom type.

    Customer suggested us to update our documentation for this use case

    To be honest, I do not fully understand why now working. Is there some info about how this works together in the documentation? Which impact the itemTypes have for versioning, publication and using it together. (I could not find the itemTypes or related topics in the documentation - but maybe I have just not seen)

    1. A quite complex topic Viet Nguyen.

      I am not yet sure which doc pages and how to update. 
      As I said, a really complex case - I have to think about more in depth.

      Probably would be already worth to describe exactly this "use case" - as it is written here - but with more details, and with the solution and some explanations ...
      Could be in the WIKI.

      And since this comment is on the Content Types page ... you are aware of the fact that we will release The Magnolia Content Types module with Magnolia-6.0, right?

      1. As long as we successfully implemented Content Type theme, content editors would be able to define and manage different content types themselves. Then lots of content (data) using those types would be on production.

        So we need to have a proper solution to support publishing and versioning for their custom content types without manually or customization. Then we won't need to add any documentation.

        If we didn't have any out of the box working content type suite yet, Mikaël Geljić please provide us a clean and clear way on how to achieve it, my provided steps are just manually changing the configuration points which is not so convenience if a content editor have to do so many steps for his new content type.

        1. The only difference between mgnl:content and mgnl:contentNode is that the first one is mgnl:versionable and the latter is not. This means contentNodes are "typically" versioned with their parent (without any recursion).

          Yes, this is indeed similar to pages vs. areas/components, or Stories app's compositions vs. blocks (which looks very similar to what they are doing btw). Your node-type assumptions are correct.
          In fact, we are taking the same assumptions for Content Types: the root "model" produces mgnl:content while sub-models (composite or multiple property groups within that model) result in mgnl:contentNodes. 

          So this is likely *not an issue for Content Types to fix, but rather for versioning/publication*.

          We need to recollect the rationale why parentNodeTypeOnly is true by default, and whether mgnl:contentNode could be present in itemTypes by default. (cc Roman Kovařík)
          I expect the type-checks to be done with javax.jcr.Node#isNodeType, so there should be no need for additional configuration for custom sub-types.

          Returns true if this node is of the specified primary node type or mixin type, or a subtype thereof.

          With that said, can we move the discussion back to the support ticket?

          Thanks for reporting and for the thorough investigation Viet Nguyen.

          1. So

            With that said, can we move the discussion back to the support ticket?

            → No please, our support ticket has been fixed by providing him with correct configuration for his use case, we are not trying to go further in supporting him this 'corner case'.

            However if we are trying to support Content Types out of the box, we would have to consider other aspects such as versioning and publishing like below:

            So this is likely *not an issue for Content Types to fix, but rather for versioning/publication*.

            → We are not mentioning a 'fix' in Content Types, we are discussing a solution on how would we support. For example:

            • We will automatically generate proper configuration for a newly created node-type and remove its correspondent configuration when user remove it.
            • Or we improve our type-checking mechanism to automatically recognize things that end users publishing / versioning, then your released features (content type theme) will compatible and work out of the box.
            1. Ok, copy that. Exactly, I'd aim at the second solution then. Let's open a MAGNOLIA ticket.

              1. Ticket created in  MAGNOLIA-7415 - Getting issue details... STATUS