分类: C/C++
2008-09-27 18:44:15
This topic includes the following sections:
Note: | The BEA Tuxedo CORBA Java client and BEA Tuxedo CORBA Java client ORB were deprecated in Tuxedo 8.1 and are no longer supported. All BEA Tuxedo CORBA Java client and BEA Tuxedo CORBA Java client ORB text references, associated code samples, should only be used to help implement/run third party Java ORB libraries, and for programmer reference only. |
Note: | Technical support for third party CORBA Java ORBs should be provided by their respective vendors. BEA Tuxedo does not provide any technical support or documentation for third party CORBA Java ORBs. |
outlines the development process for creating Notification Service applications.
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.
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 .
The following types of CORBA applications can post events:
To post events, an application must, at a minimum, implement the following functions:
The following sections describe each of these functions.
Before the client application can post an event, it must get the event channel.
This development step is illustrated in . is code from the Reporter.cpp
file in the Introductory sample application that uses the CosNotification Service API.
To get the event channel factory object reference, the resolve_initial_references
method is invoked on the Bootstrap object using the "NotificationService"
environmental object. The object reference is used to get the channel
factory, which is, in turn, is used to get the event channel. shows code examples in C++.
// Get the CosNotification channel factory object reference.
CORBA::Object_var channel_factory_oref =
bootstrap.resolve_initial_references(
"NotificationService" );
CosNotifyChannelAdmin::EventChannelFactory_var
channel_factory =
CosNotifyChannelAdmin::EventChannelFactory::_narrow(
channel_factory_oref.in() );
// use the channel factory to get the default channel
CosNotifyChannelAdmin::EventChannel_var channel =
channel_factory->get_event_channel(
Tobj_Notification::DEFAULT_CHANNEL );
To post events, you must get the SupplierAdmin object, use it to create a proxy, create the event, and then post the event to the proxy.
shows how this is implemented in C++.
// Since we are a supplier (that is, we post events),
// get the SupplierAdmin object
CosNotifyChannelAdmin::SupplierAdmin_var supplier_admin =
channel->default_supplier_admin();
// Use the supplier admin to create a proxy. Events are posted
// to the proxy (unlike the simple events interface where events
// are posted to the channel).
CosNotifyChannelAdmin::ProxyID proxy_id;
CosNotifyChannelAdmin::ProxyConsumer_var generic_proxy_consumer =
supplier_admin->obtain_notification_push_consumer(
CosNotifyChannelAdmin::STRUCTURED_EVENT, proxy_id );
CosNotifyChannelAdmin::StructuredProxyPushConsumer_var
proxy_push_consumer =
CosNotifyChannelAdmin::StructuredProxyPushConsumer::_narrow(
generic_proxy_consumer );
// Connect to the proxy so that we can post events.
proxy_push_consumer->connect_structured_push_supplier(
CosNotifyComm::StructuredPushSupplier::_nil() );
...
// 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
proxy_push_consumer->push_structured_event(notification);
...
// Disconnect.
proxy_push_consumer->disconnect_structured_push_consumer();
The following types of CORBA applications can subscribe to events:
To subscribe to events, an application must, at a minimum, support the following functions:
push_structured_event
operation.CosNotifyComm::StructuredPushConsumer
interface.In order for the callback
servant 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 servant callback
object in the subscriber application to deliver 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
.
and show how this interface is implemented in C++.
#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
#include "NewsConsumer_i.h"
#include
//-----------------------------------------------------------
// 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;
...
}
Before an application can create a subscription, it must get the event channel and the ConsumerAdmin and Filter Factory objects. shows how this is implemented in C++.
To get the event channel factory object reference, the resolve_initial_references
method is invoked on the Bootstrap object using the "NotificationService"
environmental object. The object reference is used to get the channel
factory, which is, in turn, used to get the event channel. Finally, the
event channel is used to get the ConsumerAdmin object and the
FilterFactory object.
// Get the CosNotification channel factory object reference.
CORBA::Object_var
channel_factory_oref =
bootstrap.resolve_initial_references(
"NotificationService" );
CosNotifyChannelAdmin::EventChannelFactory_var
channel_factory =
CosNotifyChannelAdmin::EventChannelFactory::_narrow(
channel_factory_oref.in() );
// Use the channel factory to get the default channel.
CosNotifyChannelAdmin::EventChannel_var channel =
channel_factory->get_event_channel(
Tobj_Notification::DEFAULT_CHANNEL );
// Use the channel to get the consumer admin and the filter factory.
CosNotifyChannelAdmin::ConsumerAdmin_var consumer_admin =
channel->default_consumer_admin();
CosNotifyFilter::FilterFactory_var filter_factory =
channel->default_filter_factory();
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 joint client/server. BEA Tuxedo CORBA servers can also subscribe to events. |
For a complete description of the BEAWrapper Callbacks object and its methods, see the Joint Client/Servers chapter in the .
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 . |
shows how to use the BEAWrapper Callbacks object to create a callback object in C++. In the code examples, the NewsConsumber_i servant
is created and the start_transient
method is used to create a transient object reference.
// 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;
// Create a transient object reference to this servant.
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() );
In order for the subscriber to receive events, it must subscribe to the Notification Service. You can create a transient subscription or a persistent subscription.
To create a subscription, the following steps must be performed:
domain_name
, type_name
, and data_filter
(optional) to it.from the Introductory sample application, shows how to create a transient subscription in C++.
// Create a new subscription (at this point, it is not complete).
CosNotifyChannelAdmin::ProxyID subscription_id;
CosNotifyChannelAdmin::ProxySupplier_var generic_subscription =
consumer_admin->obtain_notification_push_supplier(
CosNotifyChannelAdmin::STRUCTURED_EVENT,
subscription_id );
CosNotifyChannelAdmin::StructuredProxyPushSupplier_var
subscription =
CosNotifyChannelAdmin::StructuredProxyPushSupplier::_narrow(
generic_subscription );
s_subscription = subscription.in();
// Set the quality of service. This sets the subscription name
// and subscription type (=TRANSIENT).
CosNotification::QoSProperties qos;
qos.length(2);
qos[0].name =
CORBA::string_dup(Tobj_Notification::SUBSCRIPTION_NAME);
qos[0].value <<= subscription_name;
qos[1].name =
CORBA::string_dup(Tobj_Notification::SUBSCRIPTION_TYPE);
qos[1].value <<=
Tobj_Notification::TRANSIENT_SUBSCRIPTION;
subscription->set_qos(qos);
// Create a filter (used to specify domain, type and data filter).
CosNotifyFilter::Filter_var filter =
filter_factory->create_filter(
Tobj_Notification::CONSTRAINT_GRAMMAR );
s_filter = filter.in();
// Set the filtering parameters.
// (domain = "News", type = "Sports", and no data filter)
CosNotifyFilter::ConstraintExpSeq constraints;
constraints.length(1);
constraints[0].event_types.length(1);
constraints[0].event_types[0].domain_name =
CORBA::string_dup("News");
constraints[0].event_types[0].type_name =
CORBA::string_dup("Sports");
constraints[0].constraint_expr =
CORBA::string_dup(""); // No data filter.
CosNotifyFilter::ConstraintInfoSeq_var
add_constraints_results = // ignore this returned value
filter->add_constraints(constraints);
// Add the filter to the subscription.
CosNotifyFilter::FilterID filter_id =
subscription->add_filter(filter.in());
// Now that we have set the subscription name, type and filtering
// parameters, complete the subscription by passing in the
// reference of the callback object to deliver the events to.
subscription->connect_structured_push_consumer(
news_consumer.in() );
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.
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. shows the idl
commands used for each type of subscriber.
Language
|
BEA Tuxedo CORBA Joint Client/Server
|
BEA Tuxedo CORBA Server
|
---|---|---|
C++
|
idl -P
|
idl
|
The following is an example of an idl
command:
>idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl
lists the IDL files required by each type of Notification Service application.
Application Type
|
Required OMG IDL Files
|
---|---|
Event poster (can be a client, a joint client/server, or a server)
|
CosEventChannelAdmin.idl CosEventComm.idl CosNotification.idl CosNotifyChannelAdmin
CosNotifyComm.idl CosNotifyFilter Tobj_Events.idl Tobj_Notification.idl |
Subscriber (can be joint client/server or a server)
|
CosEventChannelAdmin.idl CosEventComm.idl CosNotification.idl
CosNotifyChannelAdmin CosNotifyComm.idl CosNotifyFilter Tobj_Events.idl
Tobj_Notification.idl
|
The compiling and linking procedure differs depending on the type of Notification Service application you are building. provides an overview of the commands and files used to compile each type of application.
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, and the IDL skeletons.
|
Use the
buildobjserver command to compile the application files, the IDL stubs, and the IDL skeletons.
|
shows the commands used for a C++ Reporter 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.
# Run the idl command.
idl -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosEventChannelAdmin \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\CosNotifyFilter.idl \
C:\tuxdir\include\Tobj_Notification.idl
# Run the buildobjclient command.
buildobjclient -v -o is_reporter.exe -f "\
-DWIN32 \
Reporter.cpp \
CosEventComm_c.cpp \
CosEventChannelAdmin_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyFilter_c.cpp \
CosNotifyChannelAdmin_c.cpp \
Tobj_Events_c.cpp \
Tobj_Notification_c.cpp "
# Run the application.
is_reporter
and 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, the IDL skeleton (for CosNotifyComm_s.cpp
).
# Run the idl command.
idl -P -IC:\tuxdir\include C:\tuxdir\include\CosEventComm.idl \
C:\tuxdir\include\CosEventChannelAdmin \
C:\tuxdir\include\CosNotification.idl \
C:\tuxdir\include\CosNotifyComm.idl \
C:\tuxdir\include\CosNotifyFilter.idl \
C:\tuxdir\include\CosNotifyChannelAdmin \ \C:\tuxdir\include\Tobj_Events.idl \
\C:\tuxdir\include\Tobj_Notification
# Run the buildobjclient command.
buildobjclient -v -P -o is_subscriber.exe -f " \
-DWIN32 \
Subscriber.cpp \
NewsConsumer_i.cpp \
CosEventComm_c.cpp \
CosEventChannelAdmin_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
CosNotifyFilter_c.cpp \
CosNotifyChannelAdmin_c.cpp \
Tobj_Events_c.cpp \
Tobj_Notification_c.cpp \
C:\tuxdir\lib\libbeawrapper.lib \
"
# Run the application.
is_subscriber
# Run the idl command.
idl -P -I/usr/local/tuxdir/include /usr/local/tuxdir/include/CosEventChannelAdmin \
/usr/local/tuxdir/include/CosEventComm.idl \
/usr/local/tuxdir/include/CosNotification.idl \
/usr/local/tuxdir/include/CosNotifyComm.idl \
/usr/local/tuxdir/include/CosNotifyFilter.idl \
/usr/local/tuxdir/include/CosNotifyChannelAdmin \
/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 \
CosEventChannelAdmin_c.cpp \
CosNotification_c.cpp \
CosNotifyComm_c.cpp \
CosNotifyComm_s.cpp \
CosNotifyFilter_c.cpp \
CosNotifyChannelAdmin_c.cpp \
Tobj_Events_c.cpp \
Tobj_SimpleEvents_c.cpp \
-lbeawrapper \
"
# Run the application.
is_subscriber