org.drools.runtime.pipeline
Class PipelineFactory

java.lang.Object
  extended by org.drools.runtime.pipeline.PipelineFactory

public class PipelineFactory
extends Object

The PipelineFactory and associated classes are there to help with the automation of getting information into and out of Drools, especially when using services, such as JMS, and non pojo data sources. Transformers for Smooks, JAXB, Xstream and Jxls are povided. Smooks is an ETL tooling and can work with a variety of data sources, JAXB is a Java standard aimed at working with XSDs, while XStream is a simple and fast xml serialisation framework and finally Jxls allows for loading of pojos from an excel decision table. minimal information on these technologies will be provided here and it is expected for the user to consult the relevant user guide for each.

Pipeline is not meant as a replacement for products like the more powerful Camel, but is aimed as a complimentary framework that ultimately can be integrated into more powerful pipeline frameworks. Instead it is a simple framework aimed at the specific Drools use cases.

In Drools a pipeline is a series of stages that operate on and propagate a given payload. Typically this starts with a Pipeline instance which is responsible for taking the payload, creating a PipelineContext for it and propagating that to the first Receiver stage. Two types of Pipelines are provided, both requiring a different PipelineContexts. StatefulKnowledgeSessionPipeline and StatelessKnowledgeSessionPipeline. Notice that both factory methods take the relevant session as an argument.

 Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
 pipeline.setReceiver( receiver );
 

A pipeline is then made up of a chain of Stages that can implement both the Emitter and the Receiver interfaces. The Emitter interface means the stage can propagate a payload and the Receiver interface means it can receive a payload. This is why the Pipeline interface only implements Emitter and Stage and not Receiver, as it is the first instance in the chain. The Stage interface allows a custom exception handler to be set on the stage.

 Transformer transformer = PipelineFactory.newXStreamFromXmlTransformer( xstream );
 transformer.setStageExceptionHandler( new StageExceptionHandler() { .... } );
 

The Transformer interface above extends both Stage, Emitter and Receiver, other than providing those interface methods as a single type, it's other role is that of a marker interface that indicates the role of the instance that implements it. We have several other marker interfaces such as Expression and Action, both of which also extend Stage, Emitter and Receiver. One of the stages should be responsible for setting a result value on the PipelineContext. It is the role of the ResultHandler interface, that the user implements that is responsible for executing on these results or simply setting them an object that the user can retrieve them from.

 ResultHandler resultHandler = new ResultHandlerImpl();
 pipeline.insert( factHandle, resultHandler );
 System.out.println( resultHandler );
 ...
 public class ResultHandlerImpl implements ResultHandler {
     Object result;

     public void handleResult(Object result) {
         this.result = result;
     }

     public Object getResult() {
         return this.result;
     }
 }
 

while the above example shows a simple handler that simply assigns the result to a field that the user can access, it could do more complex work like sending the object as a message.

Pipeline is provides an adapter to insert the payload and internally create the correct PipelineContext. Two types of Pipelines are provided, both requiring a different PipelineContext. StatefulKnowledgeSessionPipeline and StatelessKnowledgeSessionPipeline. Pipeline itself implements both Stage and Emitter, this means it's a Stage in a pipeline and emits the payload to a receiver. It does not implement Receiver itself, as it the start adapter for the pipeline. PipelineFactory provides methods to create both of the two Pipeline. StatefulKnowledgeSessionPipeline is constructed as below, with the receiver set

In general it easier to construct the pipelines in reverse, for example the following one handles loading xml data from disk, transforming it with xstream and then inserting the object:

// Make the results, in this case the FactHandles, available to the user Action executeResultHandler = PipelineFactory.newExecuteResultHandler(); // Insert the transformed object into the session associated with the PipelineContext KnowledgeRuntimeCommand insertStage = PipelineFactory.newStatefulKnowledgeSessionInsert(); insertStage.setReceiver( executeResultHandler ); // Create the transformer instance and create the Transformer stage, where we are going from Xml to Pojo. XStream xstream = new XStream(); Transformer transformer = PipelineFactory.newXStreamFromXmlTransformer( xstream ); transformer.setReceiver( insertStage ); // Create the start adapter Pipeline for StatefulKnowledgeSessions Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession ); pipeline.setReceiver( transformer ); // Instantiate a simple result handler and load and insert the XML ResultHandlerImpl resultHandler = new ResultHandlerImpl(); pipeline.insert( ResourceFactory.newClassPathResource( "path/facts.xml", getClass() ), resultHandler );

