Skip to content

Development

This document describes application development for WebSight CMS. We assume you completed the project setup guide and generated a new project from the Maven archetype. All the screens and examples presented below refer to the project prepared in the previous step.

Note

You don’t need to read and understand all the linked content, basic concepts will be explained here.

WebSight CMS is based on Apache Sling which “is a framework for RESTful web-applications based on an extensible content tree”​​ and OSGi specification - “Java framework specification that supports the deployment of extensible and downloadable applications known as bundles”. What does this mean? The two most important things coming from the technologies WebSight CMS is based on, needed to understand this guide, are OSGi bundles and Resources.

OSGi bundle

OSGi bundle is a unit of modularization in OSGi specification - a bundle is comprised of Java classes and other resources, which together can provide functions to end users. Open http://localhost:8080/system/console/bundles to see all the Bundles on the WebSight CMS instance and use the filter bar at the top to filter the list.

Some of the bundles are delivering the OSGi specification implementation (list filtered by org.apache.felix; Apache Felix is an implementation of the OSGi specification): Bundles - OSGi secification implementation

Some of the bundles are delivering Apache Sling functionality (list filtered by org.apache.sling): Bundles - Apache Sling functionality

Some of the bundles are delivering WebSight CMS functionality (list filtered by WebSight): Bundles - WebSight CMS functionality

And finally, some of the bundles are delivering the functionality of the application which was just generated from archetype (list filtered by my-artifactId which was used in example project generation at the beginning of the guide): Bundles - application functionality

Click on my-artifactId-backend bundle to open details. At the beginning the bundle definitions were mentioned: OSGi bundle is a unit of modularization in OSGi specification - a bundle is comprised of Java classes and other resources, which together can provide functions to end users.

At the screen below it is highlighted that the my-artifactId-backend is exporting (making it available to use for other bundles) some Java packages (with use of Export-Package standard OSGi bundle header - provided by bnd-maven-plugin in pom.xml and package-info.java files in the code base) and is providing some resources (with use of Sling-Bundle-Resources bundle header handled by Bundle Resources Provider). Bundles - my-artifactId-backend

Resources

As already mentioned: WebSight CMS is based on Apache Sling which “is a framework for RESTful web applications based on an extensible content tree”. It is important to understand the concept of an “extensible content tree”.

WebSight CMS Resource Browser admin tool allows browsing all Resources available on the instance. Resources are organized in the tree and every resource has a path and properties. Resources are abstractions that represent objects which might be coming from different sources. Resource Browser provides an option to select ‘Providers’ (sources of Resources available in the instance) used to display the presented Resources tree. We will focus on JCR and Bundle resources.

http://localhost:8080/apps/browser#/ WebSight CMS - Resource Browser

JCR (Java Content Repository) is a database with a tree structure consisting of nodes with properties. Nodes in JCR are reflected by the JCR Resource in the Resources tree. JCR is based on Java specification and implemented by Apache Jackrabbit which is also part of Sling and WebSight CMS (check the bundles list mentioned in the previous chapter and filter by org.apache.jackrabbit to see related bundles). For technical details check the links (it is not needed for this guide, all you need to know is explained in this document):

Content stored in JCR is represented by JCR Resources (provided to Resources tree by JCR Resource provider). WebSight CMS is storing JCR content in MongoDB (this is the default setup and we will not go into other options here). JCR is used for all the content created during content authoring. Every created page and every added component is represented by nodes (with properties containing data) in the JCR and Resources tree.

Resources could be also provided by OSGi Bundles. From the perspective of the Resources tree and Resource abstraction, there is no difference between resources provided by bundles and JCR. However, the bundle resources are read-only so would not be suitable for authorable content but are great for providing applications. The application resources provided by bundles are available as long as the bundle is available and are not stored in JCR - application data is not mixed with content data which is great from the perspective of Blue-green deployments, CI/CD, and Separation of concerns (but we will not go into details here).

For technical details check the link (it is not needed for this guide, all you need to know is explained in this document): https://sling.apache.org/documentation/bundles/bundle-resources-extensions-bundleresource.html

