Skip to main content
Jump to: navigation, search

Difference between revisions of "SMILA/Development Guidelines/How to write a ProcessingService"

(Implementation (as DeclarativeService): some clarifications)
(Replacing page with '= '''Processing Services have been removed, please use [[SMILA/Documentation/Pipelets| Pipelets] instead!''' = <br>')
Line 1: Line 1:
This page describes how to implement and configure your own [[SMILA/Glossary#P|processing service]] in case you wish to [[SMILA/Howto_integrate_a_component_in_SMILA|add functionality]] to SMILA.
+
= '''Processing Services have been removed, please use [[SMILA/Documentation/Pipelets| Pipelets] instead!''' =
  
== What are processing services? ==
+
<br>
In contrast to [[SMILA/Glossary#P|pipelets]] processing services are not instantiated and configured by the workflow engine, but are started as OSGi services (preferably by declarative services) independently from the workflow engine. They can read their configuration from wherever they want. Their service registration must have a property named <tt>smila.processing.service.name</tt> that specifies the name with which the service is referenced by the workflow engine. For more information  take a look at [[SMILA/Documentation/Pipelets_and_ProcessingServices| Pipelets and ProcessingServices]].
+
 
+
 
+
== Implementation (as <tt>DeclarativeService</tt>) ==
+
Follow these instructions to implement a processing service in SMILA:
+
* Create a class that implements the interface <tt>org.eclipse.smila.processing.ProcessingService</tt> and register it at least with that interface in the ORGi runtime. Note, that your processing service is free to implement additional interfaces.
+
 
+
* Follow the instructions and rules for implementing [[SMILA/Development Guidelines/Declarative Services|DeclarativeService]].
+
 
+
* Implement <tt>Id[] process(Blackboard blackboard, Id[] recordIds)</tt>. Here you have to place the "business logic" of your processing service. 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.
+
 
+
* As with regular DeclarativeServices, you have to specify the service component description(s) in <tt>META-INF/MANIFEST.MF</tt>.
+
 
+
* Add the property ''smila.processing.service.name'' to your service registration file. The name defined here is referenced in the invocation of the pipeline (e.g. <tt><proc:service name="recordTracker" /></tt>) and thus the key to look up the service by the workflow egine. It makes sense that the DS component name and this property are equal, but that is not a must.
+
 
+
* Consider thread-safeness. As processing services are often accessed by multiple threads make sure that the 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 processing service needs configurable settings, you are free to use any configuration you like (XML configuration files, property files, etc.) A good place to read configuration settings is the <tt>activate()</tt> method. But it is also possible to read the configuration in the <tt>process()</tt> method. Configuration files are usually located within the global configuration folder in a subfolder that equals the name of your bundle (e.g. <tt>org.eclipse.smila.mypackage</tt>). If your processing service only needs some simple configuration settings it is possible to use the same format used by pipelets but put the configuration inside a separate configuration file. Therefore you can use <tt>org.eclipse.smila.utils.config.ConfigUtils</tt> and <tt>org.eclipse.smila.processing.configuration.PipeletConfigurationLoader</tt>.
+
 
+
Here is a code sample showing how to use it in your processing service:
+
 
+
<source lang="java">
+
  private PipeletConfiguration readConfiguration(String bundleName, String configFileName) throws Exception {
+
    InputStream configurationFileStream = null;
+
    try {
+
      configurationFileStream = ConfigUtils.getConfigStream(bundleName, configFileName);
+
      final Unmarshaller unmarshaller = PipeletConfigurationLoader.createPipeletConfigurationUnmarshaller();
+
      return = (PipeletConfiguration) unmarshaller.unmarshal(configurationFileStream);
+
    } catch (final Exception ex) {
+
      throw new Exception("Could not read configuration property file " + configFileName, ex);
+
    } finally {
+
      IOUtils.closeQuietly(configurationFileStream);
+
    }
+
  }
+
</source>
+
 
+
== Example ==
+
 
+
A template for a <tt>MyService</tt> class:
+
 
+
<source lang="java">
+
package org.eclipse.smila.mypackage
+
 
+
import org.eclipse.smila.blackboard.Blackboard;
+
import org.eclipse.smila.datamodel.id.Id;
+
import org.eclipse.smila.processing.ProcessingException;
+
import org.eclipse.smila.processing.ProcessingService;
+
import org.osgi.service.component.ComponentContext;
+
 
+
public class MyService implements ProcessingService {
+
 
+
  protected void activate(ComponentContext) {
+
    // add any initialization code here
+
    // e.g. reading of configuration files
+
  }
+
 
+
  protected void deactivate(ComponentContext) {
+
    // add any clean up code here
+
  }
+
 
+
  public Id[] process(Blackboard blackboard, Id[] recordIds) throws ProcessingException {
+
    // process the recordIds and create a result
+
  }
+
}
+
</source>
+
 
+
Register the DS component description in the bundle manifest:
+
 
+
<pre>
+
...
+
Service-Component: OSGI-INF/myservice.xml
+
...
+
</pre>
+
 
+
A template for the component description:
+
 
+
<source lang="xml">
+
<?xml version="1.0" encoding="UTF-8"?>
+
<component name="MyService" immediate="true">
+
    <implementation class="org.eclipse.smila.mypackage.MyService" />
+
    <service>
+
        <provide interface="org.eclipse.smila.processing.ProcessingService"/>       
+
    </service>
+
    <property name="smila.processing.service.name" value="MyService"/>
+
</component>
+
</source>
+
 
+
== Useful Information ==
+
If your service also implements an interface besides <tt>org.eclipse.smila.processing.ProcessingService</tt> and you want to be able to use the service outside of the workflow in any other class, simply provide another service interface:
+
<source lang="xml">
+
...
+
    <service>
+
        <provide interface="org.eclipse.smila.processing.ProcessingService"/>       
+
        <provide interface="org.eclipse.smila.mypackage.MyServiceInterface"/>       
+
    </service>
+
...
+
</source>
+
 
+
See  <tt>org.eclipse.smila.processing.pipelets.aperture.ApertureMimeTypeIdentifier</tt> for an example.
+
{info}
+
 
+
[[Category:SMILA]]
+

Revision as of 09:45, 20 April 2011

Processing Services have been removed, please use [[SMILA/Documentation/Pipelets| Pipelets] instead!


Back to the top