Plugin Extensions

DataNucleus is an extensible persistence tool. The DataNucleus Core persistence engine allows the user to plug in many user extensions which will contribute to augment the numerous persistence aspects faced by the Object/Datastore mapping. Plugins are loaded by a plugin manager which uses a registry mechanism, inspecting jars in the CLASSPATH.

These plugins are defined in OSGi format. This format relies on there being a set of extension-points where DataNucleus can be extended, and then adding extensions for each of these points. The format means that with very little effort any user can provide their own DataNucleus plugins and have them available very quickly. In short, the three steps necessary for creating a DataNucleus plugin are

  1. Review the DataNucleus interface 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 below).
  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: org.datanucleus.myplugin
Bundle-Version: 1.0.0
Bundle-Vendor: My Company

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 DataNucleus Forum


Plugins : 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.

Standard Java runtimes and J2EE containers 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 closing, PM closing or in another form depending in what the extension is used for.


Plugins : 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 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.


Plug-ins : Extension Points and Extensions

DataNucleus has mechanism that allows extending its persistence engine while not coupling the DataNucleus engine to the extensions. This mechanism is known as "Extension Points", which are well defined interfaces that allows the extension of certain aspects of DataNucleus in a dynamic and consistent model. The "Extensions" are the implementation of Extension Points that are registered in a PluginRegistry and used by DataNucleus Core or other DataNucleus Plug-ins. 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 it's 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.

Plugin Properties

Plugins can make use of existing persistence properties defined by "core" etc. They can also add on their own persistence properties. They define these in the plugin.xml. Let's take an example

    <!-- PERSISTENCE PROPERTIES -->
    <extension point="org.datanucleus.persistence_properties">
        <persistence-property name="datanucleus.rdbms.query.fetchDirection" value="forward"
            validator="org.datanucleus.store.rdbms.RDBMSPropertyValidator"/>
    </extension>

So here we have a property defined in the "store.rdbms" plugin which defines a persistence property org.datanucleus.rdbms.query.fetchDirection with a default value of forward and with values validated by the class org.datanucleus.store.rdbms.RDBMSPropertyValidator. This means that when we instantiate a PMF/EMF we automatically get that property defined with value "forward", and if we provide it ourselves we override this default. We do the same with any properties we want in our own plugins.

In order to avoid conflicts between different property names that can be set in the PMF and to have a consistent naming schema for properties, the following recommendations should be applied.

Naming the persistence property name should be prefixed by the plug-in id. Example:

Plugin: org.datanucleus.myplugin1
Property: myprop1

The persistence property should look like datanucleus.myplugin1.myprop1.

If an extension point defines a new persistence configuration, the property name should be prefixed by the extension-point id. Example:

Extension-Point id: org.datanucleus.myplugin2.myextensionpoint2
Property: myprop2

The persistence property should look like datanucleus.myplugin2.myextensionpoint2.myprop2.

Another form of persistence configuration could happen if multiple Extension-Points uses the same information. In this case an abstraction of the plug-in id and extension point id could be used, as the following example. However, make sure to use this naming schema only when absolutelly necessary.

Extension-Point id: org.datanucleus.myplugin3.myextensionpoint3
Extension-Point id: org.datanucleus.yourplugin3.yourextensionpoint4
Extension-Point id: org.datanucleus.theirplugin4.theirextensionpoint5
Property: myprop345

The persistence property should look like datanucleus.somepluginXXXX.someextensionpointYYYY.myprop345. Alternativelly, the PMF property could also look like datanucleus.myplugin3.myextensionpoint3.myprop345


Integrating with 3rd party products

It's a goal of the DataNucleus project to seamless integrate to all major 3rd party products used by the DataNucleus community. In addition to the plugins above it also provides plugins for the Eclipse IDE. All plugins can be downloaded here.