Hitachi Vantara Pentaho Community Wiki
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Introduction

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.

Background

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, nor 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 (Interface) as well as adding a filtering mechanism so a single implementation could be found by attributes (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

ObjectReferences

Another change made in the 5.0 release was the introduction of IPentahoObjectReference (source). These are wrappers, or more appropriately descriptors, of an object in the ObjectFactory. The main advantage these brought was the ability to provide attribute metadata which powers the ordering and filtering available in 5.0. It also allows for the lazy creation of the actual objects described by the reference. The same lazy mechanism also allows the ObjectReference to be a factory.

OSGI ObjectFactory

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.

In OSGI Bundle
BundleContext cxt = ...
IContentInfo infoInstance = new ContentInfo();
HashTable props = new HashTable( { put("prop1", "value"); } );
cxt.registerService( IContentInfo.class, infoInstance, props );
In Pentaho Code
IContentInfo fromOsgi = PentahoSystem.get( IContentInfo.class, null, Collections.singletonMap( "prop1", "value" ) );
Runtime ObjectFactory

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.

Object Registration

import static org.pentaho.platform.api.engine.IPentahoRegistrableObjectFactory.Types;
...
// "Testing" will be registered under all Classes in the inheritance chain (String, Object).
PentahoSystem.registerObject( "Testing", Types.CLASSES );

// "Testing" will be registered under all implementing Interfaces ( CharSequence an Serializable )
PentahoSystem.registerObject( "Testing", Types.INTERFACES );

// "Testing" will be registered under all implemented Interfaces and all Classes in the inheritance chain (String, Object, CharSequence, Serializable).
PentahoSystem.registerObject( "Testing", Types.ALL );

// "Testing" will be registered under just the String Class.
PentahoSystem.registerObject( "Testing", String.class);

// "Testing" will be registered under the String Class and CharSequence Interface
PentahoSystem.registerObject( "Testing", String.class, CharSequence.class);

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.

SingletonPentahoObjectReference Registration
import static org.pentaho.platform.api.engine.IPentahoRegistrableObjectFactory.Types;
...

// Singleton will always return the same Object it was constructed with
SingletonPentahoObjectReference reference = new SingletonPentahoObjectReference.Builder<String>( String.class ).object( "Hello" ).attributes(
    Collections.<String, Object>singletonMap( "attr1", "value1" ) ).build()
PentahoSystem.registerReference( reference, Types.CLASSES );

PrototypePentahoObjectReference Registration
import static org.pentaho.platform.api.engine.IPentahoRegistrableObjectFactory.Types;
...

// Prototype requires an IObjectCreator which is called for each call to reference.getObject()
PrototypePentahoObjectReference protoReference = new PrototypePentahoObjectReference.Builder<UUID>( UUID.class ).creator(
  new IObjectCreator<UUID>() {
    @Override public UUID create( IPentahoSession session ) {
      return UUID.randomUUID();
    }
  }).build();
PentahoSystem.registerReference( protoReference, UUID.class );

PrototypePentahoObjectReference Registration
import static org.pentaho.platform.api.engine.IPentahoRegistrableObjectFactory.Types;
...

// Session-Based will call the IObjectCreator for each unique IPentahoSession it's called with. Subsequent calls with the same session will return the same Object
SessionBoundPentahoObjectReference sessionReference = new SessionBoundPentahoObjectReference.Builder<UUID>( UUID.class ).creator(
  new IObjectCreator<UUID>() {
    @Override public UUID create( IPentahoSession session ) {
      return UUID.randomUUID();
    }
  }).build();
PentahoSystem.registerReference( sessionReference, UUID.class );

EEPluginManager

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:

// instead of this
IPluginManager pluginManager = PentahoSystem.get( IPluginManager.class );
List<XulOverlay> overlays = pluginManager.getOverlays();

// you can call this
List<XulOverlay> overlays = PentahoSystem.getAll( XulOverlay.class )

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!

  • No labels