BEA Logo BEA BEA Tuxedo Release [Release Number]

  BEA Home  |  Events  |  Solutions  |  Partners  |  Products  |  Services  |  Download  |  Developer Center  |  WebSUPPORT

 

   BEA Tuxedo Doc Home   |   Using the CORBA Notification Service   |   Previous Topic   |   Next Topic   |   Contents   |   Index

Using the BEA Simple Events API

 

This chapter describes the development steps required to create Notification Service applications using the BEA Simple Events API and the C++ and Java programming languages.

This topic includes the following sections:

 


Development Process

Table 3-1 outlines the development process for creating Notification Service applications.

Table 3-1 Development Process

Step

Description

1

Designing events

2

Writing an application that posts events

3

Writing an application that subscribes to events

4

Compiling a Notification Service application


 

These steps are explained in detail in subsequent topics.

 


Designing Events

The design of events is basic to any notification service. The design impacts not only the volume of information that is delivered to matching subscriptions, but the efficiency and performance of the Notification Service as well. Therefore, careful planning should be done to ensure that your Notification Service will be able to handle your needs now and allow for future growth. For a discussion of event design, see Designing Events.

 


Step 1: Writing an Application to Post Events

The following types of CORBA applications can post events:

Note: BEA Tuxedo 8.0 supports Java clients and joint client servers, but it does not support Java servers. Support for Java servers was previously included in versions 5.0 and 5.1 of the BEA WebLogic Enterprise product, however, that support was removed when BEA WebLogic Enterprise was merged with the BEA Tuxedo in release 8.0.

To post events, an application must, at a minimum, implement the following functions:

The following sections describe each of these functions.

Getting the Event Channel

Before the client application can post an event, it must first get the event channel.

This development step is illustrated in Listing 3-1. Listing 3-1 is based on the Notification Service sample applications that use the BEA Simple Events API.

To get the event channel factory object reference, the resolve_initial_references method is invoked on the Bootstrap object using the "Tobj_SimpleEventsService" environmental object. The object reference is used to get the channel factory, which is in turn is used to get the event channel. Listing 3-1 and Listing 3-2 show code examples in C++ and Java.

Listing 3-1 Getting the Event Channel (C++)

// Get the Simple Events channel factory object reference.
CORBA::Object_var channel_factory_oref =
bootstrap.resolve_initial_references(
"Tobj_SimpleEventsService");
Tobj_SimpleEvents::ChannelFactory_var channel_factory =
Tobj_SimpleEvents::ChannelFactory::_narrow(
channel_factory_oref.in());
// Use the channel factory to get the default channel.
Tobj_SimpleEvents::Channel_var channel =
channel_factory->find_channel(
Tobj_SimpleEvents::DEFAULT_CHANNEL);

Listing 3-2 Getting the Event Channel (Java)

// Get the Simple Event channel factory object reference.
org.omg.CORBA.Object channel_factory_oref =
bootstrap.resolve_initial_references(
"Tobj_SimpleEventsService");
// Use the channel factory to get the default channel.
ChannelFactory channel_factory =
ChannelFactoryHelper.narrow(channel_factory_oref);
Channel channel =
channel_factory.find_channel(DEFAULT_CHANNEL.value);

Creating and Posting Events

Before an event can be posted, it must be created. The following listings are based on the Notification Service sample applications.

