DataNucleus Extensions Guide

DataNucleus products are built using a plugin mechanism, allowing plugins to operate together. This plugin mechanism is useful also from a user viewpoint in that you, the user, could provide plugins that use these plugin points and extend the capabilities of DataNucleus. Plugins are loaded by a plugin manager when DataNucleus is initialised at runtime, and this plugin manager uses a registry mechanism, inspecting jars in the CLASSPATH. The three steps necessary for creating a DataNucleus plugin are

  1. Review the DataNucleus PluginPoint that you will need to implement to generate the plugin, and implement it.
  2. Create a file plugin.xml at the top level of your JAR defining the plugin details (see the actual PluginPoint docs).
  3. Update the META-INF/MANIFEST.MF file contained in the jar so that it includes necessary information for OSGi.

A minimum META-INF/MANIFEST.MF for a plugin jar should look like this

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: myplugin
Bundle-SymbolicName: mydomain.myplugin
Bundle-Version: 1.0.0
Bundle-Vendor: My Company</source>

Each plugin extension has attributes. If you want to override an extension that is included in DataNucleus itself then you need to specify the priority attribute, setting it to an integer (the default plugin has priority=0, so set to higher than this to override it). If you write a DataNucleus plugin and you either want it to be included in the DataNucleus distribution, or want it to be listed here then please contact us via the Forum

The current plugin points are :-

Plugins in a Non-managed environment

Non-managed environment is a runtime environment where DataNucleus runs and plug-ins are not managed by a container. In this environment the plug-in discovery and lifecycle is managed by DataNucleus.

There is a 1 to N instance relationship from DataNucleus to a plug-in per PMF. More exactly, if only one PMF exists, there is only one Plug-in instance for a Connection Pool Plug-in, and if N PMF exist, there are N Plug-in instances for a Connection Pool Plug-in.

JavaSE and JavaEE runtimes are considered non-managed environments. In non managed environments there is no lifecycle itself of plug-ins. Extensions implemented by plug-ins are instantiated on demand and terminated on PMF/EMF closing, PM/EM closing or in another form depending in what the extension is used for.

Plugins in a Managed environment

Managed environment is a runtime environment where DataNucleus plug-ins are managed by a container. The discovery, registry and lifecycle of plug-ins are controlled by the container. There is no plug-in instance relationship from DataNucleus to a plug-in regarding PMF instances. In managed environments, there is only one plug-in instance for one or N PMFs. Again, this is managed by the container.

DataNucleus supports OSGi containers as managed environment. In OSGi managed environments plug-in lifecycle is determined by the OSGi specification. Once activated, a plug-in is only stopped when the OSGi container finishes its execution, or the plug-in is stopped by an OSGi command.

Extensions and Plugins

A plugin owns an Extension. The behaviour is defined below :-

  • Lifecycle : Each extension is created by a segment of code during the runtime execution, and destroyed/released whenever they are no longer needed. This has no influence with the plug-in lifecycle.
  • Manageability : In non managed environments, the plug-ins are managed by DataNucleus and maintained with a composition relation to the PMF instance. This allows a plug-in instance per PMF. If multiple PMFs are created multiple extensions for an extension point are instantiated. In managed environments, more precisely in OSGi containers, the plug-ins are managed by the OSGi framework. Each plug-in will mostly be a singleton inside the OSGi container.
  • Registration : In non managed environments all plugins are registered using an instance of JDOClassLoaderResolver (so using the current ClassLoader of the PMF and the current thread). This means that the /plugin.xml and /META-INF/MANIFEST.MF files must be accessible to the classloader. In managed environment this is handled by the container.
  • ClassLoading : The classloading in non managed environments is usually made of one single ClassLoader, while in managed environments each plug-in has its own ClassLoader.
  • Configuration : Some Extensions needs to retrieve a configuration that was set in the PMF. This means that Plug-ins should not hold singleton / static configurations if they want to serve to multiple PMFs at the same time.
  • Constructors/Methods : In order of having consistent and avoid changes to extension-point interfaces, the Extension Constructors or Methods (either one) should have receive a PMFContext instance as argument. If by the time the Extension Point is designed clearly there is usage for a PMFContext, then the Extension-Point does not need to take the PMFContext as argument, but keep in mind that a 3rd Extension may need one due to different reasons.
  • Instantiation : Inside the DataNucleus Core, regardless if the runtime is OSGi managed or non managed, extension instances are created per PMF. DataNucleus Extensions should always be created through a PluginManager, regardless if the managed environment would allow you to instantiate using their own interfaces. This allows DataNucleus and its Plug-ins to run in non managed environments.

MANIFEST.MF : Plugin Version

Each DataNucleus bundle uses a version schema that has the following grammar (OSGi 3.0 §3.2.4): major.minor.micro.qualifier Major, Minor and Macro are numeric values, and qualifier is a alphanumeric.

Each bundle has the version value set in the /META-INF/MANIFEST.MF file, Bundle-Version entry.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: DataNucleus Enhancer
Bundle-SymbolicName: org.datanucleus.enhancer;singleton:=true
Bundle-Vendor: DataNucleus
Bundle-Version: 1.2.0.b2

The most common version compatibility policies are (OSGI 3.0 §3.6.2): * major - An incompatible update * minor - A backward compatible update * micro - A change that does not affect the interface: for example, a bug fix

MANIFEST.MF : Dependencies on other bundles

When your bundle depends on another bundle, you must declare it in the /META-INF/MANIFEST.MF file, via the Require-Bundle entry.

For example, the RDBMS plugin (org.datanucleus.store.rdbms) plug-in depends on the core (org.datanucleus) plug-in.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: DataNucleus RDBMS
Bundle-SymbolicName: org.datanucleus.store.rdbms;singleton:=true
Bundle-Vendor: DataNucleus
Bundle-Version: 1.2.0.b2
Bundle-Localization: plugin
Require-Bundle: org.datanucleus

See more on the OSGi 3.0 specification §3.13.1.

If a bundle depends on a specific version of a bundle, you must declare it in the Require-Bundle entry, bundle-version parameter. For example

Require-Bundle: org.datanucleus;bundle-version=(1.2.0.b2, 2.0)

See more on the OSGi 3.0 specification §3.2.5 and §3.13.1 chapters.

MANIFEST.MF : Generation

All recent DataNucleus releases (v3.2 onwards) use the Maven bundle plugin to auto-generate the MANIFEST.MF file. This means that the version in the pom.xml is taken for the bundle version, and the dependencies are auto-generated from imports etc. We recommend that you use this same method for your own plugins.