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/Development Guidelines/How to write a ProcessingService"

 
(9 intermediate revisions by 5 users not shown)
Line 1: Line 1:
== What are ProcessingServices ==
+
{{Note|Deprecated:
 
+
Processing Services have been removed, please refer to [[SMILA/Documentation/Pipelets|pipelets]] instead!}}
In contrast to "Pipelets" ProcessingService 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 "smila.processing.service.name" that specifies the name with which the service is references by the workflow engine.
+
 
+
 
+
== Implementation (as DeclarativeService) ==
+
 
+
* Create a class that implements interface <tt>org.eclipse.smila.processing.ProcessingService</tt>.
+
** Note: your ProcessingService is free to implement additional interfaces
+
 
+
* Follow the rules for implementing DeclarativeServices: [[SMILA/Development Guidelines/Declarative Services]]
+
 
+
* Implement <tt>Id[] process(BlackboardService blackboard, Id[] recordIds)</tt>. Here you have to place the "business logic" of your ProcessingService. 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 META-INF/MANIFEST.MF
+
 
+
* Add property "smila.processing.service.name" to your service registration file
+
 
+
* Thread-safe: as ProcessingServices are often accessed by multiple threads make sure that access to member variables (e.g. the configuration) is read only.
+
** Best Practice: use local variables instead of memeber variables if possible
+
 
+
 
+
== Configuration ==
+
If your ProcessingService needs configurable settings you are free to use any configuration you like (XML config 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. If your ProcessingService only needs some simple configuration settings it is possible to use the same format used by Pipelets but put the configuration inside a seperate configuration file. Therfore you can use org.eclipse.smila.utils.config.ConfigUtils and org.eclipse.smila.processing.configuration.PipeletConfigurationLoader.
+
 
+
Here is a code sample of how to use it in your ProcessingService:
+
 
+
<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 MyService class:
+
 
+
<source lang="java">
+
package org.eclipse.smila.mypackage
+
 
+
import org.eclipse.smila.blackboard.BlackboardService;
+
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(BlackboardService 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, just 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]]
+

Latest revision as of 07:03, 19 January 2012

Note.png
Deprecated: Processing Services have been removed, please refer to pipelets instead!

Back to the top