Building your own mediation primitive with WebSphere Integration Developer and WebSphere Enterprise Service Bus

The WebSphere Integration Developer mediation flow editor comes with a set of pre-packaged mediation primitives. But what if they don't do what you want to do? This article shows you how to create your own mediation primitives, which sit on the mediation flow editor palette along with the pre-packaged primitives.

Share:

Russell Butek, Software Engineer, IBM

Russell Butek is one of the developers of the IBM WebSphere web services engine. He is also an IBM representative on the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0. Previously, he was a developer of the IBM CORBA ORB and an IBM representative on a number of OMG task forces: the portable interceptor task force (of which he was chair), the core task force, and the interoperability task force. You can contact Russell at butek at us.ibm.com.



30 May 2007

Introduction

This article assumes that you are familiar with IBM® WebSphere® Enterprise Service Bus (hereafter called WebSphere ESB). Some experience with custom mediation primitives and Eclipse plug-ins is helpful but not essential. Mediation primitives, whether prepackaged or created by you, are Eclipse plug-ins. This article tells you in general terms what you need to do, then walks you through a specific sample -- a mediation primitive that dumps the Service Message Object (SMO) or some part of it to the console. When you complete this tutorial, your new DumpSMO primitive will appear on the mediation flow editor palette along with the pre-packaged primitives.

Terminology for mediation primitives

The terminology for mediation primitives has been a bit confusing. Here are the terms used in this article:

Mediation Primitive
Everything on the palette in the mediation flow editor.
Custom mediation primitive
Pre-packaged primitive within which you can write your own Java code.
Mediation primitive plug-in
A primitive Eclipse plug-in, like the one you will create in this article.

Before building your own mediation primitive, it's worth looking at your reasons for doing so and going through a brief cost-benefit analysis, because designing the primitive and writing the Java™ code will take some time. Here are some possible reasons for building your own mediation primitive:

Because the pre-packaged mediation primitives don't do everything you want them to do.
This reason is pretty good, but you can build a custom mediation primitive to satisfy this requirement, so it's not good enough.
Because you want to reuse of your custom mediation primitive implementation.
When you write your own primitive, users of it simply have to drag it onto the workspace and perhaps supply a few configuration properties, reusing your code in every instance of the primitive. For a custom mediation primitive, its implementation is specific to the single primitive. It is not in itself reusable. However, if you use custom mediation primitives, you can get close to the level of reuse that you get with a mediation primitive plug-in. If you put the bulk of your implementation in a Java library, and then, in each custom mediation primitive instance, just call that library, that library code is reused. However, this technique still requires a line or two of special code in each custom mediation primitive instance.
Because you want to define your own properties.
Properties defined on custom mediation primitives are meta-level properties describing the mediation implementation, and they do not provide for properties used by the mediation implementation itself. If you define your own mediation primitive plug-in, you can define properties that the implementation can use.
Because you want a set of terminals different from the standard set.
You cannot add new terminals to a custom mediation primitive. If you need something other than the standard set of one input, one output, and one fail terminal, then you have to define your own mediation primitive plug-in.
Because user-defined mediation primitives are cool.
OK, this reason is a bit lame, but some of us get excited seeing our own icon on the mediation flow editor palette.

High-level steps for creating your own mediation primitive plug-in

Each of these high-level steps is covered in a section below.

  1. Build the plug-in project, which contains the information for the visual aspect of the mediation primitive. It describes what you see in the mediation flow editor.
  2. Build the Java project, which is the actual implementation of the mediation primitive.
  3. Deploy the plug-in project, which is an Eclipse plug-in and must be deployed as one.
  4. Deploy the Java project. The implementation must reside somewhere where the runtime can find it.
  5. Test the new mediation primitive.

Prerequisites

  • WebSphere Integration Developer V6.0.2 or later, with either a WebSphere ESB server or WebSphere Process Server as your test server.
  • The sample files for this article, which you can download below. The article assumes that you unzip them into C:\.

Build the plug-in project

There is nothing magical about mediation primitives -- they are simply specialized Eclipse plug-ins. Creating them is a bit tedious, but not difficult. To build the plug-in, use the Plug-in Development Environment that comes with WebSphere Integration Developer:

  1. Open the Plug-in Development Environment perspective:
    1. Select Window => Open Perspective => Other.
    2. In the Select Perspective popup window, check Show All, select Plug-in Development, and click OK.
    3. In the confirmation pop-up window, click OK.
  2. Select File => New => Plug-in Project.
  3. In the New Plug-in Project popup window:
    1. Set the Project Name to com.ibm.wesb.samples.dumpSMO. The Eclipse convention is to give plug-ins Java-package-like names.
    2. Under Project Settings, uncheck Create a Java project. We want our Java project to be separate from the GUI project.
    3. Click Next.
  4. Click Finish.