This is how bundle resources are provided in the generated project: Bundle resources - generated project

and the same resource in the resource browser: http://localhost:8080/apps/browser#/apps/example-project/components/hello Resource browser - generated project

This is how JCR resources are defined in the codebase in the content module: JCR resources in codebase

And in the Resources tree: http://localhost:8080/apps/browser#/content/example-project/pages/homepage/jcr:content Resource tree

Backend Resources

Generated application/backend module contains in src/main/resources folder example application resources needed to work with Pages in WebSight CMS. The resources structure starts at /apps/example-project path. This path is set in the proper OSGi bundle header to provide the information about resources delivered by the bundle.

Resource structure tree

The following resources are defined:

.
└── apps
    └── example-project             - application root "sling:resourceType": "ws:Application"
        ├── components              - folder containing components
        │   ├── container           - example container component
        │   ├── hello               - example component
        │   └── page                - example page component
        └── templates               - templates folder
            ├── contentpage         - example page template
            └── pagesspace          - example pages space template

Application root should be under /apps resource and must contain property sling:resourceType" = "ws:Application. Folders containing components and templates must be named ‘components’ and ‘templates’ and be under the application root resource. Different relative paths could be set by providing ‘components’ or ‘templates’ properties with relative paths to components or templates folders located under the application root resource - otherwise, components and templates will not be available in the authoring UI.

Pages Space template

In WebSight CMS content is organized in Spaces - areas where dedicated teams can work on content. WebSight CMS allows the creation of two types of spaces

  • Assets (Digital Assets Manager) - allows managing assets
  • Pages - allows managing pages and assets (includes the same functionality as Assets Space and more)

The content module in the project generated from the archetype contains the Pages Space instance ‘Example project’ visible in the All Spaces view. New space can be created from UI:

Create space - type selection

Create space - pages configuration

In the second step, the Space Template needs to be selected in case of Pages Space creation. The list contains the ‘Example Project Pages’ template defined at /apps/example-project/templates/pagesspace resource. Pages Space template resource must use sling:resourceType equals ws:PagesTemplate and should provide allowedChildren property defining the list of allowed pages templates to create.

Page template - resource

Another Pages Space template could be defined in the application if needed. For example:

/apps/example-project/templates/anotherpagesspace
{
 "sling:resourceType": "ws:PagesTemplate",
 "title": "Another Example Project Pages",
 "allowedChildren": ["/apps/example-project/templates/contentpage"]
}

To deploy the updated bundle to the running instance, use the command from the backend module folder:

mvn clean install -P autoInstallBundle

Page template - bundle instalation

New Pages Space template will be available: New page template - space creation

Page template

Pages spaces are for page management. To create a new page, a page template is needed. Generated backend module provides example page template resource /apps/example-project/templates/contentpage

  • sling:resourceType property of the page template must be ws:PageTemplate.
  • title and description properties are used in UI.
  • allowedChildren property contains an array of page templates that can be created under pages created from this template. The content Page template allows to the creation of subpages of the same type.

New page template - resources

The /apps/example-project/templates/contentpage was listed in allowedChildren property in the Pages Space template (/apps/example-project/templates/pagesspace ) which is templates of the Example Project space: New page template - resource browser

This means that page template /apps/example-project/templates/contentpage can be created under pages root in the space: http://localhost:8080/apps/websight/index.html/content/example-project/pages (click Create Page button) New page - template selection

In the second step page properties can be set: New page - dialog

The dialog displayed at this step is a dialog of the component defined in the initial content of the page template (sling:resourceType": "example-project/components/page). Read more about components and dialogs in Components documentation.

The initial content of the page template is defined in a resource named ‘initial’ located under the page template resource. The initial content is copied to initialize the created page and properties set via dialog are set on the copied page content. Page is a node of type ws:Page. It contains a page content sub-node named jcr:content of type ws:PageContent. The nodes located under the page content node can be modified via authoring UI. All the Page properties including properties set via page dialog are set on the page content node. This is initial content of /apps/example-project/templates/contentpage page template: Initial content for the template

