Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "SMILA/Documentation/HowTo/How to write a Pipelet"

(Pipelet Usage)
(Piplet configuration usage)
Line 105: Line 105:
 
<source lang="java">
 
<source lang="java">
 
public class AddValuesPipelet implements Pipelet {
 
public class AddValuesPipelet implements Pipelet {
   private static final String PARAM_ATTRIBUTE = "outputAttribute";
+
   /** parameter for source attribute name. */
   private static final String PARAM_VALUES = "valuesToAdd";
+
   private static final String SOURCE_ATT = "source_attribute_name";
  
   private String _outputAttribute;
+
   /** parameter for target attribute name. */
   private Any _values;
+
   private static final String TARGET_ATT = "target_attribute_name";
  
   public void configure(final AnyMap configuration) throws ProcessingException {
+
   /** the pipelet's configuration. */
    _outputAttribute = configuration.getStringValue(PARAM_ATTRIBUTE);
+
  private AnyMap _config;
    _values = configuration.get(PARAM_VALUES);
+
  }
+
  
   public String[] process(Blackboard blackboard, String[] recordIds) throws ProcessingException {
+
  /** local logger. */
     if (_outputAttribute != null && _values != null) {
+
  private final Log _log = LogFactory.getLog(getClass());
 +
 
 +
  /** {@inheritDoc} */
 +
  @Override
 +
   public String[] process(final Blackboard blackboard, final String[] recordIds) throws ProcessingException {
 +
     final ParameterAccessor paramAccessor = new ParameterAccessor(blackboard, _config);
 +
    final ResultCollector resultCollector =
 +
      new ResultCollector(paramAccessor, _log, ProcessingConstants.DROP_ON_ERROR_DEFAULT);
 +
    for (final String id : recordIds) {
 
       try {
 
       try {
         for (final String id : recordIds) {
+
         paramAccessor.setCurrentRecord(id);
          for (final Any value : _values) {
+
        String inValue = "";
            blackboard.getMetadata(id).add(_outputAttribute, value);
+
        String outValue = "";
           }
+
        // get parameter either from record or configuration via parameter accessor.
 +
        final String sourceAttr = paramAccessor.getRequiredParameter(SOURCE_ATT);
 +
        final String targetAttr = paramAccessor.getRequiredParameter(TARGET_ATT);
 +
 
 +
        if (blackboard.getMetadata(id).containsKey(sourceAttr)) {
 +
           inValue = blackboard.getMetadata(id).getStringValue(sourceAttr);
 
         }
 
         }
       } catch (final Exception ex) {
+
 
         throw new ProcessingException(ex);
+
        outValue = inValue + " --- Hello world!!!";
 +
 
 +
        final Value outLiteral = blackboard.getDataFactory().createStringValue(outValue);
 +
        blackboard.getMetadata(id).put(targetAttr, outLiteral);
 +
        resultCollector.addResult(id);
 +
       } catch (final Exception e) {
 +
         resultCollector.addFailedResult(id, e);
 
       }
 
       }
 
     }
 
     }
     return recordIds;
+
     return resultCollector.getResultIds();
 +
  }
 +
 
 +
  /** {@inheritDoc} */
 +
  @Override
 +
  public void configure(final AnyMap config) throws ProcessingException {
 +
    _config = config;
 
   }
 
   }
 
}
 
}

Revision as of 10:27, 14 September 2011

This page describes how to implement and configure your own pipelet in case you wish to add functionality to SMILA.

What are pipelets?

Pipelets are not standalone services, but their lifecycle and configuration is managed by the workflow engine. Each occurrence of a pipelet in a workflow uses a different pipelet instance. For more information take a look at Pipelets.

Before writing your own pipelet we recommend you to take a look at the HelloWorldPipelet. This pipelet is an example of a very simple processing pipelet and can be used as a template for your pipelets.

Implementation

Follow these instructions to implement a pipelet in SMILA:

  • If needed, create a new plugin project. You can add multiple pipelets to a single project. See [1] for details.
  • In the MANIFEST.MF, add at least these as "Imported Packages" (of course, you will need more to develop your pipelet, depending on what you want to do):
    • org.eclipse.smila.blackboard
    • org.eclipse.smila.datamodel
    • org.eclipse.smila.processing
  • Create a class that implements the interface org.eclipse.smila.processing.Pipelet and make sure that the class has a public no-argument constructor.
  • Implement void configure(AnyMap configuration). This method is called prior to process. Here you can read the configuration provided for the pipelet in the pipeline. To share those properties either store the whole configuration in a member variable or better check the configuration for validity and completeness and store the settings in separate member variables.
  • Implement String[] process(Blackboard blackboard, String[] recordIds). Here you have to place the "business logic" of your pipelet. In most cases the result is the same as the input recordIDs, so just return it. But it is possible to return another list of IDs as result.
  • Register your class in META-INF/MANIFEST.MF of the providing bundle using the header name "SMILA-Pipelets". Then they can be detected by the PipeletTracker service. If you would like to register multiple classes, separate them with commas.
  • Consider thread-safe-ness. Because pipelets may be accessed by multiple threads, make sure that access to member variables (e.g. the configuration) is read-only. For best practices: use local variables instead of member variables if possible.

