User-defined Input node life-cycle

This topic guides you through the various stages in the life of a user-defined input node written either using the C or Java programming languages. It covers the following stages in an input node's lifecycle:

C input node life-cycle

Registration

During the registration phase, the broker discovers which resources - in this case nodes - are available and which lils can provide them. The phase starts when an execution group starts. The lils are loaded on the startup of an execution group, and the broker queries them to find out what resources they can provide.

A CciFactory structure is created during the registration phase, when the user-defined node calls cniCreateNodeFactory.

APIs called by the broker during this stage:
  • biGetMessageflowNodeFactory
  • bipGetParserFactory
APIs called by the user-defined node during this stage:
  • cniCreateNodeFactory

Instantiation

An instance of a user-defined Input node is created when the mqsistart command starts or restarts the execution group process, or when a message flow associated with the node is deployed.

The following APIs are called during this phase:
  • cniCreateNodeContext. This API allocates memory for the instantiation of the user-defined node to hold the values for configured attributes. This API is called once for each message flow that is using the user-defined Input node.
  • cniCreateInputTerminal. This API is invoked within the cniCreateNodeContext API, and is used to tell the broker what input terminals, if any, your user-defined input node has.
    Note: Your user-defined input node will only have input terminals if it is also acting as a message processing node. If this is the case, it is usually better to use a separate user-defined message processing node to perform the message processing, rather than combine both operations in one, more complex, node.
  • cniCreateOutputTerminal. This API is invoked within the cniCreateNodeContext API, and is used to tell the broker what output terminals your user-defined input node has.
  • cniSetAttribute. This API is called by the broker to establish the values for the configured attributes of the user-defined node.

During this phase, a CciTerminal structure is created. This structure is created when cniCreateTerminal is called.

Processing

The processing phase begins when the cniRun function is called by the broker. The broker uses the cniRun function to determine how to process a message, including determining the domain in which a message is defined, and invoking the relevant parser for that domain.

A thread is demanded from the message flow's thread pool, and is started in the run method of the input node. The thread connects to the broker's queue manager, and retains this connection for its lifetime. When a thread has been allocated, the node enters a message processing loop while it waits to receive a message, retrying until a message is received. If the message flow is configured to use multiple threads, thread dispatching is activated.

The message data can now be propogated downstream.

The following APIs are called by the broker during this phase:
  • cniRun. This function is called by the broker to determine how to process the input message.
  • cniSetInputBuffer. This function provides an input buffer, or tells the broker where the input buffer is, and associates it with a message object.

Destruction

A user-defined input node is destroyed when the message flow is redeployed, or when mqsistop is used to stop the execution group process. You can destroy the node by implementing the cniDeleteNodeContext function.

When a user-defined input node is destroyed in one of these ways, you should free any memory used by the node, and release any held resources, such as sockets.

The following APIs are called by the broker during this phase:
  • cniDeleteNodeContext. This function is called by the broker to destroy the instance of the input node.

Java input node lifecycle

Registration

During the registration phase a user-defined Input node written in Java makes itself known to the broker. The node is registered with the broker through the static getNodeName method. Whenever a broker starts, it loads all the relevant java classes. The static method getNodeName is called at this point, and the broker registers the input node with the node name specified in the getNodeName method. If you do not specify a node name, the broker automatically creates a name for the node based on the package it is contained in.

Using a static method here means that the method can be called by the broker before the node itself is instantiated.

Instantiation

A Java User-defined input node is instantiated when a broker deploys a message flow containing the user-defined input node. When the node is instantiated, the constructor of the input node's class is called.

When a node is instantiated, any terminals you have specified using the relevant methods are created. An Input node does not have any input terminals associated with it, but it can have any number of output nodes. Output terminals include out, failure, and catch terminals. Use the createOutputTerminal method within the node class constructor to create as many output terminals as you require.

If you want to handle exceptions that are passed back to your input node, you should use createOutputTerminal to create a catch terminal for your input node. When the input node catches an error, the catch terminal will process it in the same way that a regular MQInput node would.You can allow most exceptions, such as exceptions caused by deployment problems, to pass back to the broker, however, which will warn the user of any possible configuration errors.

As a minimum, your constructor class only needs to create these output terminals on your input node. However, if you need to initialize attribute values, such as defining the parser that will initially parse a message passed from the input node, you should also include that code at this point in your input node.

Processing

Message processing for an input node begins when the broker calls the run method. The run method creates the input message, and should contain the processing function for the input node.

The run method is defined in MbInputNodeInterface, which is the interface used in a user-defined input node that defines it as an input node. You must include a run method in your node. If you do not include a run method in your user-defined input node, then the node source code will not compile.

When a message flow containing a user-defined input node is deployed successfully, the broker calls the node's run implementation method, and continues to call this method while it waits for messages to process.

When a message flow starts, a single thread is dispatched by the broker, and is called into the input node's run method. If the dispatchThread method is called, further threads can also be created in the same run method. These new threads immediately call into the input node's run method, and can be treated the same as the original thread. The number of new threads that can be created is defined by the additionalInstances attribute. You should make sure that threads are dispatched after a message has been created and before it is propagated. This ensures that only one thread at a time is waiting for a new message.

A user deploying a message flow using a user-defined input node can specify that multiple threads can be used to service the message flow. The input node is responsible for implementing the chosen threading model, but you cannot place restrictions on this ability in your code. Instead, you must ensure that your code is fully reentrant, and that any functions that your code invokes are also fully reentrant.

For more information on the threading model for User-defined Input nodes, see Threading.

Destruction

A Java user-defined input node is destroyed when the node is deleted or the broker is shut down. You do not need to include anything in your code that specifies the node should be physically deleted, because this can be handled by the garbage collector.

However, if you want to be notified that a node is about to be deleted, you can use the onDelete method. You might want to do this if there are resources other than those that will be garbage collected that you want to delete. For example, if you have opened a socket, this will not be properly closed again when the node is automatically deleted. You can include this instruction in your onDelete method to ensure that the socket is properly closed.

Related concepts
User-defined parsers
User-defined extensions

Related tasks
Creating an input node in Java
Creating an input node in C

Related reference
cniCreateInputTerminal
cniCreateNodeContext
cniCreateNodeFactory
cniRun
cniSetInputBuffer