Listing 3-3 and Listing 3-4 show how this is implemented in C++ and Java respectively. To report news to the events channel, this application executes the following steps:

  1. Creates an event and sets the domain name and type name. In the code samples, the domain name is set to "News" and the event type is set to "Sports".

  2. Adds a field to the event's filterable data to contain the story, sets the name of the added field to "Story", and the value of the field to a string containing the story.

  3. Uses the push_structured_event operation to post the event to the Notification Service.

    Listing 3-3 Creating and Posting the Event (C++)

    // Create an event.
    CosNotification::StructuredEvent notification;
    // Set the domain to "News".
    notification.header.fixed_header.event_type.domain_name =
    CORBA::string_dup("News");
    // Set the type to the news category.
    notification.header.fixed_header.event_type.type_name =
    CORBA::string_dup("Sports");
    // Add one field, which will contain the story, to the
    // event's filterable data. Set the field's name to
    // "Story" and value to a string containing the story.
    notification.filterable_data.length(1);
    notification.filterable_data[0].name =
    CORBA::string_dup("Story");
    notification.filterable_data[0].value <<= "John Smith wins again";
    // Post the event.
    // Subscribers who subscribed to events whose domain is
    // "News" and whose type matches the news category will
    // receive this event
    channel->push_structured_event(notification);

    Listing 3-4 Creating and Posting the Event (Java)

    // Create an event.
    StructuredEvent notification = new StructuredEvent();
    // Create the sub structures for the header.
    notification.header = new EventHeader();
    notification.header.fixed_header = new FixedEventHeader();
    notification.header.fixed_header.event_type = new EventType();
    // Set the domain to "News".
    notification.header.fixed_header.event_type.domain_name = "News";
    // Set the type to the news category.
    notification.header.fixed_header.event_type.type_name = "Sports";
    // Set the event name to an empty string since this sample
    // doesn't use it.
    notification.header.fixed_header.event_name = "";
    // Empty the variable header since this sample doesn't use it.
    notification.header.variable_header = new Property[0];
    // Add one field, which will contain the story, to the
    // event's filterable data. Set the field's name to
    // "Story" and value to a string containing the story.
    notification.filterable_data = new Property[1];
    notification.filterable_data[0] = new Property();
    notification.filterable_data[0].name = "Story";
    notification.filterable_data[0].value = orb.create_any();
    notification.filterable_data[0].value.insert_string(John Smith wins again");
    // Set the remainder of body to a new (empty) any since this
    // sample doesn't use the remainder of body.
    notification.remainder_of_body = orb.create_any();
    //Post the event.
    channel.push_structured_event(notification);

 


Step 2: Writing an Application to Subscribe to Events

The following types of CORBA applications can subscribe to events:

Note: BEA Tuxedo 8.0 supports Java clients and joint client servers, but it does not support Java servers. Support for Java servers was previously included in versions 5.0 and 5.1 of the BEA WebLogic Enterprise product, however, that support was removed when BEA WebLogic Enterprise was merged with the BEA Tuxedo in release 8.0.

To subscribe to events, an application must, at a minimum, implement the following functions:

Implementing the CosNotifyComm::StructuredPushConsumer Interface

In order for the callback object to receive events, it must implement the CosNotifyComm::StructuredPushConsumer interface that supports the push_structured_event operation. When an event occurs that has a matching subscription, the Notification Service invokes this operation on the callback object to push the event to the subscriber application.

The CosNotifyComm::StructuredPushConsumer interface also defines the operations offer_change and disconnect_structured_push_consumer. The Notification Service never invokes these operations, so you should implement stubbed out versions that throw CORBA::NO_IMPLEMENT.

Listing 3-5 and Listing 3-6 show how this interface is implemented in C++.

Listing 3-5 Sample CosNotifyComm::StructuredPushConsumer Interface Implementation (NewsConsumer_i.h)

#ifndef _news_consumer_i_h
#define _news_consumer_i_h
#include "CosNotifyComm_s.h"
// For the servant class to receive news events,
// it must implement the CosNotifyComm::StructuredPushConsumer
// idl interface.
class NewsConsumer_i : public POA_CosNotifyComm::StructuredPushConsumer
{
public:
    // This method will be called when a news event occurs.
    virtual void push_structured_event(
const CosNotification::StructuredEvent& notification
);
    // OMG's CosNotifyComm::StructuredPushConsumer idl
// interface defines the methods "offer_change" and
// "disconnect_structured_push_consumer". Since the
// Notification Service never invokes these methods, just
// have them throw a CORBA::NO_IMPLEMENT exception
    virtual void offer_change(
const CosNotification::EventTypeSeq& added,
const CosNotification::EventTypeSeq& removed )
{
throw CORBA::NO_IMPLEMENT();
}
    virtual void disconnect_structured_push_consumer()
{
throw CORBA::NO_IMPLEMENT();
}
};
#endif

Listing 3-6 Sample CosNotifyComm::StructuredPushConsumer Interface Implementation (NewsConsumer_i.cpp)

#include "NewsConsumer_i.h"
#include <iostream.h>
//-----------------------------------------------------------
// Subscriber.cpp creates a simple events subscription to "News"
// events and has the events delivered to a NewsConsumer_i
// object. When a news event occurs (this happens when a user
// runs the Reporter application and reports a news story), this
// method will be invoked:
void NewsConsumer_i::push_structured_event(
const CosNotification::StructuredEvent& notification )
{
// Extract the story from the first field in the event's
// filterable data.
char* story;
notification.filterable_data[0].value >>= story;
// For coding simplicity, assume "story" is not "null".
// Print out the event.
cout
<< "-----------------------------------------------------"
<< endl
<< "Category : "
<< notification.header.fixed_header.
event_type.type_name.in()
<< endl
<< "Story : "
<< story
<< endl;
...
}

Getting the Event Channel

This step is the same for event posters and event subscribers. For a discussion of this step, see Implementing the CosNotifyComm::StructuredPushConsumer Interface.

Creating a Callback Object

To receive events, the application must also be a server; that is, the application must implement a callback object that can be invoked (called back) when an event occurs that matches the subscriber's subscription.

Creating a callback object includes the following steps:

Note: The following steps apply to a BEA Tuxedo CORBA joint client/server. BEA Tuxedo CORBA servers can also subscribe to events.

  1. Create a callback object. Callback objects can be implemented using either the BEAWrapper Callback API or the CORBA Portable Object Adaptor (POA).

  2. Create the servant.

  3. Create an object reference to the callback servant.

For a complete description of the BEAWrapper Callbacks object and its methods, see the Joint Client/Servers chapter in the CORBA Programming Reference.

Note: Using the BEAWrapper Callback object to create a callback object is discussed below. For a discussion of how to implement a callback object using the POA, see Using CORBA Server-to-Server Communication.

Listing 3-7 shows how to use the BEAWrapper Callbacks object to create a callback object in C++ and Java respectively. In the code examples, the NewsConsumber_i servant is created and the start_transient method is used to create a transient object reference.

Listing 3-7 Sample Code for Creating a Callback Object With Transient Object Reference (Introductory Application Subscriber.cpp)

// Create a callback wrapper object since this client needs to
// support callbacks.
BEAWrapper::Callbacks wrapper(orb.in());
NewsConsumer_i* news_consumer_impl = new NewsConsumer_i;
CORBA::Object_var news_consumer_oref =
wrapper.start_transient(
news_consumer_impl,
CosNotifyComm::_tc_StructuredPushConsumer->id()
);
CosNotifyComm::StructuredPushConsumer_var
news_consumer =
CosNotifyComm::StructuredPushConsumer::_narrow(
news_consumer_oref.in()
);

Creating a Subscription

In order for the subscriber to receive events, it must subscribe to the Notification Service. You can create either a transient subscription or a persistent subscription.

Listing 3-8 which is from the Introductory sample application, show how to create a transient subscription in C++ and Java respectively.

The following steps must be performed:

  1. Set the subscription's quality of service (QoS) to either transient or persistent.

  2. Determine the subscription_name (optional), domain_name, type_name, and data_filter (optional).

  3. Create the subscription. The subscription sets the domain_name, type_name, and data_filter (optional), the Quality of Service (QoS), and supplies the object reference to the subscriber's callback object to the Notification Service.

    Listing 3-8 Creating a Transient Subscription (C++)

    // Set the quality of service to TRANSIENT.
    CosNotification::QoSProperties qos;
    qos.length(1);
    qos[0].name =
    CORBA::string_dup(Tobj_SimpleEvents::SUBSCRIPTION_TYPE);
    qos[0].value <<=
    Tobj_SimpleEvents::TRANSIENT_SUBSCRIPTION;
    // Set the type to the news category.
    const char* type = "Sports";
    // Create the subscription. Set the domain to "News" and
    // the data filter to age greater than 30.
    Tobj_SimpleEvents::SubscriptionID subscription_id =
    channel->subscribe(
    subscription_name,
    "News", // domain
    "Sports", // type
    "Age > 30", // Data filter.
    qos,
    news_consumer.in()
    );

Note: When you use data filtering, you must also perform some configuration tasks. For a discussion of data filtering configuration requirements, see Configuring Data Filters.

Listing 3-9 shows code in the Advanced sample application in C++ and Java, illustrates the coding steps required to create a persistent subscription to the Notification Service. The steps required to create a persistent subscription are the same as those required to create a transient subscription, as described previously.

Note: While the code examples shown here assume that the news_consumer callback object has a persistent object reference, you can also create persistent subscriptions with transient callback object references. For a discussion of transient versus persistent callback object references, see Table 2-3.

Listing 3-9 Creating a Persistent Subscription (Advanced Subscriber.cpp)

CosNotification::QoSProperties qos;
qos.length(1);
qos[0].name =
CORBA::string_dup(Tobj_SimpleEvents::SUBSCRIPTION_TYPE);
qos[0].value <<= Tobj_SimpleEvents::PERSISTENT_SUBSCRIPTION;
CosNotifyComm::StructuredPushConsumer_var
news_consumer =
CosNotifyComm::StructuredPushConsumer::_narrow(
news_consumer_oref.in()
);
Tobj_SimpleEvents::SubscriptionID sub_id =
channel->subscribe(
subscription_info.subscription_name(),
"News", // domain
"Sports", // type
"", // No data filter.
qos,
news_consumer.in()
)
);

