Creating a message processing or output node in Java
A message processing node is used to process a message, and an output node is used to output a message as a bit stream.
Before you begin
About this task
IBM® Integration Bus provides the source for two sample user-defined nodes called SwitchNode and TransformNode. You can use these nodes in their current state, or you can modify them.
When you code a message processing node or an output node, the two types provide essentially the same functions. You can perform message processing within an output node, and likewise you can propagate an output message to a bit stream from a message processing node. For simplicity, this topic refers mainly to the node as a message processing node, but it does discuss the functionality of both types of node.
A Java user-defined node is distributed as a .jar file.
Creating a new Java project
About this task
- Click Java and click Next. . Select
- In the Project name field, enter a project a name, then click Next.
- On the Java Settings pane, select the Libraries tab, and click Add External JARs.
- Select install_dir\server\classes\jplugin2.jar.
- Follow the prompts on the other tabs to define any other build settings.
- Click Finish.
Declaring the message processing node class
About this task
Any class that implements MbNodeInterface, and is contained in the integration node's LIL path, is registered with the integration node as a message processing node. When you implement MbNodeInterface, you must also implement an evaluate method for this class. The evaluate method is called by the integration node for each message that passes through the flow.
The class name must end with the word "Node". For example, if you have assigned the name as Basic in the IBM Integration Toolkit, the class name must be BasicNode.
package com.ibm.jplugins;
import com.ibm.broker.plugin.*;
public class BasicNode extends MbNode implements MbNodeInterface
- Click Class, then click Next. , select
- Set the package and class name fields to appropriate values.
- Delete the text in the Superclass text field and click Browse.
- Select MbNode and click OK.
- Click the Add button next to Interfaces text field, and select MbNodeInterface.
- Click Finish.
Defining the node constructor
About this task
When the node is instantiated, the constructor of the user's node class is called. Create the terminals of the node, and initialize any default values for attributes in this constructor.
A message processing node has a number of input terminals and output terminals that are associated with it. Use the methods createInputTerminal and createOutputTerminal to add terminals to a node when the node is instantiated.
For example, to create a node with one input terminal and two output terminals:
public MyNode() throws MbException
{
// create terminals here
createInputTerminal ("in");
createOutputTerminal ("out");
createOutputTerminal ("failure");
}
Accessing message data
About this task
In many cases, the user-defined node needs to access the contents of the message received on its input terminal. The message is represented as a tree of syntax elements. Use the supplied utility function to evaluate methods for message management, message buffer access, syntax element navigation, and syntax element access.
The MbElement class provides the interface to the syntax elements.
For example:
Procedure
Results
Transforming a message object
About this task
The received input message is read-only, so before you can transform a message, you must write it to a new output message. You can copy elements from the input message, or you can create new elements in the output message.
The MbMessage class provides the copy constructors, and the methods to get the root element of the message. The MbElement class provides the interface to the syntax elements.
- To create a new copy of the message assembly and its embedded
messages:
MbMessage newMsg = new MbMessage(assembly.getMessage()); MbMessageAssembly newAssembly = new MbMessageAssembly(assembly, newMsg);
- To navigate to the relevant syntax element in the XML message:
MbElement rootElement = newAssembly.getMessage().getRootElement(); MbElement switchElement = rootElement.getFirstElementByPath("/XML/data/action");
- To change the value of an existing element:
String elementValue = (String)switchElement.getValue(); if(elementValue.equals("add")) switchElement.setValue("change"); else if(elementValue.equals("change")) switchElement.setValue("delete"); else if(elementValue.equals("delete")) switchElement.setValue("hold"); else switchElement.setValue("failure");
- To add a new tag as a child of the switch tag:
MbElement tag = switchElement.createElementAsLastChild(MbElement.TYPE_NAME, "PreviousValue", elementValue);
- To add an attribute to this new tag:
tag.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "NewValue", switchElement.getValue()); MbOutputTerminal out = getOutputTerminal("out");
createElementAfter(String)
createElementAsFirstChild(String)
createElementAsLastChild(String)
createElementBefore(String)
createElementAsLastChildFromBitstream(byte[], String, String, String, String, int, int, int)
createElementAfter(int)
createElementAfter(int, String, Object)
createElementAsFirstChild(int)
createElementAsFirstChild(int, String, Object)
createElementAsLastChild(int)
createElementAsLastChild(int, String, Object)
createElementBefore(int)
createElementBefore(int, String, Object)
Propagating the message
About this task
Before you propagate a message, decide what message flow data you want to propagate, and whether to propagate to a node terminal, or to a Label node.
- To propagate the message to the output terminal "out":
MbOutputTerminal out = getOutputTerminal("out"); out.propagate(newAssembly);
- To propagate the message to a Label node:
MbRoute label1 = getRoute ("label1"); Label1.propagate(newAssembly);
Call the clearMessage() function within the finally block of try/catch to clear the memory that is allocated for the message tree.
MbMessage newMsg = new MbMessage(assembly.getMessage());
MbMessageAssembly newAssembly = new MbMessageAssembly(assembly, newMsg);
...
newMsg.finalizeMessage(MbMessage.FINALIZE_NONE);
out.propagate(newAssembly;
...
newMsg.finalizeMessage(MbMessage.FINALIZE_NONE);
out.propagate(newAssembly);
Declaring the node name
About this task
The name of the node must be the same as the one that is used in the IBM Integration Toolkit. All node names must end with "Node". Declare the name using the following method:
public static String getNodeName()
{
return "BasicNode";
}
- The class name is appended to the package name.
- The dots are removed, and the first letter of each part of the package and class name are capitalized.
package com.ibm.pluginsamples;
public class BasicNode extends MbNode implements MbNodeInterface
{
...
Declaring attributes
About this task
Declare node attributes in the same way as Java Bean properties. You must write getter and setter methods for the attributes. The API framework infers the attribute names using the Java Bean introspection rules. For example, if you declare the following two methods:
private String attributeVariable;
public String getFirstAttribute()
{
return attributeVariable;
}
public void setFirstAttribute(String value)
{
attributeVariable = value;
}
the integration node infers that this node has an attribute called firstAttribute. This name is derived from the names of the get or set methods, not from any internal class member variable names. Attributes can only be exposed as strings, therefore, you must convert any numeric types to and from strings in the get or set methods. For example, the following method defines an attribute called timeInSeconds:
int seconds;
public String getTimeInSeconds()
{
return Integer.toString(seconds);
}
public void setTimeInSeconds(String value)
{
seconds = Integer.parseInt(value);
}
Implementing the node functionality
About this task
The evaluate method, defined in MbNodeInterface, is called by the integration node to process the message. All the processing function for the node is included in this method.
- The MbMessageAssembly, which contains the following
objects that are accessed using the appropriate methods:
- The incoming message
- The LocalEnvironment
- The global Environment
- The ExceptionList
- The input terminal on which the message has arrived.
public void evaluate(MbMessageAssembly assembly, MbInputTerminal inTerm) throws MbException
{
// add message processing code here
getOutputTerminal("out").propagate(assembly);
}
The message flow data, which consists of the message, Environment, LocalEnvironment, and ExceptionList, is received at the input terminal of the node.
Deleting an instance of the node
About this task
- You shut down the integration node.
- You remove the node or the message flow that contains the node, and redeploy the configuration.
public void onDelete()
{
// perform node cleanup if necessary
}
This method is called by the integration node immediately before it deletes the node.