Cms module

This module adds the content-management system (CMS) capabilities to your project. Adding it to your classpath will let you create a website and later manage the content inside it, without restarting or redeploying your project.

Business

Structural elements

Before diving in the CMS module, you need to grasp the difference between the different notions. This module talks about PageTemplate, Page, CmsSlot and Widget. Please read below about each one of them.

Page templates

Your website is composed of different web-pages. Each of these pages can be further classified, based on the design fuctionalities they offer. The PageTemplate is exactly this - the template your page is of, and the categorization of this page. We use the page templates to keep the consistency across the whole website. For example, you might have a single-column page template, and a two-column page template.

These page templates very roughly describe what type of pages you will have in your project. Every PageTemplate has a frontendTemplateName property of type java.lang.String which points to the location of a JSP file, which we will use to render the pages that have this page template:

io.nemesis.platform.module.cms.core.definition.CmsPageTemplateEntityDefinition.java
Unresolved directive in <stdin> - include::/opt/bitnami/apps/jenkins/jenkins_home/workspace/nemesis-platform-master/modules/nemesis-module-cms/src/main/java/com/nemesis/platform/module/cms/core/definition/CmsPageTemplateEntityDefinition.java[tags=frontendTemplateName]

The page templates have a style property that stores some custom CSS style so that you don’t need to redeploy the site every time there is a tiny change in the CSS.

Your pages do also have a style property. If defined, the custom page CSS overrides the template’s CSS.

Content slots

Once you have defined how many different templates you will have in your system and how many pages you will have, it is time to put some content in those pages. This is done by means of using the CmsSlot objects. Content slots are defined in two parts - first they are created in the database (just like pages), but they are also defined in the view layer which specifies where in the DOM they will sit.

Further, on every PageTemplate there is a java.util.Collection of CmsSlot objects assigned to it.

io.nemesis.platform.module.cms.core.definition.CmsPageTemplateEntityDefinition.java
Unresolved directive in <stdin> - include::/opt/bitnami/apps/jenkins/jenkins_home/workspace/nemesis-platform-master/modules/nemesis-module-cms/src/main/java/com/nemesis/platform/module/cms/core/definition/CmsPageTemplateEntityDefinition.java[tags=slots]

This allows us to define what areas of the look and feel will be editable later on, when we run the website. Continuing our example our single-column template can define the following slots: cs-logo and cs-footer and the two-column page template would define the same.

It might seem useless to define two page templates, while they have the same content slots defined. You must remember that each page template has a different view URL assigned to it. In this way we can have different structure of the DOM for different page templates (single column, two-column, etc.)

Finally, every Page object also holds a java.util.Collection of CmsSlot objects.

This allows the page to define some more content slots that are different per page, while the page template will define the slots that are common for every page that is of this page template. In our scenario, the homepage will define content slots cs-section1, cs-section2 and cs-section3, while the loginpage will have cs-left-box and cs-right-box.

Widgets

Widgets are the functionalities that you can change on the page. You can change a certain slot to contain a banner, or an image, or a piece of text, or a carousel of some sort, or pretty much anything. As you can see, the CmsSlot has a relation to a java.util.Collection of widgets:

io.nemesis.platform.module.cms.core.definition.CmsSlotEntityDefinition.java
Unresolved directive in <stdin> - include::/opt/bitnami/apps/jenkins/jenkins_home/workspace/nemesis-platform-master/modules/nemesis-module-cms/src/main/java/com/nemesis/platform/module/cms/core/definition/CmsSlotEntityDefinition.java[tags=widgets]

This allows you to specify which widgets will be rendered in which slots. If more than one widget is added in a slot, they will be rendered one after another. Each widget extends the AbstractActivatableEntityDefinition which adds a field called active to control which widgets are active and which not. Widgets also extend the AbstractFilterableEntityDefinition to specify a java.util.Collection of AbstractFilterEntityDefinition to again control which widgets will be visible when.

Request flow

Here’s how a sample request flow goes, from the moment a user types a page url to the moment the page is rendered on his screen.

  • First, the user types a URL (let’s imagine this is /contacts) and their browser makes a request to the server.

  • Then the platform tries to find a Spring MVC controller to handle this request. If a controller is found, the request is handled and the controller must return the name of the view the server will render to the client.

  • If a controller is not found, then the platform will try to find a Page instance in the database with urlPath field matching what was requested (/contacts). If a page is not found, then the platform will try to find a Page in the database with the id field matching what was requested. If no page is found, the platform will throw a RequestedResourcesNotFoundException and the controller will return a 404 page to be rendered.

  • If, in the previous step, a page is found, the controller will add the content slots of the page, together with the content slots of the template in the request model and return the view URL from the masterTemplate of the page template of the page that was found.

  • When rendering the view, the tag libraries will make so that the content slots defined in the view, will renderer the widgets that are currently active in the given content slot.

  • The end result is an HTML document that gets sent back to the client.