While the above example is for loading a resource from disk it is also possible to work from a running messaging service. Drools currently provides a single Service for JMS, called JmsMessenger. Support for other Services will be added later. Below shows part of a unit test which illustrates part of the JmsMessenger in action

 // as this is a service, it's more likely the results will be logged or sent as a return message 
 Action resultHandlerStage = PipelineFactory.newExecuteResultHandler();

 // Insert the transformed object into the session associated with the PipelineContext
 KnowledgeRuntimeCommand insertStage = PipelineFactory.newStatefulKnowledgeSessionInsert();
 insertStage.setReceiver( resultHandlerStage );

 // Create the transformer instance and create the Transformer stage, where we are going from Xml to Pojo. Jaxb needs an array of the available classes
 JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames,
                                                              kbase );
 Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
 Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
 transformer.setReceiver( insertStage );

 // payloads for JMS arrive in a Message wrapper, we need to unwrap this object
 Action unwrapObjectStage = PipelineFactory.newJmsUnwrapMessageObject();
 unwrapObjectStage.setReceiver( transformer );

 // Create the start adapter Pipeline for StatefulKnowledgeSessions
 Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
 pipeline.setReceiver( unwrapObjectStage );

 // Services, like JmsMessenger take a ResultHandlerFactory implementation, this is because a result handler must be created for each incoming message.
 ResultHandleFactoryImpl factory = new ResultHandleFactoryImpl();
 Service messenger = PipelineFactory.newJmsMessenger( pipeline,
                                                      props,
                                                      destinationName,
                                                      factory );
 messenger.start();
 

This api is experimental and thus the classes and the interfaces returned are subject to change.


Constructor Summary
PipelineFactory()
           
 
Method Summary
static Action newAssignObjectAsResult()
          This assigns the propagating payload object to the PipelineContext.result property
static KnowledgeRuntimeCommand newCommandExecutor()
           
static Action newExecuteResultHandler()
          When inserting into a Pipeline a ResultHandler may be passed.
static KnowledgeRuntimeCommand newInsertElementsCommand()
           
static KnowledgeRuntimeCommand newInsertObjectCommand()
           
static Splitter newIterateSplitter()
          Iterates the Iterable object and propagate each element in turn.
static Transformer newJaxbFromXmlTransformer(javax.xml.bind.Unmarshaller unmarshaller)
          Transforms from XML to Pojo using JAXB, the resulting pojo is set as the propagating object.
static Transformer newJaxbToXmlTransformer(javax.xml.bind.Marshaller marshaller)
          Transforms from Pojo to XML using JAXB, the resulting XML is set as the propagating object.
static Service newJmsMessenger(Pipeline pipeline, Properties properties, String destinationName, ResultHandlerFactory resultHandlerFactory)
          Creates a new JmsMessenger which runs as a service in it's own thread.
static Action newJmsUnwrapMessageObject()
          Unwrap the payload from the JMS Message and propagate it as the payload object.
static Transformer newJxlsTransformer(net.sf.jxls.reader.XLSReader xlsReader, String text)
          Transforms from an Excel spread to a Map of pojos pojos using jXLS, the resulting map is set as the propagating object.
static Join newListCollectJoin()
          Collect each propagated item into a list, this is used as part of a Splitter.
static Action newMvelAction(String action)
          Create a new MVEL action
static Expression newMvelExpression(String expression)
          Creat a new MVEL expression, the payload will be set to the results of the expression.
static Transformer newSmooksFromSourceTransformer(org.milyn.Smooks smooks, String rootId)
           Transforms from Source to Pojo using Smooks, the resulting pojo is set as the propagating object.
static Transformer newSmooksToSourceTransformer(org.milyn.Smooks smooks)
           Transforms from Pojo to Source using Smooks, the resulting Source is set as the propagating object // Instantiate Smooks with the config...
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionGetGlobal()
          The payload here is expected to be a String and the global will be set on the PipelineContext result property.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionGetObject()
          Expects the payload to be a FactHandle, the associated insert object will be set on the PipelineContext result property and the result itself will also be propagated.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionInsert()
          Insert the payload into the StatefulKnowledgeSesssion referenced in the context.