Configuration

If your pipelet requires a configuration:

  • Add a <configuration> element to the <extensionActivity> section of your pipelet in the BPEL pipeline.

Examples

Pipelet Usage

This is a template for MyPipelet.java:

package org.eclipse.smila.mypackage

import org.eclipse.smila.blackboard.Blackboard;
import org.eclipse.smila.processing.ProcessingException;
import org.eclipse.smila.processing.Pipelet;
import org.eclipse.smila.datamodel.AnyMap;
 
public class MyPipelet implements Pipelet {
 
  public void configure(AnyMap configuration) throws ProcessingException {
    // read the configuration properties
  }
 
  public String[] process(Blackboard blackboard, String[] recordIds) throws ProcessingException {
    // process the records and create a result
  }
}

And this is how to register the pipelet class in the bundle's manifest MANIFEST.MF:

...
SMILA-Pipelets: org.eclipse.smila.mypackage.MyPipelet
...

And finally, this is a sample showing how a pipelet is invoked in the BPEL pipeline using an <extensionActivity>. It also shows how the pipelet is configured using a <configuration>.

...
<extensionActivity>
    <proc:invokePipelet name="invokeMyPipelet">
        <proc:pipelet class="org.eclipse.smila.mypackage.MyPipelet" />
        <proc:variables input="request" output="request" />
        <proc:configuration>
            <rec:Val key="aStringParam">some value</rec:Val>
            <rec:Val key="aDateParam" type="datetime">2008-06-11T16:08:00.000+0200</rec:Val>
        </proc:configuration>       
    </proc:invokePipelet>
</extensionActivity>
...

Piplet configuration usage

The following example shows the usage of multiple values for properties:

...
<extensionActivity>
  <proc:invokePipelet name="addValuesToNonExistingAttribute">
    <proc:pipelet class="org.eclipse.smila.processing.pipelets.AddValuesPipelet" />
    <proc:variables input="request" output="request"/>
    <proc:configuration>
      <rec:Val key="outputAttribute">out</rec:Val>
      <rec:Seq key="valuesToAdd">
        <rec:Val>value1</rec:Val>
        <rec:Val>value2</rec:Val>
      </rec:Seq>
    </proc:configuration>
  </proc:invokePipelet>
</extensionActivity>
...
public class AddValuesPipelet implements Pipelet {
  /** parameter for source attribute name. */
  private static final String SOURCE_ATT = "source_attribute_name";
 
  /** parameter for target attribute name. */
  private static final String TARGET_ATT = "target_attribute_name";
 
  /** the pipelet's configuration. */
  private AnyMap _config;
 
  /** local logger. */
  private final Log _log = LogFactory.getLog(getClass());
 
  /** {@inheritDoc} */
  @Override
  public String[] process(final Blackboard blackboard, final String[] recordIds) throws ProcessingException {
    final ParameterAccessor paramAccessor = new ParameterAccessor(blackboard, _config);
    final ResultCollector resultCollector =
      new ResultCollector(paramAccessor, _log, ProcessingConstants.DROP_ON_ERROR_DEFAULT);
    for (final String id : recordIds) {
      try {
        paramAccessor.setCurrentRecord(id);
        String inValue = "";
        String outValue = "";
        // get parameter either from record or configuration via parameter accessor.
        final String sourceAttr = paramAccessor.getRequiredParameter(SOURCE_ATT);
        final String targetAttr = paramAccessor.getRequiredParameter(TARGET_ATT);
 
        if (blackboard.getMetadata(id).containsKey(sourceAttr)) {
          inValue = blackboard.getMetadata(id).getStringValue(sourceAttr);
        }
 
        outValue = inValue + " --- Hello world!!!";
 
        final Value outLiteral = blackboard.getDataFactory().createStringValue(outValue);
        blackboard.getMetadata(id).put(targetAttr, outLiteral);
        resultCollector.addResult(id);
      } catch (final Exception e) {
        resultCollector.addFailedResult(id, e);
      }
    }
    return resultCollector.getResultIds();
  }
 
  /** {@inheritDoc} */
  @Override
  public void configure(final AnyMap config) throws ProcessingException {
    _config = config;
  }
}

Back to the top