How to create a custom module?
Creating a module
By using maven you can easily create a module skeleton by using our archetype. A initial module is build in the directory you called the command and it will contain:
- maven pom.xml
- module class
- module descriptor
- bootstrap resources directory
mvn archetype:create -DarchetypeGroupId=info.magnolia \\
-DarchetypeArtifactId=maven-archetype-magnolia-module \\
-DarchetypeVersion=1.0.0-SNAPSHOT \\
-DgroupId=com.foo.bar \\
-DartifactId=my-module \\
-DremoteRepositories=http://svn.magnolia.info/maven/snapshotsEverything in src/main/java and src/main/resources will be finally in the by maven generated module jar file. The file src/main/resources/META-INF/magnolia/mymodule.xml is the module descriptor.
All resources found in the directory mgnl-bootstrap/mymodule will be bootstrapped during the registration process.
The files in mgnl-files are extracted to the webapp's filesystem. Here you place the jsps or files enduser like to change.
The files in mgnl-resources will stay in the jar and will be streamed directly. You can access these files using the URL prefix .resources. In this example it would be /.resource/mymodule/sample.css
Module descriptor
The module has an xml descriptor found in META-INF/magnolia/modulename.xml. The descriptor defines the name, class to load, dependencies, servlets and repositories to register.
For more details see the module.dtd in the info.magnolia.cms.module package.
Note: The descriptor is read using the commons betwixt project.
<module>
<name>workflow</name>
<displayName>Workflow</displayName>
<description>Workflow using OpenWFE</description>
<class>info.magnolia.module.owfe.Engine</class>
<version>1.0</version>
<dependencies>
<dependency>
<name>adminInterface</name>
<version>3.0</version>
</dependency>
</dependencies>
<servlets>
<servlet>
<class>info.magnolia.module.owfe.servlets.FlowDefServlet</class>
<mappings>
<mapping>/FlowDef</mapping>
</mappings>
<name>FlowDef</name>
<comment>Servlet to see flow definition.</comment>
<params>
<!-- <param></param> -->
</params>
</servlet>
</servlets>
</module>Configuration
Each module has a node in the config repository under the modules node. Each module has a subnode called config under which the module specific configuration is done.
A good example is a mailing list module needing properties like servername, port, ...
Registration
The ModuleRegistration calls the Modules method register(). The current ModuleDefinition read from the xml descriptor is passed to this method as well the node created for this module. In addition a register state constant is passed to define the state of this registration (new installation, new version, none). Where none means the module is already installed.
The method is always called (even if already registered). This gives the module a chance to register in multiple steps, to update its data ...
/**
* No registration needed. Same version is already registered
*/
int REGISTER_STATE_NONE = 0;
/**
* First installation. Node didn't exist in the repository
*/
int REGISTER_STATE_INSTALLATION = 1;
/**
* New version of a already registered module
*/
int REGISTER_STATE_NEW_VERSION = 2;
A module can request a restart of the webapp after the registration. It will set the restartNeeded flag. If this flag is set the module is not initialized and a restart page is showed to the user if he tries to access magnolia.
Before a registration is started all the dependencies are checked.
Default Implementation
The abstract class AbstractModule processes this default registration
- create the modules node with the default properties (name, class, ...)
- bootstrap all the files under
mgnl-bootstrap/modulename/*.xml. The naming of the bootstrap files is following the shema:repository.dot.separated.path.to.node.xml - register servlets defined in the descriptor
- register repositories defined in the descriptor
- extract the files in the following folders to the filesystem:
mgnl-files/*/modulename
If the module needs additional tasks to do, it can overwrite the onRegistration() method. If so overwrite the onUnRegister() to.
Initialization
The Modules method init() is called after the registration of all the modules. Here you will instantiate module specifig objects, add objects to the managers (like dialogs, paragraphs, ...)
Default Implementation
Default Implementation of AbstractAdminModule
Some modules needs to register dialogs, paragraphs, tress,… It is best practice to extend the AbstractAdminModule of the admin interface package class, which does the following default initialization
- register the virtual URI mappings in the modules subnode virtualURIMapping
- register the dialogs in the modules subnode dialogs
- register the controls in the modules subnode controls
- register the trees in the modules subnode trees
- register the paragraphs in the modules subnode paragraphs
- register the templates in the modules subnode templates
- register the commands in the modules subnode commands
The the module can overwrite the onInit() method to execute additional tasks.
Unregister
The Modules unregister method has to undo all the tasks done during the registration process. All the nodes created through the bootstrap are deleted as well the files extracted. After the call of the unregister method the jar is moved to libs/uninstalled to avoid a reinstall by a system restart.
AbstractModule has not yet a default implementation, but will in the future
Development
ModuleUtil
The most of the tasks in the default implementation are done by using the ModuleUtil class of the module package. If you want to extract files, bootstrap content, register servlets, … it's wise to check the existence of a method in the ModuleUtil.
Resource reloading
You can set the magnolia.develop property to true in the magnolia.properties file. All the resources are read newly for each request afterward.
JSP
The JSP in mgnl-files folder are not extracted again after a change. This means that the originally extracted file still lays in the templates folder for example. But you can easely trigger the extraction again by using the Deployment found in the Tools menu.