
JPOX is an extensible persistence tool. The JPOX 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 JPOX 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 JPOX plugins and have them
available very quickly. In short, the three steps necessary for creating a JPOX plugin are
- Review the JPOX interface that you will need to implement to generate the plugin, and implement it
- Create a file plugin.xml at the top level of your JAR defining the plugin details (see below).
- Update the MANIFEST.MF file contained in the jar so that it includes necessary information for OSGi.
Below we describe the aspects of the persistence process that are currently pluggable using this mechanism.
If you write a JPOX plugin and you either want it to be included in the JPOX distribution, or want it to be
listed here then please contact us via the JPOX Forum
Non managed environment is a runtime environment where JPOX runs and plug-ins are not managed by a container.
In this environment the plug-in discovery and lifecycle is managed by JPOX.
There is a 1 to N instance relationship from JPOX 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.
Managed environment is a runtime environment where JPOX 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 JPOX 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.
JPOX supports OSGi containers as managed environment.
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.
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.
JPOX has mechanism that allows extending its persistence engine while not coupling the JPOX
engine to the extensions. This mechanism is known as "Extension Points", which are well defined
interfaces that allows the extension of certain aspects of JPOX in a dynamic and consistent
model. The "Extensions" are the implementation of Extension Points that are registered in a
PluginRegistry and used by JPOX Core or other JPOX Plug-ins.
A plug-in owns an Extension.
Each extension is created by a segment of code during the runtime execution, and
destroyed/released whenever they are no longer needed. This have no influence with the plug-in
lifecycle.
In non managed environments, the plug-ins are managed by JPOX 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.
In non managed environments all plugins are registered using an instance of
JDOClassLoaderResolver (so using the current ClassLoader of the PersistenceManagerFactory 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.
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.
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.
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.
Inside the JPOX Core, regardless if the runtime is OSGi managed or non managed, extension
instances are created per PMF.
JPOX Extensions should always be created through a PluginManager, regardless if the managed
environment would allow you to instantiate using their own interfaces. This allows JPOX and
JPOX Plug-ins to run in non managed environments.
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.
If a plug-in defines a new PMF configuration, the property name should be prefixed by the
plug-in id. Example:
Plugin: org.jpox.myplugin1
Property: myprop1
The PMF property should look like org.jpox.myplugin1.myprop1.
If an extension point defines a new PMF configuration, the property name should be prefixed by
the extension-point id. Example:
Extension-Point id: org.jpox.myplugin2.myextensionpoint2
Property: myprop2
The PMF property should look like org.jpox.myplugin2.myextensionpoint2.myprop2.
Another form of PMF 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.jpox.myplugin3.myextensionpoint3
Extension-Point id: org.jpox.yourplugin3.yourextensionpoint4
Extension-Point id: org.jpox.theirplugin4.theirextensionpoint5
Property: myprop345
The PMF property should look like
org.jpox.somepluginXXXX.someextensionpointYYYY.myprop345. Alternativelly,
the PMF property could also look like
org.jpox.myplugin3.myextensionpoint3.myprop345