This is how the content node of the newly created page looks: Content node - resource browser

New page templates can be created in the application. /apps/example-project/templates/examplpage is a copy of /apps/example-project/templates/contentpage with changed title, allowedChildren

/apps/example-project/templates/examplpage
{
 "sling:resourceType": "ws:PageTemplate",
 "title": "Example Page",
 "description": "Example Project",
 "allowedChildren": ["/apps/example-project/templates/examplpage"]
}

and initial content:

{
 "jcr:primaryType": "ws:Page",
 "jcr:content": {
   "jcr:primaryType": "ws:PageContent",
   "sling:resourceType": "example-project/components/page",
   "container": {
     "sling:resourceType": "example-project/components/container",
     "hello": {
       "sling:resourceType": "example-project/components/hello"
     },
     "hello1": {
       "sling:resourceType": "example-project/components/hello",
       "helloName": "Example"
     }
   }
 }
}

To make it possible to create under pages root in the space it must be added to allowedChildren in pages space template /apps/example-project/templates/pagesspace:

Deploy changes again with: mvn clean install -P autoInstallBundle

The new template is available to create in pages root: New template available

Page created from this template contains defined initial content:

Components

Content is assembled from components - elements rendering parts of content according to implemented functionality. To understand the Components concept see the Components documentation.

Generated backend module contains 3 example components located under /apps/example-project/components

  • page - component used to render page content node
  • container - container component - allows adding of the child components via authoring UI
  • hello - component displaying hello text

In the editor components list, only the hello component is visible because other components are hidden because of group property value.

http://localhost:8080/apps/websight/index.html/content/example-project/pages/new-page::editor

New components can be defined to deliver application functionality. We will add a new component named Rich Text which will allow advanced text editing. Create new folder under /apps/example-project/components named richtext with content:

{
 "sling:resourceType": "ws:Component",
 "title": "Rich Text",
 "description": "Allows advanced text edition",
 "group": "Example Project"
}

Define dialog resource:

{
 "sling:resourceType": "wcm/dialogs/dialog",
 "richtext": {
   "sling:resourceType": "wcm/dialogs/components/richtext",
   "label": "Text",
   "name": "text"
 }
}

Define rendering script richtext.html (name must be matching component resource name + .html):

<data-sly data-sly-test="${properties.text && properties.text != '<p></p>'}">${properties.text @ context='html'}</data-sly>

See Components documentation for more details.

This is how the new component definition looks in the codebase. Deploy the change with the command from the backend module: mvn clean install -P autoInstallBundle

The new component is available now in the editor and can be added to the page. If text is not configured via dialog, nothing is rendered because of the data-sly-test statement in the component renderer. If nothing is rendered by the component the placeholder is displayed automatically in the editor. Edit action can be used to open dialog and use rich text dialog input to configure the text.

Frontend

Frontend scripts and resources are provided by the frontend module - webpack project containing the application frontend. During the build, the resources are embedded into a bundle which is also deployed to the instance. The generated module contains just a simple CSS class to center the text used in the hello component. The CSS files are built into the main.css file by webpack and embedded into the OSGi bundle installed on the instance which makes the files available as resources (because of the Sling-Bundle-Resources header in the bundle header). Frontend resources are published automatically because of the WebSight-Apps-WebRoot bundle header (see next chapter about publishing). The CSS file is included in the page component renderer to load the CSS.

http://localhost:8080/apps/browser#/apps/example-project/webroot/main.css

Add the hello component to the page to see the centered hello text

Publishing

Assembled content can be previewed in the editor and published to make it available for end users.

http://localhost:8080/apps/websight/index.html/content/example-project/pages/new-page::editor

The published page is served by the Nginx container:

http://localhost/new-page.html

End-to-end tests

Test module contains content used during end-to-end tests execution to validate the application. See the example test content and test script for the hello component:

The next steps

You learned the application development process for WebSight CMS. Now, we recommend exploring more details: