![]() ![]() ![]() ![]() ![]() ![]() ![]() |
This chapter describes programming requirements for CORBA joint client/servers and the C++ BEAWrapper Callbacks API.
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 in Tuxedo 9.x. All BEA Tuxedo CORBA Java client and BEA Tuxedo CORBA Java client ORB text references, associated code samples, etc. should only be used: |
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. |
This topic includes the following sections:
For either a BEA Tuxedo CORBA client or joint client/server (that is, a client that can receive and process object invocations), the programmer writes the client main(). The main()
uses BEA Tuxedo CORBA environmental objects to establish connections, set up security, and start transactions.
BEA Tuxedo clients invoke operations on objects. In the case of DII, client code creates the DII Request object and then invokes one of two operations on the DII Request. In the case of static invocation, client code performs the invocation by performing what looks like an ordinary invocation (which ends up calling code in the generated client stub). Additionally, the client programmer uses ORB interfaces defined by OMG, and BEA Tuxedo CORBA environmental objects that are supplied with the BEA Tuxedo software, to perform functions unique to BEA Tuxedo.
For BEA Tuxedo joint client/server applications, the client code must be structured so that it can act as a server for callback BEA Tuxedo objects. Such clients do not use the TP Framework and are not subject to BEA Tuxedo system administration. Besides the programming implications, this means that CORBA joint client/servers do not have the same scalability and reliability as BEA Tuxedo CORBA servers, nor do they have the state management and transaction behavior available in the TP Framework. If a user wants to have those characteristics, the application must be structured in such a way that the object implementations are in a BEA Tuxedo CORBA server, rather than in a client.
The following sections describe the mechanisms you use to add callback support to a BEA Tuxedo client. In some cases, the mechanisms are contrasted with the BEA Tuxedo server mechanisms that use the TP Framework.
In a BEA Tuxedo server, you use the buildobjserver
command to create the main program for the C++ server. (Java servers are not supported in release 8.0 and later of BEA Tuxedo.) Server main program takes care of all BEA Tuxedo- and CORBA-related initialization of the server functions. However, since you implement the Server object, you have an opportunity to customize the way in which the server application is initialized and shut down. The server main program automatically invokes methods on the Server object at the appropriate times.
In contrast, for a BEA Tuxedo CORBA joint client/server (as for a BEA Tuxedo CORBA client), you create the main program and are responsible for all initialization. You do not need to provide a Server object because you have complete control over the main program and you can provide initialization and shutdown code in any way that is convenient.
The specific initialization needed for a joint client/server is discussed in the section Servants.
Servants (method code) for joint client/servers are very similar to servants for servers. All business logic is written the same way. The differences result from not using the TP Framework. Therefore, the main difference is that you use CORBA functions directly instead of indirectly through the TP Framework.
The Server
interface is used in BEA Tuxedo CORBA servers to allow the TP Framework to ask the user to create a servant for an object when the ORB receives a request for that object. However, in joint client/servers, the user program is responsible for creating a servant before any requests arrive; thus, the Server
interface is not needed. Typically, the program creates a servant and then activates the object (using the servant and an ObjectId
; the ObjectId
is possibly system generated) before handing a reference to the object. Such an object might be used to handle callbacks. Thus, the servant already exists and the object is activated before a request for the object arrives.
For C++ joint client/servers, instead of invoking the TP
interface to perform certain operations, client servants directly invoke the ORB and POA (which is what the TP
interface does internally). Alternately, since much of the interaction with the ORB and POA is the same for all applications, for ease of use, the client library provides a convenience wrapper object that does the same things, using a single operation. For a discussion of how to use the convenience wrapper object, see Callback Object Models Supported and Preparing Callback Objects Using BEAWrapper Callbacks.
In a client that supports callbacks, as well as in a server, you write a implementation class that inherits from the same skeleton class name generated by the IDL compiler (the idl
command).
The following is a C++ example, given the IDL:
interface Hospital{ … };
The skeleton generated by the idl
command contains a “skeleton” class, POA_Hospital
, that the user-written class inherits from, as in:
class Hospital_i : public POA_Hospital { ... };
In a server, the skeleton class inherits from the TP Framework class Tobj_ServantBase
, which in turn inherits from the predefined PortableServer::ServantBase
.
The inheritance tree for a callback object implementation in a joint client/server is different than that in a server. The skeleton class does not inherit from the TP Framework class Tobj_ServantBase
, but instead inherits directly from PortableServer::ServantBase
. This behavior is achieved by specifying the -P
option in the idl
command.
Not having the Tobj_ServantBase
class in the inheritance tree for a servant means that the servant does not have activate_object
and deactivate_object
methods. In a server, these methods are called by the TP Framework to dynamically initialize and save a servant’s state before invoking a method on the servant. For a client that supports callbacks, you must write code that explicitly creates a servant and initializes a servant’s state.
BEA Tuxedo CORBA supports four kinds of callback objects and provides wrappers for the three that are most common. These objects correspond to three combinations of POA policies. The POA policies control both the types of objects and the types of object references that are possible.
The POA policies that are applicable are:
These objects are explained primarily in terms of their behavioral characteristics rather than in details about how the ORB and the POA handle them. Those details are discussed in the next sections, using either direct ORB and POA calls (which requires a little extra knowledge of CORBA servers) or using the BEAWrapper Callbacks interface, which hides the ORB and POA calls (for users who do not care about the details).
ObjectId
is not assigned by the client application, but is a unique value assigned by the system. This type of object is useful for invocations that a client wants to receive only until the client terminates. (The corresponding POA LifeSpanPolicy value is TRANSIENT
and the IdAssignmentPolicy is SYSTEM_ID
.) ObjectId
is not assigned by the client application, but is a unique value assigned by the system. This type of object and object reference is useful when the client goes up and down over a period of time. When the client is up, it can receive callback objects on that particular object reference. PERSISTENT
and SYSTEM_ID
.)ObjectId
has to be assigned by the client application. Such an ObjectId
might be, for example, a database key meaningful only to the client. (The corresponding POA policy values are PERSISTENT
and USER_ID
.)Notes: | The Transient/UserId policy combination is not considered particularly important. It is possible for users to provide for themselves by using the POA in a manner analogous to either of the persistent cases, but the BEA Tuxedo wrappers do not provide special help to do so. |
Note: | For BEA Tuxedo CORBA native joint client/servers, neither of the Persistent policies is supported, only the Transient policy. |
In order for a BEA Tuxedo server to call remote joint client/server objects, that is, joint client/server objects located outside the BEA Tuxedo domain, the server must be configured to enable outbound IIOP. This capability is enabled by specifying the -O
(uppercase letter O) option in the IIOP Server Listener (ISL) server command. Setting the -O
option enables outbound invokes (outbound IIOP) on joint client/server objects that are not connected to an IIOP Listener Handler (ISH).
You set ISL command options in the SERVERS
section of the server’s UBBCONFIG
file. Because support for outbound IIOP requires a small amount of extra resources, the default is outbound IIOP disabled. For more information, see “Using the ISL Command to Configure Outbound IIOP” in Setting Up a BEA Tuxedo Application and “ISL(1)
” in the BEA Tuxedo Command Reference.
To set up BEA Tuxedo C++ callback objects using CORBA, the client must do the following:
activates
the object in the POA (that is, puts the servant and the ObjectId
into the POA’s Active Object Map).Assuming that the client already has obtained a reference to the ORB, performing this task takes four interactions with the ORB and the POA. It might look like the model show in Listing 11-1. In this model, only the Root POA is needed.
// Create a servant for the callback Object
Catcher_i* my_catcher_i = new Catcher_i();
// Get root POA reference and activate the POA
1 CORBA::Object_var oref =
orb->resolve_initial_references("RootPOA");
2 PortableServer::POA_var root_poa =
PortableServer::POA::_narrow(oref);
3 root_poa -> the_POAManager() -> activate();
4 PortableServer::objectId_var temp_Oid =
root_poa ->activate_object ( my_catcher_i );
5 oref = root_poa->create_reference_with_id(
temp_Oid, _tc_Catcher->id() );
6 Catcher_var my_catcher_ref = Catcher::_narrow( oref );
To use the Persistent/UserId model, there are some additional steps required when creating a POA. Further, the ObjectId
is specified by the client, and this requires more steps. It might look like the model shown in Listing 11-2.
Catcher_i* my_catcher_i = new Catcher_i();
const char* oid_str = "783";
1 PortableServer::objectId_var oid =
PortableServer::string_to_objectId(oid_str);
// Find root POA
2 CORBA::Object_var oref =
orb->resolve_initial_references("RootPOA");
3 PortableServer::POA_var root_poa =
PortableServer::POA::_narrow(oref);
// Create and activate a Persistent/UserId POA
4 CORBA::PolicyList policies(2);
5 policies.length(2);
6 policies[0] = root_poa->create_lifespan_policy(
PortableServer::PERSISTENT);
7 policies[1] = root_poa->create_id_assignment_policy(
PortableServer::USER_ID );
8 PortableServer::POA_var my_poa_ref =
root_poa->create_POA(
"my_poa_ref", root_poa->the_POAManager(), policies);
9 root_poa->the_POAmanager()->activate();
// Create object reference for callback Object
10 oref = my_poa_ref -> create_reference_with_id(
oid, _tc_Catcher->id());
11 Catcher_var my_catcher_ref = Catcher::_narrow( oref );
// activate object
12 my_poa_ref -> activate_object_with_id( oid, my_catcher_i );
// Make the call passing the callback ref
foo -> register_callback ( my_catcher_ref );
All the interfaces and operations described here are standard CORBA interfaces and operations.
You can use the BEAWrapper callbacks API with to write either C++ joint client/servers.
Because the code required for callback objects is nearly identical for every client that supports callbacks, you may find it convenient to use the BEAWrappers provided in the library provided for joint client/servers.
The BEAWrappers are described in IDL, as shown in Listing 11-3.
// File: BEAWrapper
#ifndef _BEA_WRAPPER _IDL_
#define _BEA_WRAPPER _IDL_
#include <orb.idl>
#include <PortableServer.idll>
#pragma prefix “beasys.com”
moduleBEAWrapper
{
interfaceCallbacks
{
exception ServantAlreadyActive{ };
exception ObjectAlreadyActive { };
exception NotInRequest{ };
// set up transient callback Object
raises (ServantAlreadyActive);
// -- prepare POA, activate object, return objref
Object start_transient(
in PortableServer::Servant Servant,
in CORBA::RepositoryId rep_id)
// set up persistent/systemid callback Object
Object start_persistent_systemid(
in PortableServer::Servant servant,
in CORBA::Repository rep_id,
out string stroid)
raises (ServantAlreadyActive);
// reinstate set up for persistent/systemid
// callback object
Object restart_persistent_systemid(
in PortableServer::Servant servant,
in CORBA::RepositoryId rep_id,
in string stroid)
raises (ServantAlreadyActive, ObjectAlreadyActive);
// set up persistent/userid callback Object
Object start_persistent_userid(
in PortableServer::Servant servant,
in CORBA::RepositoryId rep_id,
in string stroid)
raises (ServantAlreadyActive, ObjectAlreadyActive);
// stop servicing a particular callback Object
// with the given servant
void stop_object( in PortableServer::Servant servant);
//Stop all callback Object processing
void stop_all_objects();
// get oid string for the current request
;
string get_string_oid() raises (NotInRequest)
};
}
#endif /* _BEA_WRAPPER _IDL_ */
The BEAwrappers are described in C++ as shown in Listing 11-4.
#ifndef _BEAWRAPPER_H_
#define _BEAWRAPPER_H_
#include <PortableServer.h>
class BEAWrapper{
class Callbacks{
public:
Callbacks (CORBA::ORB_ptr init_orb);
CORBA::Object_ptr start_transient (
PortableServer::Servant servant,
const char * rep_id);
CORBA::Object_ptr start_persistent_systemid (
PortableServer::Servant servant,
const char * rep_id,
char * & stroid);
CORBA::Object_ptr restart_persistent_systemid (
PortableServer::Servant servant,
const char * rep_id,
const char * stroid);
CORBA::Object_ptr start_persistent_userid (
PortableServer::Servant servant,
const char * rep_id,
const char * stroid);
void stop_object(PortableServer::Servant servant);
char* get_string_oid ();
void stop_all_objects();
~Callbacks();
private:
static CORBA::ORB_var orb_ptr;
static PortableServer::POA_var root_poa;
static PortableServer::POA_var trasys_poa;
static PortableServer::POA_var persys_poa;
static PortableServer::POA_var peruser_poa;
};
};
#endif // _BEAWRAPPER_H_
This C++ BEAWrapper Callbacks interface API is described in the following sections.
Returns a reference to the Callbacks interface.
BEAWrapper::Callbacks( CORBA::ORB_ptr init_orb);
init_orb
CORBA::IMP_LIMIT
BEAWrapper::Callbacks
class has already be instantiated with an ORB pointer. Only one instance of this class can be used in a process. Users who need additional flexibility should use the POA directly.
The constructor returns a reference to the Callbacks interface. Only one such object should be created for the process, even if multiple threads are used. Using more than one such object will result in undefined behavior.
A reference to the Callbacks object.
Activates an object, sets the ORB and the POA to the proper state, and returns an object reference to the activated object.
Object start_transient( in PortableServer::Servant servant,
in CORBA::RepositoryId rep_id)
raises ( ServantAlreadyActive );
CORBA::Object_ptr start_transient(
PortableServer::Servant servant,
const char* rep_id);
servant
rep_id
ServantAlreadyActive
ObjectId
. To receive callbacks on objects containing different ObjectId
s, you must create different servants and activate them separately. The same servant can be reused only if a stop_object
operation tells the system to stop using the servant for its original ObjectId
.
CORBA::BAD_PARAM
This operation performs the following actions:
Servant
supplied to service objects of the type rep_id
, using an ObjectId
generated by the system. stop_object
operation; after that, invocations on that object reference are no longer valid and can never be made valid.CORBA::Object_ptr
ObjectId
generated by the system and the rep_id
provided by the user. The object reference will need to be converted to a specific object type by invoking the _narrow()
operation defined for the specific object. The caller is responsible for releasing the object when the conversion is done.
Activates an object, sets the ORB and the POA to the proper state, sets the output parameter stroid
, and returns an object reference to the activated object.
Objectstart_persistent_systemid
(
in PortableServer::Servant servant,
in CORBA::RepositoryId rep_id,
out string stroid)
raises ( ServantAlreadyActive );
CORBA::Object_ptrstart_persistent_systemid
(
PortableServer::Servant servant,
const char* rep_id,
char*& stroid);
servant
rep_id
stroid
restart_persistent_systemid
), most likely after the client process has terminated and restarted.
ServantAlreadyActive
ObjectId
. To receive callbacks on objects containing different ObjectIds
, you must create different servants and activate them separately. The same servant can be reused only if a stop
operation tells the system to stop using the servant for its original ObjectId
.
CORBA::BAD_PARAMETER
CORBA::IMP_LIMIT
This operation performs the following actions:
Servant
supplied to service objects of the type rep_id
, using an ObjectId
generated by the system. stroid
to the stringified version of an ObjectId
assigned by the system. rep_id
and for the same ObjectId
, the servant will accept requests made on that same object reference. Since the ObjectId
was generated by the system, the application has to save that ObjectId
.CORBA::Object_ptr
ObjectId
generated by the system and the rep_id
provided by the user. The object reference will need to be converted to a specific object type by invoking the _narrow()
operation defined for the specific object. The caller is responsible for releasing the object when the conversion is done.
Activates an object, sets the ORB and the POA to the proper state, and returns an object reference to the activated object.
Objectrestart_persistent_systemid
(
in PortableServer::Servant servant,
in CORBA::RepositoryId rep_id,
in string stroid)
raises (ServantAlreadyActive, ObjectAlreadyActive);
CORBA::Object_ptrrestart_persistent_systemid(
PortableServer::Servant servant,
const char* rep_id
const char* stroid);
servant
rep_id
stroid
ObjectId
provided by the user to be set in the object reference being created. It must have been returned from a previous call on start_persistent_systemid
.
ServantAlreadyActive
ObjectId
. To receive callbacks on objects containing different ObjectId
s, you must create different servants and activate them separately. The same servant can be reused only if a stop_object
operation tells the system to stop using the servant for its original ObjectId
.
ObjectAlreadyActive
ObjectId
is already being used for a callback. A given ObjectId
can have only one servant associated with it. If you wish to change to a different servant, you must first invoke stop_object
with the servant currently in use.
CORBA::BAD_PARAM
ObjectId
supplied was not previously assigned by the system.
CORBA::IMP_LIMIT
This operation performs the following actions:
Servant
supplied to service objects of the type rep_id
, using the supplied stroid
(a stringified ObjectId
), which must have been obtained by a previous call on start_persistent_systemid
. restart_persistent_systemid
method.CORBA::Object_ptr
ObjectId
stroid
and the rep_id
provided by the user. The object reference will need to be converted to a specific object type by invoking the _narrow()
operation defined for the specific object. The caller is responsible for releasing the object when done.
Activates an object, sets the ORB and the POA to the proper state, and returns an object reference to the activated object.
Objectstart_persistent_userid(
portableServer::Servant a_servant,
in CORBA::RepositoryId rep_id,
in string stroid)
raises ( ServantAlreadyActive, ObjectAlreadyActive );
CORBA::Object_ptr start_persistent_userid (
PortableServer::Servant servant,
const char* rep_id,
const char* stroid);
servant
rep_id
stroid
ObjectId
provided by the user to be set in the object reference being created. The stroid
holds application-specific data and is opaque to the ORB.
ServantAlreadyActive
ObjectId
. To receive callbacks on objects containing different ObjectId
s, you must create different servants and activate them separately. The same servant can be reused only if a stop_object
operation tells the system to stop using the servant for its original ObjectId
.
ObjectAlreadyActive
ObjectId
is already being used for a callback. A given ObjectId
can have only one servant associated with it. If you wish to change to a different servant, you must first invoke stop_object
with the servant currently in use.
CORBA::BAD_PARAM
CORBA::IMP_LIMIT
This operation performs the following actions:
Servant
supplied to service objects of the type rep_id
, using the object Id stroid
. rep_id
and for the same ObjectId
, the servant will accept requests made on that same object reference.CORBA::Object_ptr
ObjectId
stroid
and the rep_id
provided by the user. The object reference will need to be converted to a specific object type by invoking the _narrow()
operation defined for the specific object. The caller is responsible for releasing the object when the conversion is done.
Tells the ORB to stop accepting requests on the object that is using the given servant.
void stop_object( in PortableServer::Servant servant);
void stop_object
(PortableServer::Servant servant);
servant
ObjectId
will be removed from the Active Object Map.
This operation tells the ORB to stop accepting requests on the given servant. It does not matter what state the servant is in, activated or deactivated; no error is reported.
Note: | If you do an invocation on a callback object after you call the stop_object operation, the OBJECT_NOT_EXIST exception is returned to the caller. This is because the stop_object operation, in effect, deletes the object. |
Tells the ORB to stop accepting requests on all servants.
void stop_all_objects ();
void stop_all_objects ();
This operation tells the ORB to stop accepting requests on all servants that have been set up in this process.
If a client calls the ORB::shutdown
method, then it must not subsequently call stop_all_objects
.
Requests the string version of the ObjectId
of the current request.
string get_string_oid() raises (NotInRequest);
char* get_string_oid();
NotInRequest
This operation returns the string version of the ObjectId
of the current request.
char*
ObjectId
of the current request. This is the string that was supplied when the object reference was created. The string is meaningful to users only in the case when the object reference was created by the start_persistent_userid function. (That is, the ObjectId
created by start_transient and start_persistent_systemid were created by the ORB and has no relationship to the user application.)
BEAWrapper::~Callbacks( );
This destructor destroys the callback object.
If a client wants to get rid of the wrapper, but not shut down the ORB, then the client must call the stop_all_objects
method.
![]() ![]() ![]() |