Development

Core

Entity Definitions

The definitions in this module have id discriminators in the range 150-170.

PageKeywordDestinationEntityDefinition

The PageKeywordDestinationEntityDefinition is a type of SearchKeywordDestinationEntityDefinition:

asciidoctor diagram PageKeywordDestinationEntityDefinition

The entity denotes e redirection to a given page, passed as a method parameter. The defined property here is page. It comes along with the respective getter and setter.

AbstractCmsEntityDefinition

The AbstractCmsEntityDefinition extends the AbstractEntityDefinition:

asciidoctor diagram AbstractCmsEntityDefinition

Via the respective getter-setter pairs, the following information can be retrieved/stored in the database:

Property Description

title

stores the title of the cms entity

content

stores the content of the cms entity

publishDate

stores the date this entity is to be published

AbstractMetaDatableEntityDefinition.

The AbstractMetaDatableEntityDefinition extends the functionalities defined within the AbstractEntityDefinition. The AbstractMetaDatableEntityDefinition is a base class for all entities that need to provide metadata attributes.

asciidoctor diagram AbstractCmsEntityDefinition

The one getter-setter pair defines a map of <String, String> metadata attributes.

CmsPageTemplateEntityDefinition

The CmsPageTemplateEntityDefinition extends the functionalities defined within the AbstractEntityDefinition and the AbstractCatalogableEntityDefinition:

asciidoctor diagram CmsPageTemplateEntityDefinition

This is the base definition for all abstract templates. Via the respective getter-setter pairs, the following information can be retrieved/stored in the database:

Property Description

name

stores the descriptive name of the template

frontendTemplateName

stores the template’s name, used as part of the url to access it from the frontend

style

stores the custom css styles to be applied on every page of the template

cssClasses

stores the applicable for the template css classes

cmsSlots

stores a set of CmsSlotEntityDefinition slots

CmsCatalogEntityDefinition

The CmsCatalogEntityDefinition adds the cms-related attributes to the CatalogEntityDefinition. The CatalogEntityDefinition, in its turn, extends the AbstractEntityDefinition and the AbstractNameableEntityDefinition.

asciidoctor diagram CmsCatalogEntityDefinition

The getter-setter within the sites property lets you retrieve/store a set of sites the catalog belongs to.

asciidoctor diagram CmsPageEntityDefinition

This is the basic entity for all content pages. The defined here getter-setter pair is homePage. It stores information if the current page is the home page or not

The url of the page is constructed from the categories the page belongs to + the code of the page (i.e. '/A/B/C/page.code').
Property Description

title

stores the title of the page

name

stores the descriptive name of the page

cssClasses

stores the applicable for page the css classes

style

stores the custom css styles to be applied on every page of the template

masterTemplate

stores the master template for the page, defining the view url of a given page

slots

stores a set of CmsSlotEntityDefinition slots

CmsSiteEntityDefinition

The CmsSiteEntityDefinition adds the cms-related attributes to the SiteEntityDefinition and the AbstractMetaDatableEntityDefinition :

asciidoctor diagram CmsSiteEntityDefinition

This is the basic entity for the cms site. Via the respective getter-setter pairs, the following information can be retrieved/stored in the database:

Property Description

googleAnalyticsKey

stores the Google analytics key for the site

responsive

stores information if the site is responsive or not

viewSuffix

stores the view suffix for the site (.html, .jsp)

cmsCatalogs

stores a set of CmsCatalogEntityDefinition catalogs for the site

startingPage

stores the starting page for the site

listerPage

stores the lister page for this site

detailsPage

stores the details page for this site

theme

stores the theme for the site

robots

stores the robots.txt snippet for this site

CmsSlotEntityDefinition

The CmsSlotEntityDefinition extends the AbstractEntityDefinition the AbstractActivatableEntityDefinition and the AbstractCatalogableEntityDefinition. Keep in mind that content slots are defined on every page or template and contain a number of widgets to be displayed on the page:

asciidoctor diagram CmsSlotEntityDefinition

Via the respective getter-setter pairs, the following information can be retrieved/stored in the database:

Property Description

position

stores the position of the content slot

cssClasses

stores the css classes for content slot

page

stores the page template the content slot belongs to

widgets

stores a list of WidgetEntityDefinition widgets that belong to the content slot

PageEmailMessageEntityDefinition

The PageEmailMessageEntityDefinition extends the features of the EmailMessageEntityDefinition:

asciidoctor diagram PageEmailMessageEntityDefinition

The page property, defined here, lets you keep track of the particular page the email message is for.

asciidoctor diagram SiteThemeEntityDefinition

The description getter-setter pairs lets you retrieve/store the description for the theme in the database.

