Similar content

Loading

Powered by Canoo FindIT.

Module mechanism

Magnolia CMS has a modular architecture. A module is a independent component that performs a particular task or is used to package content and functionality. For an introduction into the module mechanism, see Modules in the Technical Guide

Configuration items

Magnolia provides standard components including controls, templates, paragraphs, and dialogs. If you create customized implementations of such components you should configure them in your module.

The configured items must be stored directly under the module node in order to be automatically registered by Magnolia. Because Magnolia monitors configured items, any changes in the configuration of registered items will immediately be active. The config node uses Content2Bean to populate all registered module classes as Java Beans with the content of the config node. That is why it is important to put specific configuration details in the config node.

This is a list of available configuration items.

Configuration item Function of Configuration Item Details or Example
config Module-specific configuration which will be available via the module class (see below). Config contains parameters and data for your module
templates Template definition. Templates define page composition. They can use FreeMarker, JSP or a custom templating language. For example, stkNews is a template definition provided in the Magnolia Standard Templating Kit (STK). Its purpose is to render a news page.
paragraphs Paragraph definition. Paragraphs can use FreeMarker, JSP or a custom templating language. A paragraph is a content subelement of page. The paragraph definition defines the script which is used to render the content. It also defines the dialog used to edit the content. For example, one of the most used paragraphs is stkTextImage provided in STK. It's purpose is to render a subtitle, some text and an image.
dialogs Define a configured dialog. Dialog to edit the content of sample text & image of paragraph
controls Define your own dialog control. Allows editing of the control
trees Define a tree to be used in AdminCentral and when browsing in dialogs Defines where in the tree will be displayed in the Website view of AdminCentral.
commands Define commands to use with the Magnolia command management. Activates the command
pages Define a page to be used in AdminCentral. For instance, JCR Queries in the Tools menu.
virtualURIMapping Makes the rendering depend on a URI pattern. Default URI: defines which page should be rendered if no path is specified
template-renderers Define a new template type. You can integrate logic before rendering a page or use your preferred rendering engine. Magnolia ships with JSP and FreeMarker template renderers. You can also create a custom one for another templating language.
paragraph-renderers Define a new paragraph type. You can integrate logic before rendering a paragraph or use your preferred render engine. Magnolia ships with JSP and FreeMarker paragraph renderers. You can also create a custom one for another templating language.

Module descriptor elements

Element Description
name The functional name of the module. You will see this name in the config workspace
displayName The display name of the module
description A full description of the module
class The name of a module class
versionHandler The name of the class handling version changes
version The module version
properties Properties which can be used with the version handler
dependencies Dependencies on other modules - the module will install only after the specified modules
servlets Servlets which will be included in the servlet filter
repositories The repositories which must exist or will be created for this module

Properties

Properties in the module descriptor can be used to define values for install tasks. You can get the current module descriptor from the InstallContext:

installContext.getCurrentModuleDefinition().getProperty(PROPNAME);
The properties defined in the module descriptor will be included in the Magnolia system properties too, so you might want to use the SystemProperty class instead:
SystemProperty.getProperty(PROPNAME, "default");
Additional details will be described in a separate chapter.

Module version handling

The module mechanism facilitates smoother version changes. The idea is that an upgrade or update should be as easy as replacing a module JAR. Magnolia uses the version handler to determine which tasks should be executed. Upon each startup of Magnolia the version handler provides a list of deltas.

Delta

A Delta is a list of Tasks to be executed during a version change. The sample module's version handler provides three Deltas which can be referred to as an example.

Delta (from Version) Task
3.5
  • Remove menu item for sample templates
  • Add menu item for sample templates
  • Remove menu item for sample paragraphs
  • Add menu item for sample paragraphs
  • Remove menu item for sample dialogs
  • Add menu item for sample dialogs
  • Install the CSS configuration
  • Install the JS configuration
  • Install the paragraph configuration
3.5.4
  • Remove Kupu editor
3.6
  • Replace if exists user "bob" with "david"
  • Replace if exists user "joe" with "eve"
  • Replace if exists user "melinda" with "patrick"

More precisely, a Delta can store and apply an additional set of Conditions to be executed only when a version update or revision is deployed. The Tasks of a Delta will only be executed if all specified Conditions are met. We will examine Tasks and Conditions in more detail later in this chapter.

Abstract version handler classes

If you want to create your own version handler you will not have to start from scratch. There are some abstract classes for common cases which can be used. It is good practice to extend one these base classes and implement only the methods you need. There are two abstract version handler classes in the package info.magnolia.module which can be used to create a custom version handler.

Class Description
AbstractModuleVersionHandler Extend this and register your Deltas in the constructor using the register method. Add your own install tasks by overriding the getExtraInstallTasks() method. In most cases, modules won't need to override any other method.
DefaultModuleVersionHandler Extends the AbstractModuleVersionHandler and triggers the most common installation tasks (see table above):
  • register repositories, nodetypes and workspaces as stated in the module definition
  • bootstrap the module's mgnl-bootstrap files
  • bootstrap the module's mgnl-bootstrap-samples files
  • extract the module's mgnl-files files
  • register the module's servlets.

If you do not specify a version handler in the module descriptor, the DefaultModuleVersionHandler is used which performs some basic install tasks:

Task Description
SetupModuleRepositoriesTask This task bootstraps empty repositories defined in the module descriptor, grants them to the superuser and subscribes them so that activation can be used.
ModuleBootstrapTask This task bootstraps the necessary module repository content which is provided as multiple XML-export files under "/mgnl-bootstrap/moduleName".
SamplesBootstrapTask This task bootstraps the module's sample repository content which is provided as multiple XML-export files under "/mgnl-bootstrap-samples/moduleName".
ModuleFilesExtraction This task copies all files under "mgnl-files" which includes the module name as a directory to the web application folder, preserving the path.
RegisterModuleServletsTask This task registers the necessary servlets for this module

Task

A Task is a lightweight class with only minimal necessary code to augment configuration during module installation. The important method in the Task interface is:

void execute(InstallContext installContext) throws TaskExecutionException;
Tip

A good-citizen task should execute itself responsibly: it should know what to do in case of problems. For instance, fixable or irrelevant issues should usually just be logged and standard InstallContext methods should be used, allowing the developer/user to fix the logged issues at a later time. The task could also potentially perform backups of nodes when extensive modifications are performed so that the user can refer to a pre-alteration backup in case of problem. In the event of an unrecoverable issue, the Task could also automatically perform a TaskExecutionException, which will interrupt and cancel the module's installation, update and startup. If a TaskExecutionException must be thrown, keep in mind that the exception message will still be shown to the end user, so try to keep the exception messages simple and intuitive.

There is already a set of predefined and abstract Tasks available in the package info.magnolia.module.delta which can be used. Here are some of the most useful: AbstractTask, AbstractRepositoryTask, AbstractConditionalRepositoryTask, AllChildrenNodesOperation, AllModulesNodeOperation.

Also interesting are delegate Tasks:

ArrayDelegateTask, ConditionalDelegateTask, PropertyExistsDelegateTask, PropertyValueDelegateTask.

For the complete list of Tasks, please consult the javadoc.

It is customary for modules to expose some tasks that can be re-used by other modules when needed, such as RegisterNodeTypeTask. The API is designed so that it should be easy for you to write your own specific Task implementations.

Condition

Conditions are checked prior to the installation or update of a module. They check for system configuration which can't be automatically updated, like configuration, dependencies, etc. Modules register their Conditions like their Tasks, for each successive version. Only if all Conditions in Delta evaluate positively will the Tasks of the Delta be executed. The most important method in the Condition interface is:

boolean check(InstallContext installContext);

Dependencies

You can define runtime or install time dependencies (not build dependencies). If you define a dependency on a module, then this module will be installed and started before your module. A dependency can be optional which means that if an optional module is not present, installation will proceed, if the optional module is present, this module will be installed first. The dependencies could look like this:

<dependencies>
    <dependency>
      <name>core</name>
      <version>3.6.0/*</version>
    </dependency>
    <!--  in case cache module is present, 
    make sure we install after so we can add a bypass -->
    <dependency>
      <name>cache</name>
      <version>3.6.0/*</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
The syntax for a version is from version/to version where a version number consist of three parts: major version.minor version.patch level where the latter two parts are optional. For a strict version dependency just use one version string.

Taking * for the from version means "to version or lower"

Taking * for the to version means "from version or higher"

Some examples:

Example Description
3 Must have major version 3
3.6 Must have major version 3 and minor version 6
3.6.3 Must have major version 3 and minor version 6 and patch level 3
3/* Must have major version 3 or higher
3.6/* Must have major version 3 and minor version 6 or higher
3.6.3/* Must have major version 3 and minor version 6 and patch level 3 or higher
*/3 Must have major version 3 or lower
*/3.6 Must have major version 3 and minor version 6 or lower
*/3.6.3 Must have major version 3 and minor version 6 and patch level 3 or lower
3.5/3.6.2 Version not lower than 3.5 and not higher than 3.6.2

Servlets

Instead of defining servlets in web.xml, servlets can be defined in the module descriptor using the same values as in web.xml. The DMS module for example registers a servlet to deliver the documents:

  <servlets>
    <servlet>
      <name>DMSDownloadServlet</name>
      <class>info.magnolia.module.dms.DMSDownloadServlet</class>
      <comment>DMS download servlet</comment>
      <mappings>
        <mapping>/dms/*</mapping>
        <mapping>/dms-static/*</mapping>
      </mappings>
    </servlet>
  </servlets>
These servlets are actually registered through the RegisterModuleServletsTask at install time; this means that if the definition changes over time, the module developer should take care of updating the configuration by using a ModuleVersionHandler.

Servlet initialization parameters

You can specify initialization parameters for servlets in the module descriptor file. These parameters are the equivalent of servlet initialization parameters in a web.xml file. Use the following syntax in the descriptor:

<params>
  <param>
    <name>name</name>
    <value>value</value>
  </param>
</params>

Examples:

Repositories

Repositories and/or workspaces can be defined in the module descriptor. If necessary Magnolia initializes these workspaces before the installation starts. As an example look at the data module:
  <repositories>
    <repository>
      <name>magnolia</name>
      <workspaces>
        <workspace>data</workspace>
      </workspaces>
      <nodeTypeFile>/mgnl-nodetypes/magnolia-module-data-nodetypes.xml</nodeTypeFile>
    </repository>
  </repositories>
Under the hood, these repository workspaces are registered and initialized by the SetupModuleRepositoriesTask when the module is installed.