1. Developing a new Component

1.1. Component Bundle Setup

An RCE component usually consists of up to three OSGi bundles: named the execution, gui, and common bundles:

  • Execution: Contains the component's lifecycle.

  • GUI: Contains the user interface to configure the component. If a component does not require a user interface this bundle can be ommitted.

  • Common: Contains code resources which are used by both the execution and the GUI bundle. This bundle is optional, too.

Note that in the context of Eclipse, OSGi bundles are called Plug-In Projects, and can be extended with Eclipse-specific features. In practice, the terms bundle and plugin are often used interchangeably.

1.2. Creating the execution Bundle

To start developing your first component, generate a new Eclipse Plug-In Project by selecting the corresponding item in the menu bar:

Fill in the dialog properties to configure the plug-in project. The name of the new project should match the RCE naming conventions. That means it should start with "de.rcenvironment.components." and end with ".execution"; so the full name of the execution bundle should be "de.rcenvironment.components.<yourcomponentid>.execution", where <yourcomponentid> is the ID of your new component. Change the property "Source folder" to "src/main/java" and "Output folder" to "target". Proceed by clicking "Next >".

Now specify the version of your component; you can choose this freely. The name of this plugin should always be "RCE Components <YourComponentName> Execution" for the execution bundle, where <YourComponentName> again is your component's display name. Press the "Finish" button to complete the general configuration of this plugin.

Eclipse now creates the configured structure of folders, but the plugin is not ready for being used as an RCE component yet.

Create a folder called "resources" in the project you just created. If you have icon files for your component, put them into this folder. Supported formats are PNG, JPG, BMP and GIF. We recommend a resolution of 16×16 and 32×32 pixels. Conventionally these icons are namend "<yourcomponentname>16.png" and "<yourcomponentname>32.png". Also create an "inputs.json", an "outputs.json" and a "configuration.json" file in the resource folder you just created, where you later define the inputs, outputs and configuration of your component.

As a start, the files can contain an empty JSON object as content. So it suffices to enter the following text in these three files:

{ }

Note that the files must be present and must not be empty.