WidgetEntityDefinition

The WidgetEntityDefinition is the basic definition for all widgets. It extends the features, defined in AbstractEntityDefinition, AbstractActivatableEntityDefinition, AbstractCatalogableEntityDefinition, AbstractCmsEntityDefinition and AbstractFilterableEntityDefinition:

asciidoctor diagram WidgetEntityDefinition

The widgtes are contained within the content slots of a particular page. Via the respective getter-setter pairs, the following information can be retrieved/stored in the database:

Property Description

name

stores the name of the widget

cssClasses

stores the css classes for the widget

initializeScript

stores the init JS script for the widget

Spring Data JPA Repositories

PageKeywordDestinationRepository

The PageKeywordDestinationRepository extends the BaseEntityRepository and is the corresponding Spring Data JPA repository for the PageKeywordDestinationEntityDefinition.

asciidoctor diagram PageKeywordDestinationRepository
CmsCatalogRepository

The CmsCatalogRepository extends the BaseEntityRepository and is the corresponding Spring Data JPA repository for the CmsCatalogEntityDefinition.

asciidoctor diagram CmsCatalogRepository
CmsPageRepository

The CmsPageRepository extends the ActivatableRepository and is the corresponding Spring Data JPA repository for the CmsPageEntityDefinition.

asciidoctor diagram CmsPageRepository
CmsSlotRepository

The CmsSlotRepository extends the ActivatableRepository and the BaseCatalogableEntityRepository. The CmsSlotRepository is the corresponding Spring Data JPA repository for the CmsSlotEntityDefinition.

asciidoctor diagram CmsSlotRepository
PageEmailMessageRepository

The PageEmailMessageRepository extends the BaseEntityRepository and is the corresponding Spring Data JPA repository for the PageEmailMessageEntityDefinition.

asciidoctor diagram PageEmailMessageRepository
PageTemplateRepository

The PageTemplateRepository extends the BaseCatalogableEntityRepository and is the corresponding Spring Data JPA repository for the PageTemplateEntityDefinition.

asciidoctor diagram PageTemplateRepository
SiteThemeRepository

The SiteThemeRepository extends the BaseEntityRepository and is the corresponding Spring Data JPA repository for the SiteThemeRepository.

asciidoctor diagram SiteThemeRepository
WidgetRepository

The WidgetRepository extends the ActivatableRepository and the BaseCatalogableEntityRepository. The WidgetRepository is the corresponding Spring Data JPA repository for the WidgetEntityDefinition.

asciidoctor diagram WidgetRepository

Business Services

AbstractPageService

Among the helper functionalities, defined within the AbstractPageService, are:

Description Method

to obtain the name of the current frontend template*

getFrontendTemplateName()

to obtain the home page for the entity

getHomepage()

to obtain a collection of page entities by the given urlPath or code

getPagesForUrlPathOrCode()

to obtain the home page urlPath

getUrlPathOrId()

to obtain all content slots for the given page

getCmsSlotsForPage()

CmsSiteService

The CmsSiteService adds the cms features to the SiteService. As you may see from the diagram below, the inheritance goes further to the SiteEntityDefinition and, respectively, the AbstractEntityDefinition, and the AbstractDescriptionableEntityDefinition.

asciidoctor diagram CmsSiteService

The helper functionality, defined here, is getStartPageUrlPathOrId(). It allows you to obtain the urlPath or the id of the starting page for the given site.

CmsSlotService

The CmsSlotService is to hold the service logic for the cms module related to CmsSlotEntityDefinition

PageTemplateService

The PageTemplateService is to hold the service logic for each of the page templates.

WidgetService

The WidgetService is to hold the service logic for the cms widgets.

Facade

MapperFactoryConfigurers

CmsPageMapperFactoryConfigurer

The CmsPageMapperFactoryConfigurer implements the MapperFactoryConfigurer, converting the CmsPageEntityDefinition to PageDtoDefinition:

asciidoctor diagram CmsPageMapperFactoryConfigurer

The registered conversions, within the configurer, are:

  • from CmsSlotEntityDefinition to CmsSlot,

  • from PageTemplateEntityDefinition to PageTemplateDto,

  • from CmsPageEntityDefinition to PageDtoDefinition.

CmsSiteMapperFactoryConfigurer

The CmsSiteMapperFactoryConfigurer implements the MapperFactoryConfigurer:

asciidoctor diagram CmsSiteMapperFactoryConfigurer

There are 2 conversions, registered here:

  • from SiteThemeEntityDefinition to SiteThemeDto and

  • from CmsSiteEntityDefinition to CmsSiteDtoDefinition

The conversion is done via the byDefault().

WidgetMapperFactoryConfigurer

The WidgetMapperFactoryConfigurer implements the MapperFactoryConfigurer:

