Difference between revisions of "SMILA/Documentation/HowTo/How to integrate the HelloWorld webservice as a Pipelet"

From Eclipsepedia

Jump to: navigation, search
(General review on content and style)
(General review on content and style)
Line 1: Line 1:
This page illustrates all steps that need to be performed in order to integrate the HelloWorld web service as a pipelet in SMILA.
+
This page illustrates all steps that need to be performed in order to integrate the HelloWorld web service as a [[SMILA/Glossary#P|pipelet]] in SMILA. For general information on how to integrate components and add functionality to SMILA refer to [[SMILA/Howto_integrate_a_component_in_SMILA| How to integrate a component in SMILA]].
  
 
== Preparations ==
 
== Preparations ==
Line 5: Line 5:
 
It may be helpful to first take a look at the SMILA [[SMILA/Development_Guidelines|Development guidelines]] as many topics that are beyond the scope of this tutorial are illustrated there.
 
It may be helpful to first take a look at the SMILA [[SMILA/Development_Guidelines|Development guidelines]] as many topics that are beyond the scope of this tutorial are illustrated there.
  
=== Create a new bundle ===
+
=== Create new bundle ===
  
 
* Create a new bundle that should contain your pipelet. Follow the instructions on [[SMILA/Development_Guidelines/Create_a_bundle_%28plug-in%29|How to create a bundle]] and use the following settings:
 
* Create a new bundle that should contain your pipelet. Follow the instructions on [[SMILA/Development_Guidelines/Create_a_bundle_%28plug-in%29|How to create a bundle]] and use the following settings:
Line 27: Line 27:
 
  org.eclipse.smila.processing.configuration;version="0.5.0"
 
  org.eclipse.smila.processing.configuration;version="0.5.0"
 
</pre>
 
</pre>
* To make sure that the PipeletTrackerService detects your new pipelet, add the the following line to the file <tt>META-INF/MANIFEST.MF</tt>. This registers the class that will implement your SMILA pipelet:
+
* To make sure that the <tt>PipeletTrackerService</tt> detects your new pipelet, add the following line to the file <tt>META-INF/MANIFEST.MF</tt>. This registers the class that will implement your SMILA pipelet:
 
<pre>
 
<pre>
 
SMILA-Pipelets: org.eclipse.smila.sample.pipelet.HelloWorldPipelet
 
SMILA-Pipelets: org.eclipse.smila.sample.pipelet.HelloWorldPipelet
Line 33: Line 33:
  
 
=== Create Java classes from WSDL ===
 
=== Create Java classes from WSDL ===
comming soon ...
+
coming soon ...
  
 
== Implementation ==
 
== Implementation ==
  
* create a package <tt>org.eclipse.smila.sample.pipelet</tt> and a Java class <tt>HelloWorldPipelet</tt>
+
* Create the package <tt>org.eclipse.smila.sample.pipelet</tt> and the Java class <tt>HelloWorldPipelet</tt>.
* use the following code as a template for your new class. It contains empty method bodies and a reference to the logger. The comments are successively replaced with code snippets in the following sections. For your convenience you may also download the complete zipped source file [[Media:HelloWorldPipelet.zip|HelloWorldPipelet.zip]].
+
* Use the following code as a template for your new class. It contains empty method bodies and a reference to the logger. In the following we are going to gradually replace the comments in this file by the corresponding code snippets. For your convenience you may also download the complete zipped source file from [[Media:HelloWorldPipelet.zip|HelloWorldPipelet.zip]].
 +
 
 
<source lang="Java">
 
<source lang="Java">
 
package org.eclipse.smila.sample.pipelet
 
package org.eclipse.smila.sample.pipelet
Line 70: Line 71:
 
}
 
}
 
</source>
 
</source>
 
  
 
=== Read PipeletConfiguration ===
 
=== Read PipeletConfiguration ===
* first let's create two member variables that store the names of the in- and output Attributes as well as String constants for the property names used in the configuration. Replace the comment "<tt>// additional member variables </tt>" with the following code snippet.
+
* First let's create two member variables that store the names of the input and output attributes as well as string constants for the property names used in the configuration. Replace the comment "<tt>// additional member variables </tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
 
private final String PROP_IN_ATT_NAME= "IN_ATT_NAME";
 
private final String PROP_IN_ATT_NAME= "IN_ATT_NAME";
Line 82: Line 82:
 
</source>
 
</source>
  
