Convert a module into OSGi

November 11, 2022

Digital Experience Manager’s automatic module transformation

In order to ease the migration from a non-OSGi Digital Experience Manager module to a fully OSGi module, Digital Experience Manager is capable of dynamically transforming a Digital Experience Manager WAR module into an OSGi module. It will attempt to resolve dependencies by scanning the contents of the module to determine which other modules or libraries are needed, and in general, on simple modules, this should work seamlessly. However, if the modules are doing more advanced integrations with Digital Experience Manager, the automatic transformation might not be able to pick up the most advanced features and converting the module to an OSGi version manually might be required (for example if custom rule consequences were implemented, those will require some Java code change as the API has changed in Digital Experience Manager 7). Also, using a native OSGi bundle packaging will open the possibility to expose services and integrate with other OSGi frameworks that might be useful to module developers, so in general it is recommended to migrate manually at some point.

All new modules must however be developed as OSGi bundles, as the transformation system is mostly a migration tool, and might be deprecated in future versions of Digital Experience Manager.

Controlling automatically generated package imports and exports

In the file felix-framework.properties, the following settings allow you to control the generation of package imports and export for Digital Experience Manager’s module transformation engine:

  • org.jahia.bundles.url.jahiawar.importedPackages: is a list of package imports that will be added to the automatically generated list of package imports. The format of the list is the following:
MODULE_ROOT_FOLDER=PACKAGE_NAME1,
MODULE_ROOT_FOLDER=PACKAGE_NAME2

Where MODULE_ROOT_FOLDER is either the module’s root folder or "*" to indicate that the package import applies to all modules.

  • org.jahia.bundles.url.jahiawar.excludedImportPackages: uses the same format of entries but controls the exclusion of automatically generated package imports
  • org.jahia.bundles.url.jahiawar.excludedExcludePackages: uses the same format of entries but controls the exclusion of automatically generated package exports

Source code changes

Using the Jahia Maven Plugin

The Jahia Maven Plugin has a new goal to help with the conversion to OSGi : jahia:convert-to-osgi . This goal is designed to be used on a WAR packaging Digital Experience Manager module and will perform some of the project transformation described here below, notably:

  • change the module’s packaging
  • move the directories
  • remove the no longer needed WEB-INF/web.xml file
  • parse the project source code and list the required modifications for updating the project (there is even a command line parameter to attempt to perform the source code modifications automatically)

Using this goal does not mean that you won’t have to change anything in your project once it has been executed. Please review the following sections to see what changes you might have to perform manually to fully migrate your module to an OSGi package.

Here is the procedure to use the jahia:convert-to-osgi goal:

1. If you’re using the jahia-modules artifact as a parent project, you need to change your Maven POM from:

<parent>
    <artifactId>jahia-modules</artifactId>
    <groupId>org.jahia.modules</groupId>
    <version>6.6.0.0</version>
</parent>

to

<parent>
    <artifactId>jahia-modules</artifactId>
    <groupId>org.jahia.modules</groupId>
    <version>7.0.0.0</version>
</parent>

2. You can now launch the goal using:

mvn jahia:convert-to-osgi

The goal will update your project but also scan the source code for any potential issues that must be resolved before it’s usable on Digital Experience Manager 7.

Manually upgrading the source code

Changing the Maven POM

The modifications to your Maven project are quite straightforward. Basically you need to:

  1. If you’re using the jahia-modules parent project, you need to update the version from 6.6.0.0 to 7.0.0.0
  2. Remove any old repository such as:
    <repositories>
        <repository>
            <id>jahiaRepository</id>
            <name>Jahia's Maven Repository</name>
            <url>http://maven.jahia.org/maven2</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>jahiaRepository</id>
            <name>Jahia's Maven Repository</name>
            <url>http://maven.jahia.org/maven2</url>
        </pluginRepository>
    </pluginRepositories>

    and replace them with the following:

    <repositories>
        <repository>
            <id>jahia-public</id>
            <name>Jahia Public Repository</name>
            <url>https://devtools.jahia.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
  3. Change the <packaging> from war to bundle
  4. Remove the Maven WAR plugin configuration
  5. Setup the Jahia Maven Plugin with either a default configuration if you inheriting from Jahia’s modules parent project (this is the default behavior of the jahia:convert-to-osgi goal) or with your own custom configuration (see section "6.3 From scratch" for more information on how to do this)
  6. Setup the Felix Maven Bundle plugin to re-use the output of the Jahia Maven plugin and adjust any parameter (again if you used the jahia:convert-to-osgi goal this will be inherited from the parent project).

If you need to setup custom configurations, please refer to section 6.3 From scratch for more information on the configurations and the settings.

Moving directories

As there is no more web application packaging, the contents of the src/main/webapp directory must be moved into the src/main/resources directory. This is the only main structural change that is required on the module’s structure apart from the Maven POM modifications.

Rules

Most rules should be directly compatible. If they aren’t, the jahia:convert-to-osgi goal will list the eventual problems and you should then perform the indicated modifications.

Hibernate

If your module requires a Hibernate session and was previously using the Digital Experience Manager default session Factory, it will have to be modified to use a new "moduleSessionFactory". Here is an example from the Digital Experience Manager remote publication module. Before OSGi migration it looked like this:

<bean id="RemotePublicationLogService" class="org.jahia.modules.remotepublish.LogService">
    <property name="sessionFactoryBean" ref="sessionFactory"/>
    <property name="journalEntriesReadChunkSize"
              value="${jahia.remotePublicationService.journalEntriesReadChunkSize:100}"/>
    <property name="resetObjectOutputStreamAfterEachBytes"
              value="${jahia.remotePublicationService.resetObjectOutputStreamAfterEachBytes:20971520}"/>
</bean>

After the modification, the file looks like this:

<bean id="RemotePublicationLogService" class="org.jahia.modules.remotepublish.LogService">
    <property name="sessionFactoryBean" ref="moduleSessionFactory"/>
    <property name="journalEntriesReadChunkSize"
              value="${jahia.remotePublicationService.journalEntriesReadChunkSize:100}"/>
    <property name="resetObjectOutputStreamAfterEachBytes"
              value="${jahia.remotePublicationService.resetObjectOutputStreamAfterEachBytes:20971520}"/>
</bean>

As you can see this change is relatively trivial and easy to do.

Workflow

As in Digital Experience Manager 7 the workflow back-end was upgraded from jBPM 4 to jBPM 6, the workflow definition files must be modified to use the BPMN 2.0 specification. Tools such as the Eclipse jBPM plugin (https://www.jboss.org/jbpm/components/eclipse-plugin.html) or the jBPM Designer (https://www.jboss.org/jbpm/components/designer) can be used to graphically rebuild the workflow definition files.

Workflow custom tasks will also need minor modifications since the API has changed, but usually these changes can be done quite quickly.

Tag libraries

If you module used or included tag libraries, you will have to modify their usage the following way:

  • If it used an external tag library, check if there is an OSGi bundle version of the tag library. If there is you’re in luck you can then simply add a dependency to it and deploy it as a separate bundle. If not, you’ll have to use one of the solutions proposed in "12 Using libraries in an OSGi module" to use the tag library.
  • If you were providing your own library of tags and they were packaged inside a module that also offers other services (views, etc.), it is highly recommended to build a separate module (or simply an OSGi bundle, that way you could even re-use it in other environments) just for the tag library. Then in your modules you can easily add the tag library as a dependency. It is not recommended to keep the "one module for everything" philosophy for modules including tag libraries (although it should work)