static Pipeline newStatefulKnowledgeSessionPipeline(org.drools.runtime.StatefulKnowledgeSession ksession)
          Construct a new Pipeline to be used when interacting with a StatefulKnowledgeSession.
static Pipeline newStatefulKnowledgeSessionPipeline(org.drools.runtime.StatefulKnowledgeSession ksession, String entryPointName)
          Construct a new Pipeline to be used when interacting with a StatefulKnowledgeSession.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSetGlobal()
          Expects the payload to be a Map which it will iterate and set each global on the StatefulKnowledgeSession .
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSetGlobal(String identifier)
          Expects the payload to be any object, that object will be set as a global using the given identifier.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSignalEvent(String eventType)
          The payload is inserted as a Signal of a given event type.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSignalEvent(String eventType, long id)
          The payload is inserted as a Signal of a given event type for a specific process instance.
static KnowledgeRuntimeCommand newStatefulKnowledgeSessionStartProcess(String id)
          Start a process of the given id.
static Pipeline newStatelessKnowledgeSessionPipeline(org.drools.runtime.StatelessKnowledgeSession ksession)
          Construct a new Pipeline to be used when interacting with StatelessKnowledgeSessions.
static Transformer newXStreamFromXmlTransformer(com.thoughtworks.xstream.XStream xstream)
           Transforms from XML to Pojo using XStream, the resulting Pojo is set as the propagating object.
static Transformer newXStreamToXmlTransformer(com.thoughtworks.xstream.XStream xstream)
           Transforms from Pojo to XML using XStream, the resulting XML is set as the propagating object.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

PipelineFactory

public PipelineFactory()
Method Detail

newStatefulKnowledgeSessionPipeline

public static Pipeline newStatefulKnowledgeSessionPipeline(org.drools.runtime.StatefulKnowledgeSession ksession)
Construct a new Pipeline to be used when interacting with a StatefulKnowledgeSession. It assumes that the default entry point will be used for any insertions.

Parameters:
ksession -
Returns:

newStatefulKnowledgeSessionPipeline

public static Pipeline newStatefulKnowledgeSessionPipeline(org.drools.runtime.StatefulKnowledgeSession ksession,
                                                           String entryPointName)
Construct a new Pipeline to be used when interacting with a StatefulKnowledgeSession. The entry point to be used is specified as s String.

Parameters:
ksession -
entryPointName -
Returns:

newStatelessKnowledgeSessionPipeline

public static Pipeline newStatelessKnowledgeSessionPipeline(org.drools.runtime.StatelessKnowledgeSession ksession)
Construct a new Pipeline to be used when interacting with StatelessKnowledgeSessions.

Parameters:
ksession -
Returns:

newCommandExecutor

public static KnowledgeRuntimeCommand newCommandExecutor()

newInsertElementsCommand

public static KnowledgeRuntimeCommand newInsertElementsCommand()

newInsertObjectCommand

public static KnowledgeRuntimeCommand newInsertObjectCommand()

newStatefulKnowledgeSessionInsert

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionInsert()
Insert the payload into the StatefulKnowledgeSesssion referenced in the context. This stage expects the returned FactHandles to be stored in a HashMap of the PipelineContext result property.

Returns:

newStatefulKnowledgeSessionGetGlobal

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionGetGlobal()
The payload here is expected to be a String and the global will be set on the PipelineContext result property. The propagating object will also be switched to the results.

Returns:

newStatefulKnowledgeSessionSetGlobal

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSetGlobal()
Expects the payload to be a Map which it will iterate and set each global on the StatefulKnowledgeSession .

Returns:

newStatefulKnowledgeSessionGetObject

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionGetObject()
Expects the payload to be a FactHandle, the associated insert object will be set on the PipelineContext result property and the result itself will also be propagated.

Returns:

newStatefulKnowledgeSessionSetGlobal

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSetGlobal(String identifier)
Expects the payload to be any object, that object will be set as a global using the given identifier.

Parameters:
identifier -
Returns:

newStatefulKnowledgeSessionSignalEvent

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSignalEvent(String eventType)
The payload is inserted as a Signal of a given event type.

