You can develop your own mediation primitives, and contribute them to the Mediation Flow editor palette. Integration developers can then use these mediation primitives in the same way that you use the supplied mediation primitives, for example Message Filter.
The following topics briefly describe the actions that you have to perform in order to develop your own mediation primitive, contribute the primitive to the Mediation Flow Editor's palette, and deploy the primitives. We then use an example to show the steps required, and provide links to reference documentation.
Note: These steps may change in future releases, and effort may be required to re-enable your contributions for future releases.
Generate the mediation metadata (.mednode file) for the mediation primitive using the Mediation Metadata Generation view. The .mednode file contains the runtime representation of the mediationPrimitiveHandlers and must be placed at the root of the Java™ project that you create in Step 3.
Create a Java project, and write the code to implement your mediation primitive.
Note: the getter and setter method names must correspond to the property names. For example, if a property name is value, the getter and setter methods must be named getValue() and setValue().
Deploy your plug-in so that your mediation primitives appear in the Mediation Flow Editor palette:
To deploy your mediation primitives to the WebSphere Enterprise Service Bus or WebSphere Process Server runtime:
Note: the .mednode files must be within the root of the deployed jar, not in a subdirectory.
Create a plug-in project
Edit plugin.xml
Open plugin.xml in the Plug-in Manifest editor, and switch to the Extensions page.
Create required folders in plug-in the project
Add properties to the XML file
In CurrencyConverterPropertyGroup.xml , we will describe the properties of this new primitive, so as to derive the UI for the properties view Details page in the Mediation Flow editor. The Java class must have getter and setter methods that correspond to each of these properties. For more information, see Elements of the properties xml file and Property group schema definition file.
<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="CurrencyConverterPropertyGroup" xsi:type="pg:BasePropertyGroup" > <!-- currency path using XPathProperty --> <property name="currencyPath" displayName="Currency Path" defaultValue="/body" required="true" propertyType="String" id="com.ibm.propertygroup.ext.ui.XPathProperty" xsi:type="pg:ConstraintSingleValuedProperty"> <description> An XPath expression to the input currency value. </description> </property> <property name="currencyRatesTable" displayName="Currency Rates" xsi:type="pg:TableProperty"> <description> Currency rates </description> <qualifier preferredHeight="100" xsi:type="pg:TableLayoutQualifier"> <column name="currency" preferredWidth="300" xsi:type="pg:TableColumnQualifier"/> <column name="currencyRate" preferredWidth="200" xsi:type="pg:TableColumnQualifier"/> </qualifier> <column name="currency" validValuesEditable="false" required="true" displayName="Currency" xsi:type="pg:ConstraintSingleValuedProperty"> <description> List of currencies </description> <validValue value="USD" displayValue="United States Dollars(USD)"/> <validValue value="CAD" displayValue="Canadian Dollars(CAD)"/> <validValue value="EUR" displayValue="Euro(EUR)"/> <validValue value="JPY" displayValue="Japanese Yen(JPY)"/> <validValue value="CNY" displayValue="Chinese Yuan(CNY)"/> </column> <column name="currencyRate" required="true" validValuesEditable="false" displayName="Rate" propertyType="float" xsi:type="pg:ConstraintSingleValuedProperty"> <qualifier name="promotable" xsi:type="pg:PropertyClassificationQualifier" /> <description> Exchange rate </description> </column> </property> </propertyGroup> </pg:BasePropertyGroups>
Generate metadata
Author the Java Code
package com.ibm.websphere.esb.mediation.example.logic; 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; /** * This mediation converts from one currency value to another currency value. */ public class CurrencyConverterMediation extends ESBMediationPrimitive { private static final String OUTPUT_TERMINAL_NAME = "out"; private String currencyPath; private CurrencyRate[] currencyRatesTable; /** * Default constructor. */ public CurrencyConverterMediation() { super(); } /** * @return Returns the currencyPath. */ public String getCurrencyPath() { return currencyPath; } /** * @param currencyPath * The currencyPath to set. */ public void setCurrencyPath(String currencyPath) { this.currencyPath = currencyPath; } /** * @return Returns the currencyRates. */ public CurrencyRate[] getCurrencyRatesTable() { return this.currencyRatesTable; } /** * @param currencyRates The currencyRates to set. */ public void setCurrencyRatesTable(CurrencyRate[] currencyRates) { this.currencyRatesTable = currencyRates; } /* * (non-Javadoc) * * @see com.ibm.wsspi.sibx.mediation.Mediation#mediate(com.ibm.wsspi.sibx.mediation.InputTerminal, * commonj.sdo.DataObject) */ public void mediate(InputTerminal inputTerminal, DataObject message) throws MediationConfigurationException, MediationBusinessException { // retrieves the input currency value float inputCurrencyValue = message.getFloat(getCurrencyPath()); if (getCurrencyRatesTable() != null && getCurrencyRatesTable().length > 0) { // we only use the first available currency rate float currencyRate = getCurrencyRatesTable()[0].getCurrencyRate(); // converts to the new currency value float newCurrencyValue = inputCurrencyValue * currencyRate; // update the new currency value to the message message.setFloat(getCurrencyPath(), newCurrencyValue); } // gets the out terminal from the mediation services OutputTerminal outTerminal = getMediationServices().getOutputTerminal( OUTPUT_TERMINAL_NAME); if (outTerminal != null) { // fires the message to the out terminal outTerminal.fire(message); } } }
package com.ibm.websphere.esb.mediation.example.logic; /** * Data object for currency rates table property. */ public class CurrencyRate { private String currency; private float currencyRate; /** * */ public CurrencyRate() { super(); } /** * @return Returns the currency. */ public String getCurrency() { return currency; } /** * @param currencyPath * The currency to set. */ public void setCurrency(String currency) { this.currency = currency; } /** * @return Returns the currencyRate. */ public float getCurrencyRate() { return currencyRate; } /** * @param currencyRate * The currencyRate to set. */ public void setCurrencyRate(float currencyRate) { this.currencyRate = currencyRate; } }
Deploy to the runtime
Export the Java project as a jar, for example myPrimitives.jar. In the root folder, select .mednode only, but keep the Java class selected. Export the jar to WAS_HOME/lib/ext.
For information on Service Data Object APIs, see http://download.eclipse.org/tools/emf/sdo/javadoc/
<pg:BasePropertyGroups name="myGroups" resourceBundle="mypacakage.myProperties">
Attribute | Description |
---|---|
name | Name of the property group. This name will not be displayed in the Mediation Flow Editor. |
resourceBundle | The resource bundle that will be loaded to interpret a string value. This is used for globalization. |
<propertyGroup name="myGroup" xsi:type="pg:BasePropertyGroup">
Attribute | Description |
---|---|
name | Name of the property group. If there is more than one propertyGroup, each propertyGroup element is rendered as tab page in the Details page. The name attribute becomes the name of the tab page. |
Property | Attribute | Description |
---|---|---|
|
name / displayName | Name is the identifier of a property. DisplayName is used as a label preceding the property input control. |
description | Displayed as tooltip text | |
propertyType | Defines the value type (String / Boolean / Float / Integer) | |
defaultValue | The default value of the property | |
hidden | Defines whether the property is hidden or shown | |
readOnly | Defines whether the property is read only | |
required | Indicates that the property requires a value | |
sensitive | If value type is String, this attribute determines whether it is case sensitive | |
validValuesEditable | Defines whether a user is allowed to enter a value which is different from values defined by validValues | |
validValues | A list of valid values | |
pattern (optional) | If the value type is String, the editor will do a pattern match to validate user input | |
maxLength (optional) | If the value type is String, the editor will limit the size that user can input | |
minValue / maxValue (optional) | If the value type is Integer or Float, the editor will perform a range check on user input. | |
validValueGeneratorClass | Points to a class which is responsible for dynamically generating valid values.. The class must implement the interface com.ibm.propertygroup.ext.api .IValidValuesGenerator |
<property name="filters" displayName="%displayname" xsi:type="pg:TableProperty"> <column name="pattern" required="true" .../> <column name="terminalName" required="true" .../> </property>
<property name="myCustomProperty" class="MyCustomImpl" xsi:type="pg:CustomProperty">
<property name="filters" xsi:type="pg:TableProperty"> <qualifier preferredHeight="100" xsi:type="pg:TableLayoutQualifier"> <column name="pattern" preferredWidth="100" xsi:type="pg:TableColumnQualifier"/> <column name="terminalName" preferredWidth="200" xsi:type="pg:TableColumnQualifier"/> </qualifier> ... </property>
<qualifier name="promotable" xsi:type="pg:PropertyClassificationQualifier" />
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:propertygroup="http://www.ibm.com/propertygroup/6.0.1" targetNamespace="http://www.ibm.com/propertygroup/6.0.1"> <element name="propertyGroups" type="propertygroup:BasePropertyGroups"/> <element name="description" type="string"/> <complexType name="PersistentFormatter"> </complexType> <complexType name="StringFormatter"> <complexContent> <extension base="propertygroup:PersistentFormatter"> <attribute name="escapeCharacter" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="StringListFormatter"> <complexContent> <extension base="propertygroup:StringFormatter"> <attribute name="separator" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="StringTableFormatter"> <complexContent> <extension base="propertygroup:StringFormatter"> <attribute name="rowSeparator" type="token" use="optional"/> <attribute name="columnSeparator" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="Qualifier"> </complexType> <complexType name="TableColumnQualifier"> <complexContent> <extension base="propertygroup:Qualifier"> <attribute name="name" type="token" use="required"/> <attribute name="preferredWidth" type="token" use="required"/> </extension> </complexContent> </complexType> <complexType name="TableLayoutQualifier"> <complexContent> <extension base="propertygroup:Qualifier"> <choice> <element maxOccurs="unbounded" minOccurs="0" name="column" type="propertygroup:TableColumnQualifier"/> </choice> <attribute name="preferredHeight" type="token" use="required"/> </extension> </complexContent> </complexType> <complexType name="PropertyClassificationQualifier"> <complexContent> <extension base="propertygroup:Qualifier"> <attribute name="name" type="token" use="required"/> </extension> </complexContent> </complexType> <complexType name="PropertyDescriptor"> <choice> <element ref="propertygroup:description" minOccurs="0"/> <element name="persistentFormatter" type="propertygroup:PersistentFormatter" minOccurs="0"/> <element maxOccurs="unbounded" minOccurs="0" name="qualifier" type="propertygroup:Qualifier"/> </choice> <attribute name="id" type="token" use="optional"/> <attribute name="name" type="token" use="required"/> <attribute name="displayName" type="token" use="optional"/> </complexType> <complexType name="BasePropertyDescriptor"> <complexContent> <extension base="propertygroup:PropertyDescriptor"> </extension> </complexContent> </complexType> <complexType name="BaseProperty"> <complexContent> <extension base="propertygroup:BasePropertyDescriptor"> <attribute name="validationMessage" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="BaseNodeProperty"> <complexContent> <extension base="propertygroup:BaseProperty"> <sequence> <element maxOccurs="0" minOccurs="0" name="children" type="propertygroup:BaseNodeProperty"/> </sequence> </extension> </complexContent> </complexType> <complexType name="ValidValue"> <sequence> <element ref="propertygroup:description" minOccurs="0"/> </sequence> <attribute name="displayValue" type="token" use="optional"/> <attribute name="value" type="token" use="required"/> </complexType> <complexType name="BaseSingleTypedProperty"> <complexContent> <extension base="propertygroup:BaseProperty"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="validValue" type="propertygroup:ValidValue"/> </sequence> <attribute name="defaultValue" type="token" use="optional"/> <attribute name="propertyType" type="token" use="required"/> <attribute name="expert" type="boolean" use="optional"/> <attribute name="hidden" type="boolean" use="optional"/> <attribute name="readOnly" type="boolean" use="optional"/> <attribute name="required" type="boolean" use="optional"/> <attribute name="sensitive" type="boolean" use="optional"/> <attribute name="validValuesEditable" type="boolean" use="optional"/> </extension> </complexContent> </complexType> <complexType name="BaseMultiValuedProperty"> <complexContent> <extension base="propertygroup:BaseSingleTypedProperty"> </extension> </complexContent> </complexType> <complexType name="BaseBoundedMultiValuedProperty"> <complexContent> <extension base="propertygroup:BaseMultiValuedProperty"> <attribute name="boundedSize" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="File"> <attribute name="extension" type="token" use="optional"/> <attribute name="pattern" type="token" use="optional"/> </complexType> <complexType name="MultiFileProperty"> <complexContent> <extension base="propertygroup:BaseMultiValuedProperty"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="fileExtension" type="propertygroup:File"/> </sequence> </extension> </complexContent> </complexType> <complexType name="MultiFolderProperty"> <complexContent> <extension base="propertygroup:BaseMultiValuedProperty"> </extension> </complexContent> </complexType> <complexType name="ConstraintMultiValuedProperty"> <complexContent> <extension base="propertygroup:BaseBoundedMultiValuedProperty"> <attribute name="pattern" type="token" use="optional"/> <attribute name="minValue" type="integer" use="optional"/> <attribute name="maxValue" type="integer" use="optional"/> <attribute name="maxLength" type="integer" use="optional"/> </extension> </complexContent> </complexType> <complexType name="BaseSingleValuedProperty"> <complexContent> <extension base="propertygroup:BaseSingleTypedProperty"> </extension> </complexContent> </complexType> <complexType name="FileProperty"> <complexContent> <extension base="propertygroup:BaseSingleValuedProperty"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="fileExtension" type="propertygroup:File"/> </sequence> </extension> </complexContent> </complexType> <complexType name="FolderProperty"> <complexContent> <extension base="propertygroup:BaseSingleValuedProperty"> </extension> </complexContent> </complexType> <complexType name="ConstraintSingleValuedProperty"> <complexContent> <extension base="propertygroup:BaseSingleValuedProperty"> <attribute name="pattern" type="token" use="optional"/> <attribute name="minValue" type="integer" use="optional"/> <attribute name="maxValue" type="integer" use="optional"/> <attribute name="maxLength" type="integer" use="optional"/> <attribute name="validValuesGeneratorClass" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="PropertyGroup"> <complexContent> <extension base="propertygroup:BaseProperty"> </extension> </complexContent> </complexType> <complexType name="BasePropertyGroup"> <complexContent> <extension base="propertygroup:PropertyGroup"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="property" type="propertygroup:PropertyDescriptor"/> <element maxOccurs="unbounded" minOccurs="0" name="customProperty" type="propertygroup:CustomProperty"/> </sequence> </extension> </complexContent> </complexType> <complexType name="CustomPropertyGroup"> <complexContent> <extension base="propertygroup:PropertyGroup"> <attribute name="class" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="BasePropertyGroups"> <complexContent> <extension base="propertygroup:BaseProperty"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="propertyGroup" type="propertygroup:PropertyGroup"/> </sequence> <attribute name="resourceBundle" type="token" use="optional"/> </extension> </complexContent> </complexType> <complexType name="BaseTreeProperty"> <complexContent> <extension base="propertygroup:BaseProperty"> </extension> </complexContent> </complexType> <complexType name="TableProperty"> <complexContent> <extension base="propertygroup:PropertyDescriptor"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="column" type="propertygroup:BaseSingleTypedProperty"/> </sequence> </extension> </complexContent> </complexType> <complexType name="TreeProperty"> <complexContent> <extension base="propertygroup:PropertyDescriptor"> <sequence> <element maxOccurs="1" minOccurs="0" name="root" type="propertygroup:BaseNodeProperty"/> </sequence> </extension> </complexContent> </complexType> <complexType name="CustomProperty"> <attribute name="class" type="token" use="required"/> </complexType> </schema>