Hitachi Vantara Pentaho Community Wiki
Child pages
  • Pentaho ObjectFactory and Spring Enhancements
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

Version 1 Next »

Pentaho ObjectFactory and Spring Enhancements in 5.0

Introduction

Version 5.0 of the Pentaho Suite introduces several enhancements to core architecture of Platform. These enhancements are designed to aid the development of new features as well as allowing more customization options for existing features.

Background Architecture

The Pentaho Platform started with a pure service-locator facility to provide plugability of implementations and factoring of objects. Static access to this service-locator was provided through PentahoSystem.get() calls and it was backed by a rudimentary Object Factory and registery.

A typical call to locate or instance a class looked something like this:

ISolutionRepository repo = (ISolutionRepository) PentahoSystem.get("solutionRepository"); 

The PentahoSystem ObjectFactory was later replaced by a wrapper around a Spring XML ApplicationContext. At this time the system was extended to provide a class literal instead of a String. The resulting object was cast to the class of the literal. Here's the same call using this new functionality

<bean id="ISolutionRepository" class="org.pentaho.SomeImpl"/> 
ISolutionRepository repo = PentahoSystem.get(ISolutionRepository.class); 

This really wasn't much different from the first system. The SimpleName was extracted from the passed-in class. This Simple Name had to match the ID of a bean in the Spring App Context. A downside as a result of this was that you could only have one implementation for a given class. To work around this this limiation another enhancement was made allowing you to pass a String second parameter corresponding to the id of the bean in the Spring ApplicationContext.

<bean id="ISolutionRepository" class="org.pentaho.SomeImpl"/> 
<bean id="CustomSolutionRepository" class="org.pentaho.SomeImpl"/> 
ISolutionRepository repo = PentahoSystem.get(ISolutionRepository.class, "CustomSolutionRepository"); 

This is essentially the state of the system up until 5.0. Beans were simple Classes which were internally expected to call PentahoSystem.get() to retrieve their own dependencies. Any bean referencing another directly in Spring was discouraged. That lack of expressiveness in the Spring XML kept the internals of the system very opaque. Additionally every class was still very dependent of the PentahoSystem Service Locator.

New Enhancements

5.0 brings features both to the PentahoSystem service locator as well as Spring.

PentahoSystem:

The ObjectFactory backing PentahoSystem is no longer based on a single Spring ApplicationContext. There can now be any number of registered Object Factories registered with the system. Queries for a particular type will find the most appropriate type from any of the registered ObjectFactories.

Call

Description

PentahoSystem.getAll()

Retrieve a list of implementations for a given type (i.e. all IContentGenerators). Ordered by priority

PentahoSystem.get()

Now returns the highest priority implementation registered in the system.

PentahoSystem.get(Type, Map<String, String>)

Query for an implementation with the given properties. Ordered by priority.

PentahoSystem.getObjectReference(Type)

Returns a descriptor for a registered implementation containing all attributes and a method getObject() to instantiate the referenced type.

Spring:

Spring Element

Description

<pen:bean class="com.foo.Bar"/>

Retrieve the highest priority implementation for a given type (i.e. all IContentGenerators). Published beans are given highest priority when searching for an implementation. If no beans have been published for the type, each registered ObjectFactory will be checked to see if they have an implementation (simple <bean>). The first one found will be returned.

<pen:list class="com.foo.Bar"/>

Retrieve a list of implementations for a given type (i.e. all IContentGenerators). Ordered by priority. unlike <pen:bean> only published implementations will be included in the list.

<pen:attributes>

Provide attribute metadata about a published bean, or use in conjuction with <pen:bean> or <pen:list> to query for specific implementations.
A special named attribute "priority" is used by the system to determine the order of implementations.

Any Spring file can take advantage of these extensions. <pen:bean> and <pen:list> can be used like any other bean in the Spring file. They can be given IDs and references, embedded in <constructor-arg> and <property> elements. Anything you can do with a normal Spring <bean> can be done with the Pentaho additions.

If you want your Spring ApplicationContext to be able to provide implementations for others to find, you must register the ApplicationContext by placing the following in your XML file.

