Module deployment

November 14, 2023

Modules are extensions to Jahia, which are packaged as JAR files and can be deployed on a server. A module can contain different kinds of resources: JSPs, definitions in CND files, CSS and images, resource bundles, XML or ZIP import files, rules definitions, libraries, Spring files etc. Modules are deployed by using the built-in module management screen in the server administration, the Provisioning API or the REST API (with supplied command line scripts).

Jahia does not support several versions of a module being deployed at the same time in production mode. After deploying a new version of a module, you need to undeploy the previous one. This is meant to ensure reliable OSGi wiring between Jahia modules. Please note that this restriction is not enforced in the product. However, on development environments, it may be useful to keep several versions deployed to be able to easily switch between them. Learn more about this

Module management UI

The module management UI contains an explicit checkbox for starting or not a module, uploaded via that UI, as well as a similar checkbox for the modules, downloaded from private app store.

For more information about the module management UI, see Managing modules.

Provisioning

Jahia 8.0.3 introduces the Provisioning API, and we encourage customers to use it for module management, as it is more modern than the Rest API.

The following commands can also be found in the Provisioning commands documentation:

Installing a module

This command installs a module, also called an OSGI bundle, by providing a PAX-url. These options are available:

  • target
    The cluster group name where the operation will be performed (unset to execute on all nodes), or local to perform operation on a node individually using standard non-clustered module deployment
  • autoStart
    Autostarts the bundle after installation (at the end of the script execution)
  • uninstallPreviousVersion
    Uninstalls all other versions (at the end of the script execution).
  • forceUpdate
    If true, updates the module if it is already installed. The default is false.
  • if
    Optional condition that must be met to perform the operation

Example:

- installBundle: "mvn:org.jahia.modules/article/3.0.0"
  autoStart: true
  uninstallPreviousVersion: true

or:

- installBundle: "file:/tmp/example-1.0.0.jar"

Multiple bundles can be installed with the same command and options:

- installBundle:
  - 'mvn:org.jahia.modules/forms-snippets-extension/3.0.0'
  - 'mvn:org.jahia.modules/forms-nocss-theme/2.0.0'
  - 'mvn:org.jahia.modules/font-awesome/6.0.0'
  - 'mvn:org.jahia.modules/forms-prefill/2.0.0'
  - 'mvn:org.jahia.modules/forms-core/3.2.0'  
  autoStart: true
  uninstallPreviousVersion: true

The autoStart option starts all listed bundles once they have all been installed. Then previous versions will be uninstalled.

Conditional installation

You can add a condition on install by adding the if option. 

- installBundle: 'mvn:org.jahia.modules/sdl-generator-tools/2.1.0'
  if: "'${jahia:operatingMode}' == 'development'"

Additional commands

As an alternate to autoStart: true, you can use installAndStartBundle:

- installAndStartBundle: "file:/tmp/example-1.0.0.jar"

The  installOrUpgradeBundle additional command is also available for upgrades. The behavior changes for new installs and upgrades:

  • If no version of this bundle is installed, it behaves like installAndStartBundle.
  • If another version of the bundle is installed, this installs the new version, uninstalls the previous ones (as with uninstallPreviousVersion), and restores the state of the previous version (started or stopped)
- installOrUpgradeBundle: "mvn:org.jahia.modules/article/3.0.0"

Adding a Maven repository

Add a Maven repository to allow modules to be installed from that repository. The repository will be available when using mvn:// URL.

- addMavenRepository: "https://devtools.jahia.com/nexus/content/groups/enterprise@id=jahia-enterprisee@snapshots"

Or if that repository requires authentication:

- addMavenRepository: "https://devtools.jahia.com/nexus/content/groups/enterprise@id=jahia-enterprise@snapshots"
  username: "USERNAME"
  password: "PASSWORD"

Enabling a module on a site

You can enable a module on a specific site. For example:

- enable: "news"
  site: "digitall"

Installing a package

All packages based on jahia-packages-parent from 8.0.3.0 have an associated provisioning script that is generated when building. You can install a package by just referencing its script. For example:

- include: "mvn:org.jahia.packages/forms-package/3.2.1/yaml/provisioning"

Uninstalling a bundle