Threading Considerations for C++ Joint Client/Server Applications

A joint client/server application may first function as a client application and then switch to functioning as a server application. To do this, the joint client/server application turns complete control of the thread to the Object Request Broker (ORB) by making the following invocation:

orb -> run();

If a method in the server portion of a joint client/server application invokes ORB::shutdown(), all server activity stops and control is returned to the statement after ORB::run() is invoked in the server portion of the joint client/server application. Only under this condition does control return to the client functionality of the joint client/server application.

Since a client application has only a single thread, the client functionality of the joint client/server application must share the central processing unit (CPU) with the server functionality of the joint client/server application. This sharing is accomplished by occasionally checking with the ORB to see if the joint client/server application has server application work to perform. Use the following code to perform the check with the ORB:

if ( orb->work_pending() ) orb->perform_work();

After the ORB completes the server application work, the ORB returns to the joint client/server application, which then performs client application functions. The joint client/server application must remember to occasionally check with the ORB; otherwise, the joint client/server application will never process any invocations.

You should be aware that the ORB cannot service callbacks while the joint client/server application is blocking on a request. If a joint client/server application invokes an object in another BEA Tuxedo CORBA server application, the ORB blocks while it waits for the response. While the ORB is blocking, it cannot service any callbacks, so the callbacks are queued until the request is completed.

 


