5.1 includes several large changes which bring new features to the platform today while setting the stage for larger things to come. Before we dive-in to the specific enhancements made, it's important to understand the broader context in which the changes are being and the motivations behind them.
For some years now it’s been our desire to transition away from our limited home-grown plugin system to an industry standard modular system based-on OSGI. In 5.0 we began laying the groundwork for this transition. 5.1 sees us forge a clear migration path and rolls-out the first stages of OSGI in the Platform.
First a little background on why these changes were necessary. The Platform at one time was designed around a central service-locator backed by a singular ObjectFactory ( Spring in production ). Unfortunately this service locator didn’t support collections of objects, querying, or the ability to extend it without editing a bunch of core files. There was no clean way to drop something into the platform and have it integrate well with the system. Consequently the IPluginManager came to prominence.
PluginManager and PlatformPlugins provided a good “vehicle” for getting new features into the system. Since then the Platform has steadily moved to a more plugin-centric model. This is not wholly bad, its one-step closer to a modular architecture.
Unfortunately, our plugin system is not that sophisticated. Classes cannot be shared between plugins, limiting the extension of the platform and hurting cohesion between plugins. Since Classes cannot be shared out of Plugins, no new concepts can be added to the system. We actually have multiple instances of plugins communicating between each other using web services, content-generators and even reflection to work-around this limitation. Some things can only be supplied through plugins, making core code a second-class citizen in it’s own house. To work around this many of the "core" features are registered through the “default-plugin”. OSGI addresses all of these concerns, but how can be get there?
The transition involves leveling the field between legacy plugins, core code and OSGI Bundles. Once on an equal footing, Platform Plugins can be migrated to OSGI Bundles over a period of time. 5.1 accomplishes precisely this
Leveling the field
Early-on we identified that the dual APIs of PentahoSystem.getXXX() and IPluginManager.getXXX needed to be consolidated. The choice was made to enhance the PentahoSystem's backing IPentahoObjectFactory APIs to support collections of objects per type (Class/Interface) as well as adding a filtering mechanism (find IContentGenerator for type 'prpt'). The combination of these two would allow for a transition away from the IPluginManager API. 5.0 delivered these enhancements.
Extensible ObjectFactory for PentahoSystem
5.0 also replaced the singular Spring-based IPentahoObjectFactory with an Aggregating ObjectFactory implementation. This new AggregateObjectFactory supports the registration of any number of IPentahoObjectFactory instances. Queries to the Aggregate call down to all configured "sub"-factories for matches. The results are filtered by any query conditions, ordered by priority and returned back. The AggregateObjectFactory can be thought of as a single Logical view over many Physicals underneath. The main Spring ApplicationContent (pentaho-spring-beans.xml) is registered as well as any plugin.spring.xml files publishing beans (link to 5.0 document). 5.1 sees two new sub-factories registered by default, RuntimeObjectFactory and OSGIObjectFactory
Another change made in the 5.0 release was the introduction of IPentahoObjectReference (source). These are wrappers, or more appropriately descriptors, for an Object available in the ObjectFactory. The main advantage these bring is the ability to provide attribute metadata which powers the ordering and filtering capabilities. It also allows for the lazy creation of the actual objects described by the reference. The same lazy mechanism also makes it possible for an ObjectReference to be a factory.
The OSGIObjectFactory delegates down to the OSGI Service Registry to find matching ServiceReferences. These ServiceReferences map almost directly to IPentahoObjectReferences. If your bundle registers a
Service, it will be found through PentahoSystem.getXXX calls by the same Classes/Interfaces and properties as it was registered with in OSGI.
The RuntimeObjectFactory is an implementation of the IPentahoRegistrableObjectFactory interface (source). This interface extends the IPentahoObjectFactory with new methods allowing the registration of Objects and IPentahoObjectReferences at runtime. Some built-in IPentahoObjectReference implementations are available for common factory scenarios ( SingletonPentahoObjectReference, SessionBoundPentahoObjectReference, SingletonPentahoObjectReference). Each of these has a static Builder available to make construction easier.
IPentahoObjectReference registration is much the same as Object registration. Below are some examples of some of the built-in ObjectReference types available out-of-the-box.
Both PentahoSystem.registerObject and PentahoSystem.registerReference return a IPentahoObjectRegistration handle. This can be used later to de-register the Object or Reference
The new EEPluginManager uses these methods to store plugin objects in the PentahoSystem instead of keeping them hidden within, as was done in the DefaultPluginManager. The result is that you no longer have to make calls to the IPluginManager and can instead query the PentahoSystem:
The significance of this change is that this second call will return XulOverlays not just from the PlatformPlugins, but also from OSGI bundles, configured Spring ApplicationContexts or anyone registered with the AggregateObjectFactory! This is the key to transitioning to OSGI!