* then we will fill those members with the Attribute names provided by the PipeletConfiguration in method <tt>configure(PipeletConfiguration configuration)</tt>. The method <tt>getPropertyFirstValueNotNull(String)</tt> will check that the value of the property is not null. If it is null a <tt>ProcessingException</tt> will be thrown. In addition we should ensure, that the provided String is not empty or consists only of whitespaces. Replace the comment "<tt>// read the configuration properties</tt>" with the following code snippet.
+
* Then we are going to fill those members with the attribute names provided by the <tt>PipeletConfiguration</tt> in method <tt>configure(PipeletConfiguration configuration)</tt>. The method <tt>getPropertyFirstValueNotNull(String)</tt> will check that the value of the property is not null. If it is null a <tt>ProcessingException</tt> will be thrown. In addition we should ensure, that the provided string is not empty or consists of whitespaces only. Replace the comment "<tt>// read the configuration properties</tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
 
_inAttName = (String) configuration.getPropertyFirstValueNotNull(PROP_IN_ATT_NAME);
 
_inAttName = (String) configuration.getPropertyFirstValueNotNull(PROP_IN_ATT_NAME);
Line 94: Line 94:
 
}
 
}
 
</source>
 
</source>
'''Note''': Of course it is also possible to store the PipeletConfiguration in a member variable and access the properties as needed in the <tt>process(BlackboardService blackboard, Id[] recordIds)</tt> method.
+
'''Note''': Of course it is also possible to store the <tt>PipeletConfiguration</tt> in a member variable and access the properties as needed in the <tt>process(BlackboardService blackboard, Id[] recordIds)</tt> method.
  