Step 3: Compiling and Running Notification Service Applications

The final step in the development of a Notification Service application is to compile, build, and run the application. To do this, you need to perform the following steps.

  1. Generate the required client stub and skeleton files to define interfaces between the Notification Service and event poster and subscriber applications. Event poster applications can be clients, joint client/servers, or servers. Event subscriber applications can be joint client/servers or servers.

  2. Compile the application code and link against the skeleton and client stub files.

  3. Build the application.

  4. Run the application.

Generating the Client Stub and Skeleton Files

To generate the client stub and skeleton files, you must execute the idl command for each of the Notification IDL files that your application uses. Table 3-2 shows the idl commands used for each type of subscriber.

Table 3-2 idl Command Requirements

Language

BEA Tuxedo CORBA Joint Client/Server

BEA Tuxedo CORBA Server

C++

idl -P

idl

Java

idltojava

Not supported in BEA Tuxedo 8.0 and later


 

The following is an example of an idl command:

>idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl

Table 3-3 lists the IDL files required by each type of Notification Service application that uses the BEA Simple Events Interface.

Table 3-3 IDL Files Required by Notification Service Applications

Application Type

Required OMG IDL Files

Event poster (can be a client, a joint client/server, or a server). (Stubs are required for all files.)

CosEventComm.idl CosNotification.idl CosNotifyComm.idl Tobj_Events.idl Tobj_SimpleEvents.idl

Subscriber (can be a server or a joint client/server). (Stubs are required for all files. Skeleton is required for the CosNotifyComm.idl file.)

CosEventComm.idl CosNotification.idl CosNotifyComm.idl Tobj_Events.idl Tobj_SimpleEvents.idl

Building and Running Applications

