See information about the latest product version
Creating an input node in C
Create a user-defined input node in C to receive messages into a message flow.
A loadable implementation library, or LIL, is the implementation module for a C node. A LIL is implemented as a shared or dynamic link library (DLL), but has the file extension .lil not .dll.
The implementation functions that you write for the node are listed in C node implementation functions. You can call utility functions, implemented in the runtime broker, to help with the node operation; these functions are listed in C node utility functions.
WebSphere® Message Broker 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.
Declaring and defining the node
To declare and define a user-defined node to the broker, include an initialization function, bipGetMessageflowNodeFactory, in your LIL. The following steps outline how the broker calls your initialization function, and how your initialization function declares and defines the user-defined node:
Creating an instance of the node
To instantiate your node:
Setting attributes
Attributes are set whenever you start the broker, or when you redeploy the message flow with new values.
{
const CciChar* ucsAttr = CciString("nodeTraceSetting", BIP_DEF_COMP_CCSID) ;
insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_INTEGER);
_setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constZero);
free((void *)ucsAttr) ;
}
{
const CciChar* ucsAttr = CciString("nodeTraceOutfile", BIP_DEF_COMP_CCSID) ;
insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_STRING);
_setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constSwitchTraceLocation);
free((void *)ucsAttr) ;
}
- label
- userTraceLevel
- traceLevel
- userTraceFilter
- traceFilter
Implementing the node functionality
When the broker knows that it has an input node, it calls the cniRun function of this node at regular intervals. The cniRun function must then decide what course of action it must take. If data is available for processing, the cniRun function can propagate the message. If no data is available for processing, the cniRun function must return with CCI_TIMEOUT so that the broker can continue configuration changes.
If ( anything to do )
CniDispatchThread;
/* do the work */
If ( work done O.K.)
Return CCI_SUCCESS_CONTINUE;
Else
Return CCI_FAILURE_CONTINUE;
Else
Return CCI_TIMEOUT;
Overriding the default message parser attributes (optional)
An input node implementation typically determines what message parser initially parses an input message. For example, the MQInput node dictates that an MQMD parser is required to parse the MQMD header. A user-defined input node can select an appropriate header or message parser, and the mode in which the parsing is controlled, by using or overriding the following attributes that are included as default:
- rootParserClassName
- Defines the name of the root parser that parses message formats that are supported by the user-defined input node. It defaults to GenericRoot, a supplied root parser that causes the broker to allocate and chain parsers together. It is unlikely that a node would need to modify this attribute value.
- firstParserClassName
- Defines the name of the first parser, in what might be a chain of parsers that are responsible for parsing the bit stream. It defaults to XML.
- messageDomainProperty
- An optional attribute that defines the name of the message parser that is required to parse the input message. The supported values are the same as the values that are supported by the MQInput node. (See MQInput node for more information.)
- messageSetProperty
- An optional attribute that defines the message set identifier, or the message set name, in the Message Set field, only if the MRM parser was specified by the messageDomainProperty attribute.
- messageTypeProperty
- An optional attribute that defines the identifier of the message in the MessageType field, only if the MRM parser was specified by the messageDomainProperty attribute.
- messageFormatProperty
- An optional attribute that defines the format of the message in the Message Format field, only if the MRM parser was specified by the messageDomainProperty attribute.
- Declare the implementation functions:
CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix bipGetMessageflowNodeFactory() { .... CciFactory* factoryObject; .... factoryObject = cniCreateNodeFactory(0, (unsigned short *)constPluginNodeFactory); ... vftable.iFpCreateNodeContext = _createNodeContext; vftable.iFpSetAttribute = _setAttribute; vftable.iFpGetAttribute = _getAttribute; ... cniDefineNodeClass(&rc, factoryObject, (CciChar*)constSwitchNode, &vftable); ... return(factoryObject); }
- Set the attribute in the cniCreateNodeContext implementation
function:
In the code example above, the insAttrTblEntry method is called. This method is declared in the SwitchNode and TransformNode sample user-defined nodes.CciContext* _createNodeContext( CciFactory* factoryObject, CciChar* nodeName, CciNode* nodeObject ){ NODE_CONTEXT_ST* p; ... /* Allocate a pointer to the local context */ p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST)); /* Create attributes and set default values */ { const CciChar* ucsAttrName = CciString("firstParserClassName", BIP_DEF_COMP_CCSID); const CciChar* ucsAttrValue = CciString("MYPARSER", BIP_DEF_COMP_CCSID) ; insAttrTblEntry(p, (CciChar*)ucsAttrName, CNI_TYPE_INTEGER); /*see sample BipSampPluginNode.c for implementation of insAttrTblEntry*/ _setAttribute(p, (CciChar*)ucsAttrName, (CciChar*)ucsAttrValue); free((void *)ucsAttrName) ; free((void *)ucsAttrValue) ; }
Deleting an instance of the node
Nodes are destroyed when a message flow is redeployed, or when the execution group process is stopped (using the mqsistop command). When a node is destroyed, you must call the cniDeleteNodeContext function to free all used memory and release all held resources. For example:
void _deleteNodeContext(
CciContext* context
){
static char* functionName = (char *)"_deleteNodeContext()";
return;
}