=== Processing of IDs and exception handling ===
+
=== Process IDs and implement exception handling ===
The method <tt> process(BlackboardService blackboard, Id[] recordIds)</tt> has two parameters:
+
The method <tt>process(BlackboardService blackboard, Id[] recordIds)</tt> has two parameters:
* a reference to the BlackboardService that allows access on Records
+
* a reference to the [[SMILA/Glossary#B|blackboard service]] that allows access on [[SMILA/Glossary#R|records]] and
* a list of Record IDs to process
+
* a list of record IDs to process.
The HelloWorldPipelet should therefor iterate over the IDs in parameter <tt>recordIds</tt>, get the required data from the Record identified by the ID, process this data and store the Result in the Record. Let's place a <tt>try ... catch()</tt> block in the for loop to ensure that errors do only interrupt the processing of the current ID. The comments in the code serve as placeholders for the functionality described in the following sections. At the end we return the unmodified input parameter <tt>recordIds</tt> as the result of the Pipelet. Replace the comment "<tt>// process the recordIds and create a result</tt>" with the following code snippet.
+
The HelloWorld pipelet should therefore iterate over the IDs in the parameter <tt>recordIds</tt>, get the required data from the record identified by the ID, process this data, and store the result in the record. Let's place a <tt>try ... catch()</tt> block in the <tt>for</tt> loop to ensure that errors do only interrupt the processing of the current ID. The comments in the code serve as placeholders for the functionality described in the following sections. At the end we return the unmodified input parameter <tt>recordIds</tt> as the result of the pipelet. Replace the comment "<tt>// process the recordIds and create a result</tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
 
for (Id id : recordIds) {
 
for (Id id : recordIds) {
Line 119: Line 119:
 
return recordIds;
 
return recordIds;
 
</source>
 
</source>
 +
'''Note''': Most of the time the return value of a pipelet is the unmodified input parameter <tt>recordIds</tt>. However, in some cases a pipelet may filter record IDs or even create new records. Then the return value has to be adopted appropriately.
  
'''Note''': Most of the time the return value of a Pipelet is the unmodified input parameter <tt>recordIds</tt>. However, in some cases a Pipelet may filter Record IDs or even create new Records. Then the return value has to be adopted appropriately.
+
=== Read input data ===
 
+
Now we want to read the data of the attribute with the name stored in <tt>_inAttName</tt>. Therefore we first have to create a <tt>Path</tt> object with the attribute's name. Before accessing the literal value we check if the record contains an attribute with the given <tt>Path</tt>. In this tutorial we know that the value of the attribute is a string value, so we directly access the value by calling the method <tt>getStringValue()</tt>.
 
+
=== Read Input Data ===
+
Now we want to read the data of the Attribute with the name stored in <tt>_inAttName</tt>. Therefore we first have to create a <tt>Path</tt> object with the Attribute's name. Before accessing the literal value we check if the Record contains a Attribute with the given Path. In this Tutorial we know that the value of the Attribute is a String value, so we directly access the value by calling the method<tt>getStringValue()</tt>.
+
 
Replace the comment "<tt>// Read Input Data</tt>" with the following code snippet.
 
Replace the comment "<tt>// Read Input Data</tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
Line 133: Line 131:
 
}
 
}
 
</source>
 
</source>
'''Note''': The accessing of Attribute values can be done more generic. Therefore you have to check what DataType a certain Literal contains using method <tt>getDataType()</tt>. Then you can use the appropriate getter method to access thee raw data.
+
'''Note''': Accessing attribute values can be achieved more generically. Therefore you have to check what data type a certain literal contains using the method <tt>getDataType()</tt>. Then you can use the appropriate getter method to access the raw data.
  
=== Process Input Data ===
+
=== Process input data ===
At this point the HelloWorld webservice should be called with parameter <tt>inputValue</tt> and storing the result in variable <tt>outputValue</tt>, using the classes generated from WSDL.<br/>
+
At this point the HelloWorld web service should be called with the parameter <tt>inputValue</tt> and the result should be stored in the variable <tt>outputValue</tt>, using the classes generated from WSDL.<br/>
Until this tutorial description is complete simply assign the content of variable <tt>inputValue</tt> to variable <tt>outputValue</tt> and append a constant string value. Replace the comment "<tt>// Process Input Data</tt>" with the following code snippet.
+
Until this tutorial description is complete, simply assign the content of the variable <tt>inputValue</tt> to variable <tt>outputValue</tt> and append a constant string value. Replace the comment "<tt>// Process Input Data</tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
 
     String outputValue = inputValue + " modified by HelloWorldPipelet";
 
     String outputValue = inputValue + " modified by HelloWorldPipelet";
 
</source>
 
</source>
  
=== Write Output Data ===
+
=== Write output data ===
Finally we want to store the content of variable <tt>outputValue</tt> in the Record Attribute with the name contained in variable <tt>_outAttName</tt>. Therefore we have to create a new Literal object and set it's value. Then we only need to set this Literal for the current ID on the Blackboard.
+
Finally, we want to store the content of the variable <tt>outputValue</tt> in the record attribute with the name contained in variable <tt>_outAttName</tt>. Therefore we have to create a new <tt>Literal</tt> object and set its value. Then we only need to set this <tt>Literal</tt> for the current ID on the black board.
 
Replace the comment "<tt>// Write Output Data</tt>" with the following code snippet.
 
Replace the comment "<tt>// Write Output Data</tt>" with the following code snippet.
 
<source lang="Java">
 
<source lang="Java">
Line 150: Line 148:
 
blackboard.setLiteral(id, new Path(_outAttName), literal);
 
blackboard.setLiteral(id, new Path(_outAttName), literal);
 
</source>
 
</source>
'''Note''': The method <tt>commit(Id)</tt> of the BlackboardService does not need to be called in every Pipelet. It is automatically called at the end of the Pipeline.
+
'''Note''': The method <tt>commit(Id)</tt> of the blackboard service does not need to be called in each pipelet as it is automatically called at the end of the [[SMILA/Glossary/#p|pipeline]].
 
+
  
== Configuration and Invocation in BPEL ==
+
== Configuration and invocation in BPEL ==
In this tutorial we will integrate the HelloWorldPipelet in the SMILA indexing process just before the Record is stored in the Lucene index. With this configuration the input for the HelloWorldPipelet will be read from Attribute ''Title'' and the modified output will be stored in the same Attribute, overwriting the previous value.
+
In this tutorial we will integrate the HelloWorld pipelet in the SMILA indexing process just before the record is stored in the Lucene index. With this configuration the input for the HelloWorld pipelet will be read from attribute ''Title'' and the modified output will be stored in the same attribute, overwriting the previous value.
* edit file configuration\org.eclipse.smila.processing.bpel\pipelines\addpipeline.bpel and add the following right between <tt><extensionActivity name="convertDocument"></tt> and <tt><extensionActivity name="invokeLuceneService"></tt>
+
* Edit the file <tt>configuration\org.eclipse.smila.processing.bpel\pipelines\addpipeline.bpel</tt> and add the following right between the <tt><extensionActivity name="convertDocument"></tt> and the <tt><extensionActivity name="invokeLuceneService"></tt> section.
 
<source lang="XML">
 
<source lang="XML">
 
<extensionActivity name="invokeHelloWorldPipelet">
 
<extensionActivity name="invokeHelloWorldPipelet">
Line 173: Line 170:
 
</source>
 
</source>
  
== Test your Pipelet ==
+
== Test your pipelet ==
comming soon ...
+
coming soon ...
  
 
[[Category:SMILA]]
 
[[Category:SMILA]]

Revision as of 08:00, 6 October 2008

This page illustrates all steps that need to be performed in order to integrate the HelloWorld web service as a pipelet in SMILA. For general information on how to integrate components and add functionality to SMILA refer to How to integrate a component in SMILA.

Contents

Preparations

It may be helpful to first take a look at the SMILA Development guidelines as many topics that are beyond the scope of this tutorial are illustrated there.

Create new bundle

  • Create a new bundle that should contain your pipelet. Follow the instructions on How to create a bundle and use the following settings:
Project name: org.eclipse.smila.sample.pipelet
Plug-in ID: org.eclipse.smila.sample.pipelet
Plug-in Version: 1.0.0
Plug-in Name: Sample Pipelet Bundle
Plug-in Provider: your name or company
  • Then integrate your new bundle into the SMILA build process. Refer to the instructions on How to integrate a new bundle into build process for details.
  • Edit the file META-INF/MANIFEST.MF and add the following import-package dependencies as those are required to implement the basic functionalities of your pipelet:
Import-Package: org.apache.commons.logging;version="1.1.1",
 org.eclipse.smila.blackboard;version="0.5.0",
 org.eclipse.smila.blackboard.path;version="0.5.0",
 org.eclipse.smila.datamodel.id;version="0.5.0",
 org.eclipse.smila.datamodel.record;version="0.5.0",
 org.eclipse.smila.processing;version="0.5.0",
 org.eclipse.smila.processing;version="0.5.0",
 org.eclipse.smila.processing.configuration;version="0.5.0"
  • To make sure that the PipeletTrackerService detects your new pipelet, add the following line to the file META-INF/MANIFEST.MF. This registers the class that will implement your SMILA pipelet:
SMILA-Pipelets: org.eclipse.smila.sample.pipelet.HelloWorldPipelet

Create Java classes from WSDL

coming soon ...

Implementation

  • Create the package org.eclipse.smila.sample.pipelet and the Java class HelloWorldPipelet.
  • Use the following code as a template for your new class. It contains empty method bodies and a reference to the logger. In the following we are going to gradually replace the comments in this file by the corresponding code snippets. For your convenience you may also download the complete zipped source file from HelloWorldPipelet.zip.
package org.eclipse.smila.sample.pipelet
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.smila.blackboard.BlackboardService;
import org.eclipse.smila.blackboard.path.Path;
import org.eclipse.smila.datamodel.id.Id;
import org.eclipse.smila.datamodel.record.Literal;
import org.eclipse.smila.datamodel.record.RecordFactory;
import org.eclipse.smila.processing.ProcessingException;
import org.eclipse.smila.processing.SimplePipelet;
import org.eclipse.smila.processing.configuration.PipeletConfiguration;
 
public class HelloWorldPipelet implements SimplePipelet {
 
  // additional member variables 
  private final Log _log = LogFactory.getLog(HelloWorldPipelet.class);
 
  public HelloWorldPipelet(){
  }
 
  public void configure(PipeletConfiguration configuration) throws ProcessingException {
    // read the configuration properties
  }
 
  public Id[] process(BlackboardService blackboard, Id[] recordIds) throws ProcessingException {
    // process the recordIds and create a result
  }
}

Read PipeletConfiguration

  • First let's create two member variables that store the names of the input and output attributes as well as string constants for the property names used in the configuration. Replace the comment "// additional member variables " with the following code snippet.
private final String PROP_IN_ATT_NAME= "IN_ATT_NAME";
private final String PROP_OUT_ATT_NAME= "OUT_ATT_NAME";
 
private String _inAttName;
private String _outAttName;
  • Then we are going to fill those members with the attribute names provided by the PipeletConfiguration in method configure(PipeletConfiguration configuration). The method getPropertyFirstValueNotNull(String) will check that the value of the property is not null. If it is null a ProcessingException will be thrown. In addition we should ensure, that the provided string is not empty or consists of whitespaces only. Replace the comment "// read the configuration properties" with the following code snippet.
_inAttName = (String) configuration.getPropertyFirstValueNotNull(PROP_IN_ATT_NAME);
if (_inAttName.trim().length() == 0) {
    throw new ProcessingException("Property " + PROP_IN_ATT_NAME + " must not be an empty String");
}
 
_outAttName = (String) configuration.getPropertyFirstValueNotNull(PROP_OUT_ATT_NAME);
if (_outAttName.trim().length() == 0) {
    throw new ProcessingException("Property " + PROP_OUT_ATT_NAME + " must not be an empty String");
}

Note: Of course it is also possible to store the PipeletConfiguration in a member variable and access the properties as needed in the process(BlackboardService blackboard, Id[] recordIds) method.

Process IDs and implement exception handling

The method process(BlackboardService blackboard, Id[] recordIds) has two parameters:

The HelloWorld pipelet should therefore iterate over the IDs in the parameter recordIds, get the required data from the record identified by the ID, process this data, and store the result in the record. Let's place a try ... catch() block in the for loop to ensure that errors do only interrupt the processing of the current ID. The comments in the code serve as placeholders for the functionality described in the following sections. At the end we return the unmodified input parameter recordIds as the result of the pipelet. Replace the comment "// process the recordIds and create a result" with the following code snippet.

for (Id id : recordIds) {
    try {
        // Read Input Data
 
        // Process Input Data
 
        // Write Output Data
 
    } catch (final Exception ex) {
        if (_log.isErrorEnabled()) {
            _log.error("error during execution of HelloWorldPipelet with record " + id, ex);
        }
    }
} // for
 
return recordIds;

Note: Most of the time the return value of a pipelet is the unmodified input parameter recordIds. However, in some cases a pipelet may filter record IDs or even create new records. Then the return value has to be adopted appropriately.

Read input data

Now we want to read the data of the attribute with the name stored in _inAttName. Therefore we first have to create a Path object with the attribute's name. Before accessing the literal value we check if the record contains an attribute with the given Path. In this tutorial we know that the value of the attribute is a string value, so we directly access the value by calling the method getStringValue(). Replace the comment "// Read Input Data" with the following code snippet.

String inputValue = "";
final Path path = new Path(_inAttName);
if (blackboard.hasAttribute(id, path)) {
  inputValue = blackboard.getLiteral(id, path).getStringValue();
}

Note: Accessing attribute values can be achieved more generically. Therefore you have to check what data type a certain literal contains using the method getDataType(). Then you can use the appropriate getter method to access the raw data.

Process input data

At this point the HelloWorld web service should be called with the parameter inputValue and the result should be stored in the variable outputValue, using the classes generated from WSDL.
Until this tutorial description is complete, simply assign the content of the variable inputValue to variable outputValue and append a constant string value. Replace the comment "// Process Input Data" with the following code snippet.

    String outputValue = inputValue + " modified by HelloWorldPipelet";

Write output data

Finally, we want to store the content of the variable outputValue in the record attribute with the name contained in variable _outAttName. Therefore we have to create a new Literal object and set its value. Then we only need to set this Literal for the current ID on the black board. Replace the comment "// Write Output Data" with the following code snippet.

final Literal literal = RecordFactory.DEFAULT_INSTANCE.createLiteral();
literal.setStringValue(outputValue);
blackboard.setLiteral(id, new Path(_outAttName), literal);

Note: The method commit(Id) of the blackboard service does not need to be called in each pipelet as it is automatically called at the end of the pipeline.

Configuration and invocation in BPEL

In this tutorial we will integrate the HelloWorld pipelet in the SMILA indexing process just before the record is stored in the Lucene index. With this configuration the input for the HelloWorld pipelet will be read from attribute Title and the modified output will be stored in the same attribute, overwriting the previous value.

  • Edit the file configuration\org.eclipse.smila.processing.bpel\pipelines\addpipeline.bpel and add the following right between the <extensionActivity name="convertDocument"> and the <extensionActivity name="invokeLuceneService"> section.
<extensionActivity name="invokeHelloWorldPipelet">
    <proc:invokePipelet>
        <proc:pipelet class="org.eclipse.smila.sample.pipelet.HelloWorldPipelet" />
        <proc:variables input="request" output="request" />
        <proc:PipeletConfiguration>
            <proc:Property name="IN_ATT_NAME">
                <proc:Value>Title</proc:Value>
            </proc:Property>
            <proc:Property name="OUT_ATT_NAME">
                <proc:Value>Title</proc:Value>
            </proc:Property>
        </proc:PipeletConfiguration>       
    </proc:invokePipelet>
</extensionActivity>

Test your pipelet

coming soon ...