The build procedure differs depending on the type of Notification Service application you are building. Table 3-4 provides an overview of the commands and types of files used to build each type of the Notification Service application.

Table 3-4 Application Build Requirements

Application Type

Client

Joint Client/Server

Server

C++ Events Poster

Use the buildobjclient command to compile the application files and the IDL stubs.

Use the buildobjclient command with the -P option to compile the application files and the IDL stubs.

Use the buildobjserver command to compile the application files and the IDL client stubs.

C++ Events Subscriber

Not applicable.

Use the buildobjclient command with the -P option to compile the application files, the IDL stubs, the IDL skeletons, and link with the BEAWrapper library.

Use the buildobjserver command to compile the application files, the IDL stubs, and the IDL skeletons.

Java Events Poster

Use the javac command to compile the application files and the IDL stubs.

Use the javac command to compile the application files and the IDL files.

Not supported in BEA Tuxedo 8.0 and later.

Java Events Subscriber

Not applicable.

Use the javac command to compile the application files, the IDL files, and the IDL skeletons.

Not supported in BEA Tuxedo 8.0 and later.


 

Listing 3-10 shows the commands used for a C++ poster application (Reporter.cpp) on a Microsoft Windows system. To form a C++ executable, the idl command is run on the required IDL file and the buildobjclient command compiles the C++ client application file and the IDL stubs.

Listing 3-10 C++ Reporter Application Build and Run Commands (Microsoft Windows)

# Run the idl command.
idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\Tobj_Events.idl \
C:\tuxdir\include\Tobj_SimpleEvents.idl
# Run the buildobjclient command.
buildobjclient -v -o subscriber.exe -f " \
-DWIN32 \
Reporter.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \
"
# Run the application.
is_reporter

Listing 3-11 and Listing 3-12 show the commands used for a C++ subscriber application (Subscriber.cpp) on Microsoft Windows and UNIX respectively. To form a C++ executable, the buildobjclient command, with the -P option, compiles the joint client/server application files (Subscriber.cpp and NewsConsumer_i.cpp), the IDL stubs, and the IDL skeleton (CosNotifyComm_s.cpp).

Listing 3-11 C++ Subscriber Application Build and Run Commands (Microsoft Windows)

# Run the idl command.
idl -P -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\Tobj_Events.idl \
C:\tuxdir\include\Tobj_SimpleEvents.idl
# Run the buildobjclient command.
buildobjclient -v -P -o subscriber.exe -f " \
-DWIN32 \
Subscriber.cpp \
NewsConsumer_i.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \ c:\tuxdir\lib\libbeawrapper.lib \
"
# Run the application.
is_subscriber

Listing 3-12 C++ Subscriber Application Build and Run Commands (UNIX)

# Run the idl command.
idl -P -I/usr/local/tuxdir/include /usr/local/tuxdir/include/CosEventComm.idl \
/usr/local/tuxdir/include/CosNotification.idl \
/usr/local/tuxdir/include/CosNotifyComm.idl \
/usr/local/tuxdir/include/Tobj_Events.idl \
/usr/local/tuxdir/include/Tobj_SimpleEvents.idl
# Run the buildobjclient command.
buildobjclient -v -P -o subscriber -f " \
Subscriber.cpp \
NewsConsumer_i.cpp \
CosEventComm_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \
-lbeawrapper \
"
# Run the application.
is_subscriber

Listing 3-13 shows an example of the commands used to link, build, and run remote Java poster applications.

Listing 3-13 Java Reporter Application Link, Build, and Run Commands

# Run the idltojava command.
idltojava -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosNotification.idl C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\Tobj_Events.idl C:\tuxdir\include\Tobj_SimpleEvents.idl
# Compile the java files.
javac -classpath C:\tuxdir\udataobj\java\jdk\m3envobj.jar Reporter.java
# Combine the java .class files into the java archive (JAR) file.
jar cf reporter.jar Reporter.class org\omg\CosEventComm \
org\omg\CosNotification org\omg\CosNotifyComm \
com\beasys\Tobj_Events com\beasys\Tobj_SimpleEvents
# Run the reporter application.
java -DTOBJADDR=//BEANIE:2359 -classpath \
reporter.jar;C:\tuxdir\udataobj\java\jdk\m3envobj.jar Reporter

 

back to top previous page next page