Now create a Java class in your source folder by right-clicking on "src/main/java" in the Eclipse Project Explorer. As this will be the central class of your component, give it a name like "<YourComponentName>Component.java" (<YourComponentName> is your component's display name in camel case, and then add "Component.java"). This Java class must extend de.rcenvironment.core.component.model.spi.DefaultComponent.

To implement the functionality of your component override the according methods. The most basic methods to be overriden are:

  • processInput: Is called whenever the component receives a new input. In loops this method is called multiple times.

  • start: Is called at component start once. Initializations can be placed here.

  • dispose: Is called when the component disposes. Clean up methods can be placed here to release resources.

Now create a folder called "OSGI-INF" in your project folder, by using the standard Eclipse function (File->New->Folder). This folder will contain all OSGi service definitions for your project. One way to create an OSGi service definition is creating a file "<yourComponentName>.xml" ("<yourComponentName>" is your own component's display name again) and copying the following source code into it. Replace all occurences of "<yourComponentName>" with the display name of your component, and all occurences of "<yourcomponentname>" with its id:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
	factory="de.rcenvironment.rce.component" name="<yourcomponentname>">
	<implementation class="de.rcenvironment.components.<yourcomponentname>.
	execution.<yourComponentName>Component" />
	<service>
		<provide interface="de.rcenvironment.core.component.registration.api.Registerable" />
	</service>
	<property name="rce.component.class" type="String" value="de.rcenvironment.components.
	<yourcomponentname>.execution.<yourComponentName>Component" />
	<property name="rce.component.version" type="String" value="1.0" />
	<property name="rce.component.name" type="String" value="<yourcomponentname>" />
	<property name="rce.component.group" type="String" value="Test" />
	<property name="rce.component.icon-16" type="String" value="/resources/yourcomponentname16.png" />
	<property name="rce.component.icon-32" type="String" value="/resources/yourcomponentname32.png" />
	<property name="rce.component.inputs" type="String" value="/resources/inputs.json" />
	<property name="rce.component.outputs" type="String" value="/resources/outputs.json" />
	<property name="rce.component.configuration" type="String" value="/resources/configuration.json" />
</scr:component>
        

Some of these definitions are optional or refer to elements that do not exist yet. The first lines provide the general XML header, followed by the OSGi root element. The factory attribute is the part that links this definition into the RCE framework. The name attribute defines your component's name when inspected with OSGi tools and should be the same as the rce.component.name property below. The implementation class entry defines the main Java class of the component. The rce.component.group property sets the GUI group in which your component will appear. (Since the component is still under development, something like "Test" is a good choice for now.) The rce.component.icon-16 and rce-component.icon-32 properties are optional and define the icon for your component. The rce.component.inputs, rce.component.outputs and rce.component.configuration attributes define the locations of configuration files that will be described later.

The created plugin project automatically contains a folder named "META-INF". Edit the "MANIFEST.INF" file in this directory by double-clicking it and selecting the "MANIFEST.MF" tab. Add the following lines to it and save:

       
Service-Component: OSGI-INF/*.xml
RCE-Component: true
Export-Package: de.rcenvironment.components.<yourcomponentname>.execution
        

Note that "Export Package: " and the first name have to be in the same line. A second element would be added in the next line with a leading space. Moreover the file must end with a linebreak.

Also note that errors containing "inconsistent hierarchies" can be solved by adding the required referenced packages in the Import-Package property analogous to the Export-Package property.

The first line tells the OSGi framework where to look for the component declaration we created before. The second line declares this plug-in as an RCE component. The last line makes the package of your main class visible to other bundles, which is required so RCE can load and initialized the component.

Next, edit the "build.properties" file in the main folder of your plugin project. This file should always look the same for the execution bundles and can be copied from the sample component. It should look like this:

       
 source.. = src/main/java
 bin.includes = META-INF/,\ 
 OSGI-INF/,\ 
 resources/,\ 
 . 
        

After this step, the plugin configuration is complete. It should look like this in the Eclipse Package Explorer:

When you start RCE from Eclipse and open a workflow file, your component should be shown in the component palette on the right, in the group that you have set in the "OSGI-INF/..." XML file.

1.3. Creating a common Bundle

Generate a new Eclipse Plug-In Project by selecting the same option as in the "execution" bundle section above. The project name should follow the RCE naming conventions, similar to the execution bundle but ending with ".common" instead of ".execution".

Add the Java classes to the source folder, within a package with the same name as the bundle's name (or sub-packages of it). For holding shared constants, the usual convention is a Java class named "<YourComponentName>ComponentConstants.java". Create this class, and add your first constant for defining the component id and adapt the placeholders in the usual manner:

    
public static final String COMPONENT_ID = 
    "de.rcenvironment.components.<yourcomponentname>.
        execution.<YourComponentName>Component";
            

In order to keep track of your constants, it's advisable to give all constants a short comment.

To complete the setup, add the names of the all Java packages you created to the "Export-Package" attribute in the source code of the META-INF/MANIFEST.MF file. Example:

    
Export-Package: de.rcenvironment.components.<yourcomponentname>.common
            

1.4. Creating a gui Bundle

To add a graphical user interface for your component, create a "gui" bundle. Start by generating a new blank Eclipse Plug-In Project, as you did for the "execution" and "common" bundle.

The graphical user interface is shown in the properties tab which is usually shown at the bottom of RCE when the component is focused in the workflow editor.

Custom sections can be defined. Therefore create a package called like the project containing it. Inside the package create a class called "<YourComponentName>Section.java" which extends de.rcenvironment.core.gui.workflow.editor.properties.WorkflowNodePropertySection. Override the method createCompositeContent to fill the GUI.

Each component GUI must provide a Component Filter. It is used to determine which sections the GUI for the respective component consists of. Inside the package you just created add a class called "<YourComponentName>ComponentFilter.java". extending de.rcenvironment.core.gui.workflow.editor.properties.ComponentFilter. To define the component filter, override the following method:

    
@Override
public boolean filterComponentName(String componentId) {
return componentId.startsWith(YourComponentNameComponentConstants.COMPONENT_ID);
}
            

As usual, change YourComponentName to the name of your own component. This method will only return true for the component id used in the "execution" bundle, so it will only be shown for that component.

To provide sections as GUI elements, add a new file called "plugin.xml" to the root of the project folder. It is common to have a section where you can manage inputs and outputs and another section where component specific GUI elements are located. The following code demonstrates this and can be pasted into the plugin.xml you just created. As usual, adapt the component names and IDs accordingly. It is explained below:

    
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>

   <!-- Property Sections -->
   <extension point="org.eclipse.ui.views.properties.tabbed.propertySections">
      <propertySections contributorId=
      "de.rcenvironment.rce.gui.workflow.editor.WorkflowEditor">
      
         <propertySection
               tab=
               "workflow.editor.tab.<yourcomponentid>.General"
               class=
               "de.rcenvironment.components.<yourcomponentid>.
               gui.<yourComponentName>Section"
               id=
               "workflow.editor.tab.Properties.Section.General"
               filter=
               "de.rcenvironment.components.<yourcomponentid>.
               gui.<yourComponentName>ComponentFilter"
               enablesFor="1">
         </propertySection>
         
         <propertySection
               tab=
               "workflow.editor.tab.<yourcomponentid>.InputsOutputs"
               class=
               "de.rcenvironment.core.gui.workflow.editor.
               properties.DefaultEndpointPropertySection"
               id=
               "workflow.editor.tab.Properties.Section.InputsOutputs"
               filter=
               "de.rcenvironment.components.<yourcomponentid>.
               gui.<yourComponentName>ComponentFilter"
               enablesFor=
               "1">
         </propertySection>
         
      </propertySections>
   </extension>
   
   <!-- Register Property Sections -->
   <extension point="org.eclipse.ui.views.properties.tabbed.propertyTabs">
      <propertyTabs contributorId=
      "de.rcenvironment.rce.gui.workflow.editor.WorkflowEditor">
         
         <propertyTab 
         	   label="General"
               category="default"
               id="workflow.editor.tab.<yourcomponentid>.General">
         </propertyTab>
         
         <propertyTab
               label="Inputs/Outputs"
               category="default"
               id="workflow.editor.tab.<yourcomponentid>.InputsOutputs">
         </propertyTab>

     </propertyTabs>
   </extension>

</plugin>
            

For each section that you would like to add to the "Properties" view, add the entries like you can see in the propertySection and the propertyTab parts. Make sure that the "filter" attribute contains the correct path of the component filter class created above. The first entry in property section and property tab adds a general custom section to the GUI while the second entry adds a section to manage inputs and outputs.

Remember to keep the file valid by closing the definition blocks with the corresponding end tags:

After assigning the property tabs to their classes, you have to register each tab as a propertyTab.

Note that the ID of the propertyTab should be the same as the "tab" in the propertySection above. Customise the section title by editing the label attribute.

TODO: Add explanation how to use Messages file.

1.5. Adding your new component to SVN

It is recommended to develop a new component in a separate development branch. Therefore create a new branch. One of the several ways to do so is using TortoiseSVN. Check out the trunk. In the context menu of this folder select "TortoiseSVN > Branch/Tag". Navigate to the destination path which should be located in the branches folder. Call the new branch "dev_YourComponentName" where YourComponentName is the display name of your component. Then add the folders of the projects you created above to the structure in your file system. Select them and right click to open the context menu. Then select "TortoiseSVN > Add...". To commit them into the branch, open the context menu again and select "Commit... ".