Parameters:
eventType -
Returns:

newStatefulKnowledgeSessionSignalEvent

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionSignalEvent(String eventType,
                                                                             long id)
The payload is inserted as a Signal of a given event type for a specific process instance.

Parameters:
eventType -
id -
Returns:

newStatefulKnowledgeSessionStartProcess

public static KnowledgeRuntimeCommand newStatefulKnowledgeSessionStartProcess(String id)
Start a process of the given id. The payload is expected to be a Map and is used for the process variables.

Parameters:
id -
Returns:

newAssignObjectAsResult

public static Action newAssignObjectAsResult()
This assigns the propagating payload object to the PipelineContext.result property

Returns:

newExecuteResultHandler

public static Action newExecuteResultHandler()
When inserting into a Pipeline a ResultHandler may be passed. This stage will execute the user implemented class.

Returns:

newMvelAction

public static Action newMvelAction(String action)
Create a new MVEL action

Parameters:
action -
Returns:

newMvelExpression

public static Expression newMvelExpression(String expression)
Creat a new MVEL expression, the payload will be set to the results of the expression.

Parameters:
expression -
Returns:

newIterateSplitter

public static Splitter newIterateSplitter()
Iterates the Iterable object and propagate each element in turn.

Returns:

newListCollectJoin

public static Join newListCollectJoin()
Collect each propagated item into a list, this is used as part of a Splitter. The Join should be set on the splitter using the setJoin method, this allows the Splitter to signal the join when it has propagated all the elements of the Iterable object.

Returns:

newJmsMessenger

public static Service newJmsMessenger(Pipeline pipeline,
                                      Properties properties,
                                      String destinationName,
                                      ResultHandlerFactory resultHandlerFactory)
Creates a new JmsMessenger which runs as a service in it's own thread. It expects an existing JNDI entry for "ConnectionFactory" Which will be used to create the MessageConsumer which will feed into the specified pipeline.
 // as this is a service, it's more likely the results will be logged or sent as a return message 
 Action resultHandlerStage = PipelineFactory.newExecuteResultHandler();

 // Insert the transformed object into the session associated with the PipelineContext
 KnowledgeRuntimeCommand insertStage = PipelineFactory.newStatefulKnowledgeSessionInsert();
 insertStage.setReceiver( resultHandlerStage );

 // Create the transformer instance and create the Transformer stage, where we are going from Xml to Pojo. Jaxb needs an array of the available classes
 JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames,
                                                              kbase );
 Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
 Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
 transformer.setReceiver( insertStage );

 // payloads for JMS arrive in a Message wrapper, we need to unwrap this object
 Action unwrapObjectStage = PipelineFactory.newJmsUnwrapMessageObject();
 unwrapObjectStage.setReceiver( transformer );

 // Create the start adapter Pipeline for StatefulKnowledgeSessions
 Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
 pipeline.setReceiver( unwrapObjectStage );

 // Services, like JmsMessenger take a ResultHandlerFactory implementation, this is because a result handler must be created for each incoming message.
 ResultHandleFactoryImpl factory = new ResultHandleFactoryImpl();
 Service messenger = PipelineFactory.newJmsMessenger( pipeline,
                                                      props,
                                                      destinationName,
                                                      factory );
 messenger.start();
 

Parameters:
pipeline -
properties -
destinationName -
resultHandlerFactory -
Returns:

newJmsUnwrapMessageObject

public static Action newJmsUnwrapMessageObject()
Unwrap the payload from the JMS Message and propagate it as the payload object.

Returns:

newSmooksFromSourceTransformer

public static Transformer newSmooksFromSourceTransformer(org.milyn.Smooks smooks,
                                                         String rootId)

Transforms from Source to Pojo using Smooks, the resulting pojo is set as the propagating object.

 // Instantiate Smooks with the config...
 Smooks smooks = new Smooks( getClass().getResourceAsStream( "smooks-config.xml" ) );

 Transformer transformer = PipelineFactory.newSmooksFromSourceTransformer( smooks,
                                                                           "orderItem" );
 transformer.setReceiver( insertStage );
 

Parameters:
smooks -
rootId -
Returns:

newSmooksToSourceTransformer