asciidoctor diagram WidgetMapperFactoryConfigurer

The two conversions, registered byDefault() here, are:

  • from WidgetEntityDefinition to WidgetDtoDefinition and

  • from WidgetEntityDefinition to SearchRequestCmsDtoDefinition

More about the mapping configurations you may read in the respective Orika guide.

Dto definitions

* AbstractMetaDatableDtoDefinition*.

The AbstractMetaDatableDtoDefinition is the corresponding Dto object for the AbstractMetaDatableEntityDefinition.

CmsDtoDefinition

The CmsDtoDefinition extends the SearchableDtoDefinition.

asciidoctor diagram CmsDtoDefinition
CmsSiteDtoDefinition

The CmsSiteDtoDefinition extends the SiteDtoDefinition and the AbstractMetaDatableDtoDefinition. This is the corresponding Dto object for the CmsSiteEntityDefinition.

asciidoctor diagram CmsSiteDtoDefinition
CmsSlotDto

The CmsSlotDto is the corresponding Dto object for the CmsSlotEntityDefinition

PageDtoDefinition

The PageDtoDefinition is the corresponding Dto object for the CmsPageEntityDefinition. The PageDtoDefinition extends the AbstractMetaDatableDtoDefinition and the AbstractSearchEngineOptimizableDtoDefinition:

asciidoctor diagram PageDtoDefinition
PageTemplateDto

The PageTemplateDto is the corresponding Dto object for the PageTemplateEntityDefinition

WidgetDtoDefinition

The WidgetDtoDefinition extends the AbstractEntityDtoDefinition. This is the corresponding Dto object for the WidgetEntityDefinition.

asciidoctor diagram WidgetDtoDefinition

Facades

AbstractPageFacade

Some helper methods are defined within the AbstractPageFacade. Among the functionalities included here, are:

  • to obtain a page Dto for the given pathUrl or code,

  • to obtain the current home page,

  • to obtain the urlPath or the id for the given page Dto,

  • to obtain the name of the current frontend template,

  • to obtain the category, as well as the product Dto pages,

  • to obtain the CMS slots, available on the page

CmsSiteFacade

The CmsSiteFacade extends the SiteFacade:

asciidoctor diagram CmsSiteFacade

An extra functionality, defined here, is the option to obtain either the urlPath, or id of the starting page of the given site.

CmsSlotFacade

Some helper methods are defined within the CmsSlotFacade. Among the functionalities included here, are:

  • to obtain a CMS slot with the given code,

  • to obtain the page of the particular content slot,

  • to obtain either all, or a random widget for the given slot

PageTemplateFacade

The PageTemplateFacade adds the option to get all cms slots for the template with the given template code.

WidgetFacade

Some helper methods are defined within the WidgetFacade. Among the functionalities included here, are:

  • to load or obtain a widget with given id, as well as

  • to check if a particular widget is visible or not

Storefront

AbstractController

As the base controller, the AbstractController provides all of the common functionalities for the controllers.

The root for requests is /.

AbstractViewController

The AbstractViewController is the base controller for all page controllers. Here are defined all of the common functionalities for them.

The root of the views is at /layout/

AbstractWidgetController

The AbstractWidgetController is the base controller for all widgets. As such, it defines all of their common functionalities.

ContentViewController

The ContentViewController is aimed at rendering views directly. It comes in handy when you need to fetch the content of the view.

The HTTP Endpoint is at /content/view/{path}

DefaultWidgetController

The DefaultWidgetController extends the AbstractWidgetController.

asciidoctor diagram DefaultWidgetController

The HTTP Endpoint is at /view/.

FallbackCmsViewController

The FallbackCmsViewController extends the AbstractViewController and implements the Spring mvc Controller:

asciidoctor diagram FallbackCmsViewController

Each client’s search request for a particular page is based on the page’s urlPath parameter. The urlPath is checked against the stored information in the database. When a resource is mapped to the request, the particular view is rendered. Otherwise, the FallbackCmsViewController returns a 404 resource not found message.

RobotsController

The RobotsController defines an HTTP Endpoint at /robots.txt. The respective GET method handles the web robots instructions.

The generated views may be found at WEB-INF/views/${DEVICE_PREFIX}]/cms/widget.[EXTENSION]

For further details on mapping, check the corresponding mapping actuator accessible at /platform/mappings.

Test your REST API

Configuration

Name Type Description

nemesis.cms.include-site-in-view-name

java.lang.Boolean

nemesis.cms.maintenance-during-migration

java.lang.Boolean

nemesis.cms.path-locale-filter-exclude-urls

java.util.List<java.lang.String>

Unmap the following urls from path-locale filter.

nemesis.cms.view-root

java.lang.String

nemesis.cms.widget.base-path

java.lang.String

Controller base-path - all widget controllers will be mapped under this url.