You can uninstall a bundle using a key composed of the symbolic name and version (optional): <symbolic-name>[/<version>]. This additional option is available:

  • target
    The cluster group name where the operation is performed (unset to execute on all nodes), or local to perform operation on a node individually using standard non-clustered module deployment

Example:

- uninstallBundle: "article/3.0.0"

REST API and command line scripts

Jahia provides a REST API for module management, as well as corresponding command line scripts in the Jahia installation folder (in a default installation they are located in the <jahia-install-dir>/tools folder). Examples of usage of such scripts are listed below.

Note that all the scripts are available for Windows (.bat), Linux and MacOS (.sh) operating systems.
To perform these operations with a different user from root (which is the user by default), you can change the value of DX_USERNAME in the setupBundleApi.sh/.bat file with the selected username who must have the administration permission "Admin templates".

Installing a module

./installBundle.sh article-2.0.2.jar true

Installs the specified file as a module and starts it after the installation. if last parameter (true) is omitted, the module is just installed, but not started automatically.

Installing multiple modules

./installBundles.sh article-2.0.2.jar faq-2.0.2.jar --start

Installs the specified files as modules and starts them after the installation. if last parameter (--start) is omitted, the modules are just installed, but not started automatically.

Starting a module

./startBundle.sh org.jahia.modules/article/2.0.2

Starts the article module version 2.0.2. The org.jahia.modules/article/2.0.2 is a full module key in this case, which is composed like <groupId>/<artifactId>/<version> string. The start/stop/ uninstall commands can operate on a full module key as well as on a short one, like article/2.0.2 or event article, if the corresponding bundle can be resolved by that key unambiguously, for example if there is only one bundle with symbolic name article installed on your Jahia instance. The shorter form will be:

./startBundle.sh article

Stopping a module

./stopBundle.sh org.jahia.modules/article/2.0.2

Or in a shorter form:

./stopBundle.sh article

This command stops the target article module.

Uninstalling a module

./uninstallBundle.sh org.jahia.modules/article/2.0.2

And the shorter form:

./uninstallBundle.sh article

Uninstalls the target article module from your Jahia instance.

The start/stop/uninstall commands also take an optional second parameter to specify <target>, which is the group of cluster nodes targeted by the operation, or local to perform the operation on a cluster node individually using standard, non-clustered module deployment.

Get local bundle info

./getLocalBundleInfo.sh article/2.0.2

Get current local info about a single bundle.

./getLocalBundleInfo.sh article/2.0.2 jline/2.14.2

Get current local info about multiples bundles.

./getLocalBundleInfo.sh article/*

Gut current info about all versions of a bundle

./getLocalBundleInfo.sh org.jahia.modules/*/*

Get current info about all modules and their versions, having group ID org.jahia.modules

./getLocalBundleInfo.sh *

Get current info about all bundles

Get cluster wide bundle info

./getBundleInfo.sh article/2.0.2

Get current info about a single bundle.

./getBundleInfo.sh article/2.0.2 jline/2.14.2

Get current info about multiples bundles.

./getBundleInfo.sh article/*

Get current info about all versions of a bundle

./getBundleInfo.sh org.jahia.modules/*/*

Get current info about all modules and their versions, having group ID org.jahia.modules

./getBundleInfo.sh *

Get current info about all bundles

Refreshing a module

The following is available

./refreshBundle.sh org.jahia.modules/article/2.0.2

And the shorter form:

./refreshBundle.sh article/2.0.2

Refreshes the target article module from your Jahia instance.

Updating a module

The following is available

./updateBundle.sh org.jahia.modules/article/2.0.2

And the shorter form:

./updateBundle.sh article/2.0.2

Updates the target article module from your Jahia instance.

Deployment into the /modules folder

For development purposes, the deployment of modules can also be done by dropping them into the digital-factory-data/modules folder. This folder is “watched” for changes (new modules are dropped, existing modified or deleted) and actions are performed by Jahia to react to those changes. The folder supports module operations in “hot” (online, while Jahia is running) as well as in “cold” (offline, when Jahia is shut down) mode. If a new module is dropped into that folder, it is by default automatically started, as it is the default behavior when Jahia is running in development operating mode (“operatingMode” flag value in jahia.properties file). If Jahia was started in other operating modes (e.g. “production”), then such modules will  just be installed, without auto-starting. If needed, the behavior can be explicitly controlled by adding the following flag into jahia.properties (or your own jahia.custom.properties) file:

jahia.modules.fileinstall.bundles.new.start=true

Supported values are true or false.

The usage of the /modules folder is not recommended on production environments. We strongly advise using the Jahia provisioning and/or the module management API (described above), as it will increase the module deployment stability over time.

Cluster deployment

Jahia includes a built-in clustered module management support. All module operations, performed via Module management UI (in Server Settings) or via REST API/command-line scripts on any node and also including module deployments/undeployments via the /modules folder, are automatically replayed on other nodes in the cluster, so the state of bundles should be consistent across all nodes in the cluster. When a cluster node is joining the cluster it “pulls” the bundle state from the cluster and “applies” it locally. So, the module operations, listed in Module deployment, are cluster-wide (for example, a module deployed on any node of the cluster will be automatically deployed on the other nodes).

Be aware that direct bundle operations performed via Java code (on BundleContext or Bundle instances) any custom scripts, OSGi Web Console ,or SSH Console (except clustered commands under cluster:* group), are only effective locally, until the next cluster-wide operation is performed which synchronizes the cluster state in any case. Note that when a module is deployed in cluster it becomes “available” only after its deployment has been successfully completed by a Jahia processing node. For information and troubleshooting you could refer to a SSH console and “cluster:*” group of commands.

The following command:

cluster:bundle-list default

shows the clustered state of bundles in the default group – the global cluster group, which includes all nodes. This command has a shortcut alias:

clb

which does the same. Here is the sample snapshot of the output of this command:

In case of bundle state desynchronization in cluster, for example due to a cluster split (network partition) or other issues, it could be required to force synchronization of cluster state for bundles:

cluster:sync –bundle

or for all resources (bundles, config, features):

cluster:sync

Module version update with limited downtime

Starting a new version of a module can take some time (from several seconds to few minutes), depending on its complexity, which will make the module unavailable during this operation, as well as the modules depending on it. This can be even more problematic when it involves a template set module: the consequence will be the unavailability of the sites using this template set during the start operation. The steps explaining how to perform a module deployment in a cluster with limited downtime are described in the "Module version update with limited downtime" procedure.

Module undeployment

You can undeploy your modules using the Provisioning API or the REST API (or corresponding uninstallBundle.sh command-line script). Alternatively, you can undeploy the modules from the Administration>Server>System Components>Modules. The advantage of doing so using the UI approach is that Jahia will inform you of any modules that might depend on the one you're trying to undeploy and will first ask you to disable the module from all the sites that might be using it. Module undeployment in both cases is a cluster-wide operation as described in Cluster deployment.

Removing modules directly from the /modules folder is not a supported operation, even in development mode.

Notes about module dependencies

We rely on OSGI capability mechanism to define the dependencies between modules.
An OSGI bundle, so a Jahia module, can be started if all its dependencies (OSGI bundles that provides the required capabilities) are resolved.

The import and definition registering is done at resolve state.

At startup, a Jahia module if necessary:

  • Stops any previous version of the module
  • Registers the bundle into TemplatePackageRegistry (where it computes the dependencies using TemplatePackageRegistry.computeDependencies)
  • Fires deploy event to Jahia (mostly to flush caches)
  • Registers script resolvers
  • Registers the Drools rules
  • Registers HTTP resources
  • Starts spring context

We provide several mechanisms to make the module start whatever the order the modules are deployed.

  1. We compute all the dependencies each time a module, or one of its dependencies, is started
  2. If a dependency is not fulfilled, or not available at startup, the module startup is postponed. At the end of the process, all the modules should be started correctly.
  3. The jahia-depends defines the required modules to be resolved. It also defines, in case of multiple modules deployed at once, the order to start them. Copying several modules at once in the /modules directory work as each module deployed one by one, so we cannot compute the order of deployment, this can lead to inconsistencies while the modules are starting, but should be solved automatically at the end.

Deployment on sites

Once the JAR file has been deployed, modules become available. They can then be deployed to Web projects via module management screen in Server Settings or via Studio. If a new version of the module is uploaded on the server, it will be automatically deployed on all sites that are currently using it. All updates will be immediately available in the site.