Magnolia 4.5 reached end of life on June 30, 2016. This branch is no longer supported, see End-of-life policy.
Magnolia has a modular architecture where each module performs a particular task or is used to package content and functionality.
Magnolia provides standard module configuration items such as controls, template types (pages, areas, components), and dialogs. Customized implementations of configuration items need to be configured for the relevant module. The config node uses Node2Bean to populate all registered module classes as Java Beans with the content of the config node. Because Magnolia monitors configured items, any changes in the configuration of registered items will immediately be active.
Function of Configuration Item
Details or Example
Module-specific configuration which will be available via the module class (see below).
Config contains parameters and data for your module.
Template definition. Templates can be pages or components. 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.
Define a configured dialog.
Dialog to edit the content of sample text & image of component.
Define your own dialog control.
Allows editing of the control.
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.
Define commands to use with the Magnolia command management.
Activates the command.
Define a page to be used in AdminCentral.
For instance, JCR Queries in the Tools menu.
Makes the rendering depend on a URI pattern.
Default URI: defines which page should be rendered if no path is specified.
Defines a new template type and determines the renderer to use.
Magnolia ships with JSP and FreeMarker template renderers. You can also integrate logic before rendering a page, area or component by using a custom renderer or injecting your implementation of the standard renderers. It is possible to create a custom renderer for another templating language, e.g. Velocity.
The functional name of the module. You will see this name in the config workspace
The display name of the module.
Full description of the module.
The name of a module class
The name of the class handling version changes.
The module version.
Properties that can be used with the version handler.
Dependencies on other modules - the module will install only after the specified modules.
Servlets which will be included in the servlet filter
The repositories which must exist or will be created for this module.
Properties in the module descriptor can be used to define values for install tasks. You can get the current module descriptor from the InstallContext:
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:
Additional details will be described in a separate chapter.
Magnolia uses dependency injection. This means that object dependencies are injected automatically at the time the object is instantiated. The benefit of injecting dependencies in this way is that you can change the implementation of the depended object without having to change the way dependencies are retrieved. A further benefit is testability.
This type of dependency is different from module dependencies. It is a code/object level dependency that defines the relationship between objects, not a dependency between modules.
The term dependency injection (DI) is often used together with inversion of control (IoC). IoC is the principle and DI is the implementation. The concepts are related but at Magnolia we talk only about DI. To learn how IoC was implemented at Magnolia, see Concept IoC in Magnolia.
Components in Magnolia are defined in the module descriptor XML file. Modules can define components of the same type. A definition in a module takes precedence over definitions in modules that it depends on. This allows modules to override and customize components in other modules.
For example, suppose you want to implement a
MailSender component. If another Magnolia module already implements such a component, you can override it by declaring a module dependency on the module that provides the original MailSender component and by making sure that your component definition uses the same type.
The module descriptor can specify components for different containers. This is done using the
id element. You will rarely use a container other than
This example module descriptor defines a component of type
GeoService which is an interface. The actual implementation is
To retrieve a component, declare a dependency on it. Here is an example declaring a dependency to a component that needs to be injected (
GeoService). The example uses the constructor injection type. Field and setter injection are also supported.
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 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)
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
Conditions in more detail later in this chapter.
To create your own version handler you do not have to start from scratch. There are some abstract classes for common cases which can be used. Good practice is 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.
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.
Extends the AbstractModuleVersionHandler and triggers the most common installation tasks (see table above):
If you do not specify a version handler in the module descriptor, the DefaultModuleVersionHandler is used which performs some basic install tasks:
This task bootstraps empty repositories defined in the module descriptor, grants them to the superuser and subscribes them so that activation can be used.
This task bootstraps the necessary module repository content which is provided as multiple XML-export files under "/mgnl-bootstrap/moduleName".
This task bootstraps the module's sample repository content which is provided as multiple XML-export files under "/mgnl-bootstrap-samples/moduleName".
This task copies all files under "mgnl-files" which includes the module name as a directory to the web application folder, preserving the path.
This task registers the necessary servlets for this module.
Task is a lightweight class with the minimal necessary code to augment configuration during module installation. The important method in the
Task interface is:
Taskshould execute responsibly and respond to issues appropriately.
Taskshould be in place to perform backups of nodes when extensive modifications are performed, meaning that a user can refer to a pre-alteration copy.
Taskshould automatically perform a
TaskExecutionExceptionto interrupt and cancel the module installation, update and startup. If a
TaskExecutionExceptionis thrown, the exception message still shows to the end user.
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:
Also interesting are delegate
For the complete list of
Tasks, please consult the
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.
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:
The node builder API: package-summary , is commonly used in update tasks.
Here's a snippet from STKModuleVersionHandler that demonstrates its use.
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:
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".
Must have major version 3.
Must have major version 3 and minor version 6.
Must have major version 3 and minor version 6 and patch level 3.
Must have major version 3 or higher.
Must have major version 3 and minor version 6 or higher.
Must have major version 3 and minor version 6 and patch level 3 or higher.
Must have major version 3 or lower.
Must have major version 3 and minor version 6 or lower.
Must have major version 3 and minor version 6 and patch level 3 or lower.
Version not lower than 3.5 and not higher than 3.6.2.
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:
These servlets are actually registered through the
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
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:
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:
Under the hood, these repository workspaces are registered and initialized by the SetupModuleRepositoriesTask when the module is installed.