You should now see the plug-in manifest editor, which lets you configure the plug-in project. Under the covers, you are editing the file plugin.xml.

There are two extensions that have to be configured: the handler extension, which provides the details about the primitive; and the UI contribution extension, which holds the icons for the primitive.

  1. In the plug-in manifest editor, select the Extensions tab.
  2. Click Add.
  3. In the New Extension popup window:
    1. Near the bottom, uncheck Show only extension points from the required plug-ins. The Mediation Flow editor plug-ins are not required, so you won't see them unless you uncheck this option.
    2. About 1/3 of the way down the list, select com.ibm.wbit.sib.mediation.primitives.registry.mediationPrimitiveHandlers.
    3. Click Finish.
  4. Back in the plug-in manifest editor, right click on com.ibm.wbit.sib.mediation.primitives.registry.mediationPrimitiveHandlers and select New => mediationPrimitiveHandler.
  5. Make sure that the mediation primitive handler that you just created is selected, and fill in the Extension Element Details on the right with the following values (as shown in the figure):
    • typeName: DumpSMO
    • typeNamespace: mednode://mednodes/DumpSMO.mednode. This field must begin with mednode://mednodes.
    • propertyDefinition: propertygroups/DumpSMOPropertyGroup.xml. You will create this directory and file later.
    • implementationClass: com.ibm.wesb.samples.dumpSMO.DumpSMOPlugin. This is the implementation for your mediation primitive plug-in, provided in the download file. You will add it to your workspace later.
    • isTerminalTypeDeducible: true. This means that when you define an interface for one of the terminals (wire it to another node's terminal), all of the terminals on your mediation primitive will get the same interface. If you do not specify true then the user would have to explicitly define each terminal's interface.
    Mediation primitive handler extension
    Mediation primitive handler extension

Let's describe this mediation primitive. There are two descriptions: the short description appears when you hover over the icon on the mediation flow editor palette, and at the top of the properties panel. The long description does not appear in the mediation flow editor, but you should include it for Eclipse plug-in completeness. Start with the short description:

  1. Right click on (mediationPrimitiveHandler) and select New => shortDescription.
  2. At the bottom of the editor, open Body Text and type in a short description of the mediation plug-in, such as Dump the SMO.
  3. At the far right, click Apply.

Provide a long description of the plug-in:

  1. Right click on (mediationPrimitiveHandler) and select New => longDescription.
  2. At the bottom of the editor, open Body Text and type in a long description of the mediation plug-in: Dump to the console some or all of the SMO, depending on the XPath that the user specified.
  3. Click Apply.

Now that you've described the general plug-in details, you have to describe some specifics, such as each terminal. A mediation primitive has three types of terminals: input, output, and fail. You can only have 0 or 1 fail terminals, but you can have 0 or more input and output terminals. Each terminal has a name.

A terminal may be dynamic, meaning that there is no fixed number of that variety. You simply describe a single terminal of that variety and set the isDynamic flag to true. Users of your mediation primitive can then place as many terminals of that type on the primitive as they please. The filter mediation primitive takes advantage of this feature -- with that primitive, you can create as many output terminals as necessary, and define filters for each output. Of course, doing so means that your Java implementation of the primitive must be able to deal with this dynamic nature of your primitive. But that is not hard, as explained below. The DumpSMO example has a fixed set of terminals -- the typical set of one input, one output, and one fail terminal.

Describe the input terminal:

  1. Right click on (mediationPrimitiveHandler) and select New => terminalCategory.
  2. Fill in the Extension Element Details on the right with the following values:
    • type: input
    • name: in
    • isDynamic: (leave blank)

Describe the output terminal:

  1. Right click on (mediationPrimitiveHandler) and select New => terminalCategory.
  2. Fill in the Extension Element Details on the right with the following values:
    • type: output
    • name: out
    • isDynamic: (leave blank)

Describe the fail terminal:

  1. Right click on (mediationPrimitiveHandler) and select New => terminalCategory.
  2. Fill in the Extension Element Details on the right with the following values:
    • type: fail
    • name: fail (The name of the fail terminal is required to be fail).
    • isDynamic: (leave blank)

    Your extension should now look like this:

    Mediation primitive handler extension
    Mediation primitive handler extension

Now let's add the UI contribution extension, which describes the icons for the primitive. You have to be a bit artistic at this stage. You need two icons that should be the same picture, but in different sizes. The large icon (32 x 32 pixels) appears on the mediation flow editor palette, and the small icon (16 x 6 pixels) appears on each primitive in the workspace. The sample includes two icons.

  1. Beside All Extensions on the left, click Add.
  2. In the New Extension popup window, select com.ibm.wbit.sib.mediation.primitives.registry.mediationPrimitiveUIContribution. (If that extension is not visible, uncheck the option near the bottom labeled Show only extension points from the required plug-ins.)
  3. Click Finish.
  4. Right-click on com.ibm.wbit.sib.mediation.primitives.registry.mediationPrimitiveUIContribution and select New => mediationPrimitiveUIContribution.
  5. Select the mediation primitive UI contribution that you just created and fill in the Extension Element Details on the right with the following values:
    • mediationPrimitiveTypeName: DumpSMO
    • mediationPrimitiveTypeNamespace: mednode://mednodes/DumpSMO.mednode. These first two fields must be identical to the corresponding fields in the mediation primitive handler, so that they can be associated with each other.
    • paletteCategory: /
    • smallIcon: icons/dumpSMO.small.gif
    • largeIcon: icons/dumpSMO.large.gif.

      You will create the icons directory later, at which time you will also copy the provided gif files to that directory.

    Your new extension should look like this:

    Mediation primitive UI extension
    Mediation primitive UI extension
  6. Save the contents of the plug-in manifest editor.

You have now configured the plug-in. During this process, you have referred to three folders and their files: icons, propertygroups, and mednodes (or mednode://mednodes/). You will now create and populate those folders.

The icons folder:

  1. In the Package Explorer view on the left side of WebSphere Integration Developer, right-click on our plug-in project com.ibm.wesb.samples.dumpSMO and select New => Folder.
  2. For Folder Name, type icons and click Finish.
  3. Right-click on the icons folder and select Import.
  4. In the Import popup window, select File System and click Next.
  5. For From directory, browse to C:\PrimitivePluginFiles.
  6. On the right side of the File System panel, select both DumpSMO.small.gif and DumpSMO.large.gif and click Finish.

The propertygroups folder:

  1. In the Package Explorer on the left side of WebSphere Integration Developer, right-click on our plug-in project com.ibm.wesb.samples.dumpSMO and select New => Folder.
  2. For Folder Name, type propertygroups and click Finish.
  3. Right click on icons and select Import.
  4. In the Import popup window, select File System and click Next.
  5. For From directory, browse to C:\PrimitivePluginFiles.
  6. On the right side of the File System panel, select DumpSMOPropertyGroup.xml and click Finish.

This file describes the properties on a mediation primitive. You can have any number of properties -- this example has only one: the XPath to the portion of the SMO to dump to the console. Here are the contents of the file you just imported:

Listing 1. DumpSMOPropertyGroup.xml
<pg:BasePropertyGroups
    name="CacheReaderPropertyGroups"
    resourceBundle="ESBMediationExamples"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:pg="http://www.ibm.com/propertygroup/6.0.1"> 
  <propertyGroup
      name="DumpSMOPropertyGroup"
      xsi:type="pg:BasePropertyGroup" >
    <property
        name="XPath"
        displayName="Dump the DataObject at this XPath"
        defaultValue="/body"
        required="true"
        propertyType="String"
        id="com.ibm.propertygroup.ext.ui.XPathProperty"
        xsi:type="pg:ConstraintSingleValuedProperty">
      <description>
        An XPath expression to the DataObject which will be dumped to the console.
      </description>
    </property>
  </propertyGroup> 
</pg:BasePropertyGroups>

This file contains a single property group, named DumpSMOPropertyGroup, which contains a single property named XPath, with a number of fields that are self-explanatory. This property will appear in the properties panel for the DumpSMO mediation primitive.

Each property that you define in this file must have a corresponding getter and setter in the implementation for this mediation primitive. In the sample, the implementation will have getXPath and setXPath methods.

The mednodes folder

The mednode file is the mediation meta-data file. It is a generated file, and is generated with the following steps:

  1. From the menu bar, select Run => Run As => Run-time Workbench.
  2. WebSphere Integration Developer launches a new IDE, which takes a few minutes.
  3. Once the new IDE launches, select Window => Show view => Other => Mediation Development => Mediation Metadata Generation.
  4. Click OK.
  5. The mediation primitive that you created is displayed in the Mediation Metadata Generation view of this new IDE. Check the DumpSMO row.
  6. Click Generate. The status of your mediation primitive should now be OK. The tool has just generated the meta-data mednode file.
  7. Close this IDE.
  8. Back in the main WebSphere Integration Developer window, in the Package Explorer view, right-click on your mediation primitive plug-in project and select Refresh. You should now see a mednodes folder that contains the file DumpSMO.mednode:
    The mednodes folder
    The mednodes folder

Now that you have created and populated the necessary folders, you have to make sure that they are included when the plug-in project is built:

  1. Go back to the plug-in manifest editor, in which you were editing the plugin.xml file.
  2. Select the Build tab.
  3. Ensure that the following items are all checked under Binary Build (as shown in the figure):
    • The icons folder
    • The mednodes folder
    • The plugin.xml file
    • The propertygroups folder
    The build tab of the plug-in manifest editor
    screen shot of the build tab of the plug-in manifest editor
  4. Save the contents of the plug-in manifest editor.

That's it -- you are done building the plug-in project and you have completed this section. The next section shows you how to build the Java project.

Build the Java project

You have created the plug-in GUI project. Now you have to create the implementation for this GUI. The sample code includes the Java implementation project, but it is not fully configured, so you need to do a few steps to make the project usable:

  1. Import the Java project -- the project interchange file C:\PrimitivePluginFiles\DumpSMO.PI.zip.
  2. When this project interchange file is loaded, the DumpSMO project will have compile-time errors. This code is an SCA/SDO implementation, so you need to add a library with the SCA/SDO APIs to the build path:
    1. Right-click on DumpSMO and select Properties.
    2. Select the Java build path.
    3. Go to the Libraries tab:
      1. Click Add Library.
      2. Select WebSphere ESB Server V6 and click Next.
      3. Check Configure WebSphere ESB Server classpath and click Finish, then click OK.

Once the project builds, the errors will be gone.

Now let's take a look at the Java code, which is located in DumpSMO => com.ibm.wesb.samples.dumpSMO => DumpSMOPlugin.java and also shown below:

Listing 2. DumpSMOPlugin.java
package com.ibm.wesb.samples.dumpSMO;

import java.io.ByteArrayOutputStream;

import com.ibm.websphere.bo.BOXMLSerializer;
import com.ibm.websphere.sca.ServiceManager;
import com.ibm.wsspi.sibx.mediation.InputTerminal;
import com.ibm.wsspi.sibx.mediation.MediationBusinessException;
import com.ibm.wsspi.sibx.mediation.MediationConfigurationException;
import com.ibm.wsspi.sibx.mediation.OutputTerminal;
import com.ibm.wsspi.sibx.mediation.esb.ESBMediationPrimitive;
import commonj.sdo.DataObject;

public class DumpSMOPlugin extends ESBMediationPrimitive {

  private static final String OUTPUT_TERMINAL_NAME = "out";
	
  private String xPath;
	
  public String getXPath() {
    return xPath;
  }
	
  public void setXPath(String xPath) {
    this.xPath = xPath;
  }

  public void mediate(InputTerminal inputTerminal, DataObject message)
      throws MediationConfigurationException, MediationBusinessException {
    try {
      BOXMLSerializer serializer =
          (BOXMLSerializer) ServiceManager.INSTANCE.locateService(
          "com/ibm/websphere/bo/BOXMLSerializer");
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      serializer.writeDataObject(message.getDataObject(
          getXPath()), 
          "urn:someNamespace", 
          "dump", 
          baos);
      System.out.println(new String(baos.toByteArray()));

     // Get the out terminal from the mediation services
      OutputTerminal outTerminal = getMediationServices().getOutputTerminal(
          OUTPUT_TERMINAL_NAME);
      if (outTerminal != null) {
        // Fire the message to the out terminal
        outTerminal.fire(message);
      }
    }
    catch (Throwable t) {
      System.out.println("Problem calling DumpSMO.  Not dumping anything.");
      t.printStackTrace();
    }
  }
}

The actual implementation of this class is not relevant to this article, though you may find it useful as a basis for a more complete primitive of this nature.

The first thing to notice about DumpSMO is that it extends ESBMediationPrimitive, which it must do to reside on the Mediation Flow editor palette. Next, recall that you defined a property named XPath. For that property, this implementation file must have a getter and a setter: getXPath and setXPath.

The bulk of the mediation primitive plug-in implementation is in the mediate method. The parameters are:

  • inputTerminal -- This parameter contains information about the input terminal. It is useful if you have more than one. Since this method is called on every input terminal, this field describes the terminal that caused this method to be invoked. You would use this parameter to determine the interface of the input SMO. In this case you have only one input terminal, so you do not use this parameter.
  • message -- This is the SMO. It is typed as a DataObject, which the ServiceMessageObject type extends, but it is really a ServiceMessageObject, so if necessary you can down-cast this type to make use of the SMO APIs.

Lastly, after the real work of the primitive is complete, you have to fire the output terminal, which simply requires you to get the output terminal and fire the message through it.

There is one final thing that you must do on this Java project. Since it is the implementation for a mediation primitive plug-in, the project needs the GUI metadata file for that primitive:

  1. In the Package Explorer view, right-click on com.ibm.wesb.samples.dumpSMO => mednodes => DumpSMO.mednode and select Copy.
  2. Right-click on the DumpSMO project and select Paste.

That's it. You are now ready to deploy your two projects.

Deploy the Java implementation project

The code for the implementation itself has to be made available to the runtime. The steps below will install this code as a JAR file to the WebSphere Integration Developer test server runtime. If you also want to run this primitive in a standalone WebSphere ESB (or WebSphere Process Server) runtime, copy this JAR file to that installation's $WAS_HOME\lib\ext directory as well.

  1. Right-click on the Java project DumpSMO and select Export.
  2. In the Select panel, select JAR file.
  3. Click Next.
  4. In the JAR package specification panel:
    • JAR file: $WID_HOME\runtimes\bi_v6\lib\ext\DumpSMO.jar
    • Leave the remaining fields with their default values.
  5. Click Finish.

That's it. You have just deployed the implementation for the plug-in. You must restart your server in order for it to recognize this new JAR file.

Deploy the plug-in project

The plug-in project must be exported as an Eclipse plug-in, which reside in the $WID_HOME\wstools\eclipse directory.

  1. Right-click on the mediation primitive plug-in project com.ibm.wesb.samples.dumpSMO and select Export.
  2. In the Select panel, select Deployable plug-ins and fragments and click Next.
  3. In the Deployable plug-ins and fragments panel:
    • Deploy as: a directory structure
    • Directory: browse to $WID_HOME\wstools\eclipse
    • Leave the remaining fields with their default values.
  4. Click Finish.

You have now deployed the plug-in project. The last thing you have to do before you can use your newly created primitive is to enable it in WebSphere Integration Developer. Since it's an Eclipse plug-in, you must restart WebSphere Integration Developer in clean mode, which means it reloads all of its plug-ins. If you have an icon on your desktop, follow these steps:

  1. Shut down WebSphere Integration Developer and restart it with the -clean option:
    1. Right-click on the WebSphere Integration Developer desktop icon and select Properties.
    2. Add -clean to the Target field:
      WID -clean
      screen shot of Properties window
    3. Click Apply.
  2. Double-click on the WebSphere Integration Developer icon to start it in clean mode.
  3. While it is starting, you can use the time to roll back what you just did. Remove -clean from the properties Target field. WID -clean is slower than a normal invocation of WebSphere Integration Developer, so you should only use it when instructed, such as when you create new mediation primitives.
  4. Click OK.
  5. Once WebSphere Integration Developer is back up, start your test server. Then move to the next section and test your new DumpSMO mediation primitive.

Test your new mediation primitive

You can construct your own mediation module and place an instance of the new DumpSMO mediation primitive onto the mediation flow and test it. Here is what the mediation flow editor should now look like -- when you open it, you should see your new primitive on the palette (circled on the left below). To configure the primitive, go to its properties -- the XPath property is shown at the bottom below:

DumpSMO
screen shot of Properties window

Drop this mediation primitive into your flow at various places with various property values. At each point where the mediation primitive executes, you will see in the console something like what you see in Listing 3 below, in which the primitive is configured to display the default XPath: /body. The operation is named operation1 and the single parameter is named input1:

Listing 3. DumpSMO output
<_:dump
      xsi:type="intf:operation1RequestMsg"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:intf="http://junk/intf" xmlns:_="urn:namespace">
  <operation1>
    <input1>hello</input1>
  </operation1>
</_:dump>

Conclusion

By using the DumpSMO sample, you have now learned how to create your own mediation primitive, and you should have that sample functioning within your workspace.


Download

DescriptionNameSize
Sample codePrimitivePluginFiles.zip5 KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Business process management
ArticleID=227851
ArticleTitle=Building your own mediation primitive with WebSphere Integration Developer and WebSphere Enterprise Service Bus
publish-date=05302007