Notice: The documentation below only applies to versions prior to dotCMS's adoption of Java 11 — that is, versions prior to dotCMS 21.08. Current versions of dotCMS do not allow core system classes to be overridden. However, new user-defined classes with unique names may still be added via plugin.
This bundle plugin is an example of how to override dotCMS classes with our bundle plugin.
How to create a bundle plugin to override dotCMS classes
Let’s review the file organization on the Override (com.dotcms.override) example:
META-INF/MANIFEST.MF: The manifest file is very important for the deployment, it lists the Bundle Name, Version and Packages.
In this MANIFEST you must specify (see template plugin):
- Bundle-Name: The name of your bundle
- Bundle-SymbolicName: A short an unique name for the bundle
- Bundle-Activator: Package and name of your Activator class (example: com.dotmarketing.osgi.override.Activator)
- Override-Classes: Comma separated list of classes.
List of classes we are trying to override, in order to override any dotCMS class is mandatory to add it to this list because dotCMS implementation of the class will be already loaded by the dotCMS class loader so if we don’t explicit specify the classes to override the class loader wont try to load them. - Import-Package: This is a comma separated list of package's name. List the packages that you are using inside the bundle plugin and that are exported by dotCMS.
$ more META-INF/MANIFEST.MF
Manifest-Version: 1.0
Bundle-Name: Example Override class
Bundle-Description: Static.Manifest
Bundle-ManifestVersion: 2
Bundle-SymbolicName: overrideClassesOSGI
Bundle-Version: 2.5.1
Bundle-Activator: com.dotmarketing.osgi.override.Activator
Override-Classes: com.dotmarketing.portlets.folders.model.Folder
DynamicImport-Package: *
Import-Package: org.osgi.framework,
com.dotmarketing.osgi
Beware (!)
In order to work inside the Apache Felix OSGI runtime, the import and export directive must be bidirectional.
dotCMS must declare the set of packages that will be available to the OSGI plugins by changing the file: dotCMS/WEB-INF/felix/osgi-extra.conf.
This is possible also using the dotCMS UI (System -> Dynamic Plugins -> Exported Packages).
Only after that exported packages are defined in this list, a plugin can Import the packages to use them inside the OSGI blundle.
Source
Under the src folder you will find all the Java classes needed to create a new class to override an existing class in dotCMS:
$ pwd
/dotCMS/docs/examples/osgi/com.dotcms.override
$ ls src/com/dotmarketing/
osgi/ portlets/
$ ls src/com/dotmarketing/osgi/override/
src/com/dotmarketing/osgi/override/Activator.java
$ ls src/com/dotmarketing/portlets/folders/model
src/com/dotmarketing/portlets/folders/model/Folder.java
com.dotmarketing.portlets.folders.model.Folder
Copy of the original com.dotmarketing.portlets.folders.model.Folder that lives inside dotCMS but with small changes (Just logging code) inside the getPath() method in order to demonstrate we can override a dotCMS class with our implementation.
$ tail -f /dotCMS_home/dotserver_/tomcat-X.x_/logs/catalina.out
+++++++++++++++++++++++++++++++++++++++++++++++ Modified Code, this class was redefined. +++++++++++++++++++++++++++++++++++++++++++++++
Activator
This bundle activator extends from com.dotmarketing.osgi.GenericBundleActivator and implements BundleActivator.start().
* PLEASE note the “publishBundleServices( context )” call, this call is MANDATORY (!) as it will allow us to share resources between the bundle and the host container (dotcms).
Limitations (!)
There are limitations on the hot deploy functionality for the OSGI Override plugin, there are some rules for the code you can modify on the redefined classes in order to see those changes when you upload the plugin.
In order to support the overriding of a class inside ours OSGI plugins we use the java hot swapping, it allows to redefine classes, unfortunately, this redefinition is limited only to changing method bodies:
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.
As long as you don’t add, remove or change methods (ONLY the methods bodies) for your redefined classes you will have an OSGI plugin that will reflect you changes when a deploy is done.
* PLEASE note the “publishBundleServices( context )” call, this call is MANDATORY (!) as it will allow us to share resources between the bundle and the host container (dotCMS).