<bean class="org.pentaho.platform.engine.core.system.objfac.spring.ApplicationContextPentahoSystemRegisterer" scope="singleton"/> 

Once a Spring ApplicationContext is registered it can then publish beans into the system using the following:

<bean class="…"> 
  <pen:publish as-Type="com.foo.Bar"/> 
</bean> 

Once published the bean can be found by others calling <pen:bean> or <pen:list>. the as-Type attribute controls how the bean is registered. The options are INTERFACES, CLASSES, ALL or a specific class as seen above. INTERFACES will publish the bean registering it as an implementation of all interfaces for which the bean implements. CLASSES will publish it as an implementation of all classes from which it inherits, including itself. ALL publishes as both Classes and Interfaces. The default is to publish as the class itself.

Usage Examples

Register a single implementation of a given interface org.pentaho.IDatasource.

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:pen="http://www.pentaho.com/schema/pentaho-system" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd 
http://www.pentaho.com/schema/pentaho-system http://www.pentaho.com/schema/pentaho-system.xsd"> 

  <!-- Register this ApplicationContext so it can publish beans --> 
  <bean class="org.pentaho.platform.engine.core.system.objfac.spring.ApplicationContextPentahoSystemRegisterer" scope="singleton"/> 

  <bean class="org.pentaho.MyDatasource"> 
    <pen:publish as-type="INTERFACES"/> 
    <pen:attributes> 
      <pen:attr key="type" value="special"/> 
    </pen:attributes> 
  </bean> 

</beans>

PentahoSystem now has one registered implementation of the org.pentaho.IDatasource interface. It can be retrieved by calling PentahoSystem directly:

IDatasource datasource = PentahoSystem.get(IDatasource.class); 

or through Spring:

<bean class="com.foo.MyObject"> 
  <property name="datasource"> 
    <pen:bean class="org.pentaho.IDatasource"/> 
  </property> 
</bean> 

Register multiple implementations, using Priority to determine which will be provided

By default all beans are given a priority of 20. You control which will be returned by PentahoSystem.get() and <pen:bean> by specifying a higher priority in one of the published beans

<bean class="org.pentaho.MyDatasource"> 
  <pen:publish as-type="INTERFACES"/> 
</bean> 

<bean class="org.pentaho.MyCustomDatasource"> 
  <pen:publish as-type="INTERFACES"/> 
  <pen:attributes> 
    <pen:attr key="priority" value="30"/> 
  </pen:attributes> 
</bean> 

Even though two implementations of IDatasource are registered. The second will be returned by PentahoSystem.get() and <pen:bean> as it's now the highest priority. Calls to PentahoSystem.getAll() or <pen:list> will return both, ordered by priority.

Register multiple implementations, using attributes to determine which will be provided

Lets say you know need an implementation of IDatasource which provides connections to a particular system. You could create a sub-type and query for that, or you can use the Attribute metadata feature to return the one you need.

<bean class="org.pentaho.MyDatasource"> 
  <pen:publish as-type="INTERFACES"/> 
  <pen:attributes> 
    <pen:attr key="type" value="jdbc"/> 
  </pen:attributes> 
</bean> 
<bean class="org.pentaho.MyOlapDatasource"> 
  <pen:publish as-type="INTERFACES"/> 
  <pen:attributes> 
    <pen:attr key="type" value="olap"/> 
  </pen:attributes> 
</bean> 

You can now query for the highest priority implementation of IDatasource matching the type=olap using the following

IDatasource olapDs = PentahoSystem.get(IDatasource.class, Collections.singletonMap("type, "olap")); 

or in Spring using:

<pen:bean class="org.pentaho.IDatasource"> 
  <pen:attributes> 
    <pen:attr key="type" value="olap"/> 
  </pen:attributes> 
</pen:bean> 

Attribute-based queries are possible with <pen:list> as well

<pen:list class="org.pentaho.IDatasource"> 
  <pen:attributes> 
    <pen:attr key="type" value="olap"/> 
  </pen:attributes> 
</pen:bean> 

Of course in this example the list will contain only one entry.

  • No labels