public static Transformer newSmooksToSourceTransformer(org.milyn.Smooks smooks)

Transforms from Pojo to Source using Smooks, the resulting Source is set as the propagating object

 // Instantiate Smooks with the config...
 Smooks smooks = new Smooks( getClass().getResourceAsStream( "smooks-config.xml" ) );

 Transformer transformer = PipelineFactory.newSmooksToSourceTransformer( smooks );
 transformer.setReceiver( receiver );
 

Parameters:
smooks -
rootId -
Returns:

newJaxbFromXmlTransformer

public static Transformer newJaxbFromXmlTransformer(javax.xml.bind.Unmarshaller unmarshaller)
Transforms from XML to Pojo using JAXB, the resulting pojo is set as the propagating object.
 JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames,
                                                                kbase );
 Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
 Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
 transformer.setReceiver( receiver );
 
Don't forget the XSD model must be generated, using XJC at runtime into the KnowledgeBase first, Using KnowledgeBuilderHelper.addXsdModel:
 Options xjcOpts = new Options();
 xjcOpts.setSchemaLanguage( Language.XMLSCHEMA );
 KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();

 String[] classNames = KnowledgeBuilderHelper.addXsdModel( ResourceFactory.newClassPathResource( "order.xsd",
                                                                                                 getClass() ),
                                                           kbuilder,
                                                           xjcOpts,
                                                           "xsd" );
 

Parameters:
unmarshaller -
Returns:

newJaxbToXmlTransformer

public static Transformer newJaxbToXmlTransformer(javax.xml.bind.Marshaller marshaller)
Transforms from Pojo to XML using JAXB, the resulting XML is set as the propagating object.
  JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames,
                                                               kbase );
  Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
  Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
  transformer.setReceiver( receiver );

Parameters:
marshaller -
Returns:

newXStreamFromXmlTransformer

public static Transformer newXStreamFromXmlTransformer(com.thoughtworks.xstream.XStream xstream)

Transforms from XML to Pojo using XStream, the resulting Pojo is set as the propagating object.

 Marshaller marshaller = jaxbCtx.createMarshaller();
 Transformer transformer = PipelineFactory.newJaxbToXmlTransformer( marshaller );
 transformer.setReceiver( receiver );
 

The BatchExecutionHelper factory provides a pre-configured XStream instance used for marshalling Commands, specifically the BatchExecutionCommand and the ExecutionResults. It also contains docs on the xml formant and on how to use the pipeline for marshalling BatchExecutionCommand and ExecutionResults.

Parameters:
xstream -
Returns:

newXStreamToXmlTransformer

public static Transformer newXStreamToXmlTransformer(com.thoughtworks.xstream.XStream xstream)

Transforms from Pojo to XML using XStream, the resulting XML is set as the propagating object.

 XStream xstream = new XStream();
 Transformer transformer = PipelineFactory.newXStreamToXmlTransformer( xstream );
 transformer.setReceiver( receiver );
 

The BatchExecutionHelper factory provides a pre-configured XStream instance used for marshalling Commands, specifically the BatchExecutionCommand and the ExecutionResults. It also contains docs on the xml formant and on how to use the pipeline for marshalling BatchExecutionCommand and ExecutionResults.

Parameters:
xstream -
Returns:

newJxlsTransformer

public static Transformer newJxlsTransformer(net.sf.jxls.reader.XLSReader xlsReader,
                                             String text)
Transforms from an Excel spread to a Map of pojos pojos using jXLS, the resulting map is set as the propagating object. You may need to use splitters and MVEL expressions to split up the transformation to insert individual pojos. Note you must provde an XLSReader, which references the mapping file and also an MVEL string which will instantiate the map. The mvel expression is pre-compiled but executedon each usage of the transformation.
 XLSReader mainReader = ReaderBuilder.buildFromXML( ResourceFactory.newClassPathResource( "departments.xml", getClass() ).getInputStream() );
 Transformer transformer = PipelineFactory.newJxlsTransformer(mainReader, "[ 'departments' : new java.util.ArrayList(), 'company' : new org.drools.runtime.pipeline.impl.Company() ]");
 

Parameters:
xlsReader -
text -
Returns:


Copyright © 2001-2011 JBoss Inc.. All Rights Reserved.