Using the Callback Model
Overview
This chapter describes the IBM webMethods Broker callback API for receiving and processing events. Reading this chapter will help you to understand:
- How to register general and specific callback functions.
- How to define a callback function.
- How to retrieve and process events from the Broker using callback functions.
Understanding Callbacks
The callback model for processing event types allows your client application to register one or more callback functions to process event types for a Broker client.Unlike the get-events model, which can only process event types for one Broker client at a time, the callback model can receive any event type for any of your client application's Broker clients and then dispatch it to the appropriate callback function. If your client application creates several Broker clients, using the callback model frees your application from making separate calls to one of the IBM webMethods Broker get-event functions for each Broker client.
Using Callbacks
About this task
Follow these steps to use the callback processing model:
Procedure
Defining a Callback Function
All callback functions that you register must use the following function prototype:
BrokerBoolean <your_function_name_goes_here>(
BrokerClient client,
BrokerEvent event,
void *client_data);
| Value | Description |
|---|---|
| client | The client for which the event has been received. |
| event | The event that is being dispatched to this function. |
| client_data | A pointer to any data that you wish to be passed to this function when it is invoked. |
Your function should return 1 (true) if its processing
was successful or 0 (false) if
a failure occurred. If 1 (true) is
returned, the event will be acknowledged automatically. For information
on acknowledging events, see Using Sequence Numbers.
Passing Arguments to Callback Functions
When you register your callback function, you may specify a client_data pointer to any user-defined data that may be necessary for the function to complete its processing. The client_data parameter might be used to point to state information that the callback function must access and update each time it is invoked.
Assume that you want to count the number of events that your application processes. When you register your callback function, you could use the client_data pointer to point to the counter variable. When the callback is invoked, it can increment the counter.
The following example illustrates how to set up an argument for a callback function.
BrokerBoolean sample_callback(BrokerClient c, BrokerEvent e, void *counter);
long count = 0;
. . .
int main(int argc, char **argv)
{
BrokerClient c;
long n;
. . .
/* Check if can subscribe */
. . .
/* Register callback */
err = awRegisterCallbackForSubId(c, 1, sample_callback, &n);
if (err != AW_NO_ERROR) {
printf("Error on registering callback\n%s\n", awErrorToString(err));
return 0;
}
. . .
The following example illustrates how to use the client data parameter in a callback function:
BrokerBoolean sample_callback(BrokerClient c, BrokerEvent e,
void *counter)
{
/* increment counter */
(*(long*)counter)++;
/* perform rest of event processing */
. . .
}
General Callback Functions
When using the callback model, you must register a general callback function for each Broker client by calling the awRegisterCallback function. When an event is received, if there are no specific callback functions registered which match the event's subscription identifier or tag, the general callback function will be invoked to handle the event.
You may have a single callback function
process all of your application's events by making a separate awRegisterCallback call
for each BrokerClient that
your application uses, specifying the same callback function each
time.
Depending on the complexity of your design, you may find that a single, general callback function is all that your client application requires.
Using General Callbacks
The example below illustrates the use of the awRegisterCallback function to register a general callback function.
The following example illustrates how to process events with a general callback function.
. . .
BrokerBoolean sample_callback(BrokerClient c, BrokerEvent e, void *data);
. . .
/* Create a client */
. . .
/* Check if can subscribe */
. . .
/* Register a general callback */
err = awRegisterCallback(c, sample_callback, NULL);
if (err != AW_NO_ERROR) {
printf("Error on registering callback\n%s\n", awErrorToString(err));
return 0;
}
/* Open the subscription */
err = awNewSubscription(c,"Sample::SimpleEvent",NULL);
. . .
/* Do the main loop */
err = awMainLoop();
if (err != AW_NO_ERROR) {
printf("Error in main loop\n%s\n",awErrorToString(err));
return 0;
}
. . .
Specific Callback Functions
Depending on the complexity of your design, you may find that a single, general callback function is all that your client application requires. More complicated designs may need to make use of specific callback functions.
A specific callback function is only invoked to process an event with a particular subscription identifier or event tag for a particular Broker client. You may register a specific callback function by calling either the awRegisterCallbackForSubId or awRegisterCallbackForTag.
Event tag fields are part of the request-reply model, described in Using Request-Reply.
Using Specific Callbacks
The example below illustrates the use of the awRegisterCallbackForSubId function to register a specific callback function.
. . .
BrokerBoolean general_callback(BrokerClient c, BrokerEvent e,
void *data);
BrokerBoolean specific_callback(BrokerClient c, BrokerEvent e,
void *data);
/* Check if can subscribe */
. . .
/* Register a general callback */
err = awRegisterCallback(c, general_callback, NULL);
if (err != AW_NO_ERROR) {
printf("Error on registering callback\n%s\n", awErrorToString(err));
return 0;
}
/* Register a specific callback */
err = awRegisterCallbackForSubId(c, 1, specific_callback, NULL);
if (err != AW_NO_ERROR) {
printf("Error on registering callback\n%s\n", awErrorToString(err));
return 0;
}
/* Open the subscription with the ID of 1 */
err = awNewSubscriptionWithId(c, 1, "Sample::SimpleEvent",NULL);
. . .
/* Do the main loop */
err = awMainLoop();
if (err != AW_NO_ERROR) {
printf("Error in main loop\n%s\n",awErrorToString(err));
return 0;
}
. . .
Dispatching Callback Functions
After registering your subscription's callback functions, your client application should then call one of the IBM webMethods Broker dispatching functions to receive events and dispatch the appropriate callback function to process them. Only one of the following dispatching functions should be used.
Using awDispatch
The awDispatch function
may be used to wait to receive a single event for any Broker client, dispatch the event to the appropriate
callback function, and then return. The subscribe2.c and subscribe4.c sample
applications provide examples of how to use awDispatch.
Using awMainLoop
The awMainLoop function
is similar to awDispatch,
except that it enters an event loop that will continue to receive
and dispatch events until awStopMainLoop is
called. The subscribe3.c sample
application provides an example of how to use awMainLoop.
Using awThreadedCallbacks
In a multi-threaded environment, the awThreadedCallbacks function will spawn a thread that then invokes awMainLoop. This function simplifies your client application code by handling the thread creation for you.
Invoking awThreadedCallbacks(1) is identical to creating a thread and then invoking the awMainLoop method on that thread.
Invoking awThreadedCallbacks(0) is identical to invoking the awStopMainLoop method.
Event Dispatching Rules
When an event is received in the callback model, the following rules are used to dispatch the event.
- If the received event has a tag field and the tag matches a registered callback, the received event is dispatched to that callback function.
- If the received event has a subscription identifier, the event is dispatched once to each callback that matches the subscription identifier. If the event matches two event subscriptions with the same subscription identifier, the event will be dispatched twice to the callback function for that identifier.
- The received event will be dispatched
to the general callback function if the tag did not match any callback
and:
- At least one subscription identifier did not match a specific callback.
- No subscription identifiers were matched because the event was delivered.