BEA Logo BEA WebLogic Enterprise Release 5.1

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   WebLogic Enterprise Doc Home   |   Programming Topics   |   Previous Topic   |   Next Topic   |   Contents   |   Index

TP Framework

 

This topic includes the following sections:

The BEA WebLogic Enterprise TP Framework provides a programming TP Framework that enables users to create servers for high-performance TP applications. This chapter describes the TP Framework programming model and the TP Framework application programming interface (API) in detail. Additional information about how to use this API can be found in Creating CORBA C++ Server Applications.

The TP Framework is required when developing BEA WebLogic Enterprise servers. Later releases will relax this requirement, though it is expected that most customers will use the TP Framework as an integral part of their applications.

BEA WebLogic Enterprise uses BEA Tuxedo as the underlying infrastructure for providing load balancing, transactional capabilities, and administrative infrastructure. The base API used by the TP Framework is the CORBA API with BEA extensions. The TP Framework API is exposed to customers. The BEA Tuxedo ATMI is an optional API that can be mixed in with TP Framework APIs, allowing a customer to deploy distributed applications using a mix of BEA Tuxedo servers and BEA WebLogic Enterprise servers.

Before BEA WebLogic Enterprise, ORB products did not approach BEA Tuxedo's performance in large-scale environments. BEA Tuxedo systems support applications that can process hundreds of transactions per second. These applications are built using the BEA Tuxedo stateless-service programming model that minimizes the amount of system resources used for each request, and thus maximizes throughput and price performance.

Now, BEA WebLogic Enterprise and its TP Framework give customers a way to develop CORBA applications with performance similar to BEA Tuxedo applications. BEA WebLogic Enterprise servers that use the TP Framework provide throughput, response time, and price performance approaching the BEA Tuxedo stateless-service programming model, while using the CORBA programming model.

 


A Simple Programming Model

The TP Framework provides a simple, useful subset of the wide range of possible CORBA object implementation choices. You use it for the development of server-side object implementations only. When using any client-side CORBA ORB, clients interact with CORBA objects whose server-side implementations are managed by the TP Framework. Clients are unaware of the existence of the TP Framework-a client written to access a CORBA object executing in a non-BEA WebLogic Enterprise server environment will be able to access that same CORBA object executing in a BEA WebLogic Enterprise server environment without any changes or restrictions to the client interface.

The TP Framework provides a server environment and an API that is easier to use and understand than the CORBA Portable Object Adapter (POA) API, and is specifically geared towards enterprise applications. It is a simple server programming model and an orthodox implementation of the CORBA model, which will be familiar to programmers using ORBs such as ORBIX or VisiBroker.

The TP Framework simplifies the programming of BEA WebLogic Enterprise servers by reducing the complexity of the server environment in the following ways:

The TP Framework provides the following functionality:

Control Flow

The TP Framework, in conjunction with the ORB and the POA, controls the flow of the application program by doing the following:

Object State Management

The TP Framework API provides callback methods for application code to implement flexible state management schemes for CORBA objects. State management involves the saving and restoring of object state on object deactivation and activation. It also concerns the duration of activation of objects, which influences the performance of servers and their resource usage. The default duration of object activation is controlled by policies assigned to implementations at IDL compile time.

Transaction Integration

TP Framework transaction integration provides the following features:

Object Housekeeping

When a server is shut down, the TP Framework rolls back any transactions that the server is involved in and deactivates any CORBA objects that are currently active.

High-level Services

The TP interface in the TP Framework API provides methods for performing object registrations and utility functions. The following services are provided:

The purpose of these high-level service methods is to eliminate the need for developers to understand the CORBA POA, CORBA Naming Service, and BEA Tuxedo APIs, which they use for their underlying implementations. By encapsulating the underlying API calls with a high-level set of methods, programmers can focus their efforts on providing business logic rather than understanding and using the more complex underlying facilities.

 


State Management

State management involves the saving and restoring of object state on object deactivation and activation. It also concerns the duration of activation of objects, which influences the performance of servers and their resource usage. The external API of the TP Framework provides activate_object and deactivate_object methods, which are a possible location for state management code.

Activation Policy

State management is provided in the TP Framework by the activation policy. This policy controls the activation and deactivation of servants for a particular IDL interface (as opposed to the creation and destruction of the servants). This policy is applicable only to CORBA objects using the TP Framework.

The activation policy determines the default in-memory activation duration for a CORBA object. A CORBA object is active in a POA if the POA's active object map contains an entry that associates an object ID with an existing servant. Object deactivation removes the association of an object ID with its active servant. You can choose from one of three activation policies: method (the default), transaction, or process.

Note: The activation policies are set in an ICF file that is configured at OMG IDL compile time. For a description of the ICF file, refer to Implementation Configuration File (ICF).

The activation policies are described below:

Application-controlled Activation and Deactivation

Ordinarily, activation and deactivation decisions are made by the TP Framework, as discussed earlier in this chapter. The techniques in this section show how to use alternate mechanisms. The application can control the timing of activation and deactivation explicitly for objects with particular policies.

Explicit Activation

Application code can bypass the on-demand activation feature of the TP Framework for objects that use the process activation policy. The application can "preactivate" an object (that is, activate it before any invocation) using the TP::create_active_object_reference call.

Preactivation works as follows. Before the application creates an object reference, the application instantiates a servant and initializes that servant's state. The application uses TP::create_active_object_reference to put the object into the Active Object Map (that is, associate the servant with an ObjectId). Then, when the first invocation is made, the TP Framework immediately directs the request to the process that created the object reference and then to the existing servant, bypassing the necessity to call Server::create_servant and then the servant's activate_object method (just as if this were the second or later invocation on the object). Note that the object reference for such an object will not be directed to another server and the object will never go through on-demand activation as long as the object remains activated.

Since the preactivated object has the process activation policy, it will remain active until one of two events occurs: 1) the ending of the process or 2) a TP::deactivateEnable call.

Usage Notes

Preactivation is especially useful if the application needs to establish the servant with an initial state in the same process, perhaps using shared memory to initialize state. Waiting to initialize state until a later time and in a potentially different process may be very difficult if that state includes pointers, object references, or complex data structures. TP::create_active_object_reference guarantees that the preactivated object is in the same process as the code that is doing the preactivation. While this is convenient, preactivation should be used sparingly, as should all process objects, because it preallocates precious resources. However, when needed and used properly, preallocation is more efficient than alternatives.

Examples of such usage might be an object using the "iterator" pattern. For example, there might a potentially long list of items that could be returned (in an unbound IDL sequence) from a "database_query" method (for example, the contents of the telephone book). Returning all such items in the sequence is impractical because the message size and the memory requirements would be too large.

On an initial call to get the list, an object using the iterator pattern returns only a limited number of items in the sequence and also returns a reference to an "iterator" object that can be invoked to receive further elements. This iterator object is initialized by the initial object; that is, the initial object creates a servant and sets its state to keep track of where in the long list of items the iteration currently stands (the pointer to the database, the query parameters, the cursor, and so forth).

The initial object preactivates this iterator object by using TP::create_active_object_reference. It also creates an object reference to that object to return to the client. The client then invokes repeatedly on the iterator object to receive, say, the next 100 items in the list each time. The advantage of preactivation in this situation is that the state might be complex. It is often easiest to set such state initially, from a method that has all the information in its context (call frame), when the initial object still has control.

When the client is finished with the iterator object, it invokes a final method on the initial object which deacativates the iterator object. The initial object deactivates the iterator object by invoking a method on the iterator object that calls the TP::deactivateEnable method, that is, the iterator object calls TP::deactivateEnable on itself.

Caution to Users

For objects to be preactivated in this fashion, the state usually cannot be recovered if a crash occurs. (This is because the state was considered too complex or inconvenient to set upon initial, delayed activation.) This is a valid object technique, essentially stating that the object is valid only for a single activation period.

However, a problem may arise because of the "one-time" usage. Since a client still holds an object reference that leads to the process containing that state, and since the state cannot be recreated after the crash, care must be taken that the client's next invocation does not automatically provoke a new activation of the object, because that object would have inapplicable state.

The solution is to refuse to allow the object to be activated automatically by the TP Framework. If the user provides the TobjS::ActivateObjectFailed exception to the TP Framework as a result of the activate_object call, the TP Framework will not complete the activation and will return an exception to the client, CORBA::OBJECT_NOT_EXIST. The client has presumably been warned about this possibility, since it knows about the iterator (or similar) pattern. The client must be prepared to restart the iteration.

Note: This defensive measure may not be necessary in the future; the TP Framework itself may detect that the object reference is no longer valid. In particular, you should not depend on the possibility that the activate_object method might be called. If the TP Framework does in fact change, activate_object will not be called and the framework itself will generate the OBJECT_NOT_EXIST exception.

Self Deactivation

Just as it is possible to preactivate an object with the process activation policy, it is possible to request the deactivation of an object with the process activation policy. The ability to preactivate and the ability to request deactivation are independent; regardless of how an object was activated, it can be deactivated explicitly.

A method in the application can request (via TP::deactivateEnable) that the object be deactivated. When TP::deactivateEnable is called and the object is subsequently deactivated, no guarantee is made that subsequent invocations on the CORBA object will result in reactivation in the same process as a previous activation. The association between the ObjectId and the servant exists from the activation of the CORBA object until one of the following events occurs: 1) the shutdown of the server process or 2) the application calls TP::deactivateEnable. After the association is broken, when the object is invoked again, it can be re-activated anywhere that is allowed by the BEA WebLogic Enterprise configuration parameters.

There are two forms of TP::deactivateEnable. In the first form (with no parameters), the object currently executing will be deactivated after completion of the method in which the call is made. The object itself makes the decision that it should be deactivated. This is often done during a method call that acts as a "signoff" signal.

The second form of TP::deactivateEnable allows a server to request deactivation of any active object, whether it is the object that is executing or not; that is, any part of the server can ask that the object be deactivated. This form takes parameters identifying the object to be deactivated. Explicit deactivation is not allowed for objects with an activation policy of transaction, because such objects cannot be safely deactivated until the end of a transaction.

In the TP::deactivateEnable call, the TP Framework calls the servant's deactivate_object method. Exactly when the TP Framework invokes deactivate_object depends on the state of the object to be deactivated. If the object is not currently in execution, the TP Framework deactivates it before returning to the caller. The object might be currently executing a method; this is always the case for TP::deactivateEnable with no parameters (since it refers to the currently executing object). In this case, TP::deactivateEnable is not told whether the object was deactivated immediately or not.

Note: The TP::deactivateEnable(interface, object id, servant) method can be used to deactivate an object. However, if that object is currently in a transaction, the object will be deactivated when the transaction commits or rolls back. If an invoke occurs on the object before the transaction is committed or rolled back, the object will not be deactivated.

To ensure the desired behavior, make sure that the object is not in a transaction or ensure that no invokes occur on the object after the TP::deactivateEnable() call until the transaction is complete.

Servant Lifetime

A servant is a C++ class that contains methods to implement an IDL interface's operations. The user writes the servant code. The TP Framework invokes methods in the servant code to satisfy requests. The servant is created by the C++ "new" statement and is destroyed by the C++ "delete" statement. Exactly who does the creation and who does the deletion, and the timing of creation and deletion, is the subject of this section.

The Normal Case

In the normal case, the TP Framework completely controls the lifetime of a servant. The basic model is that, when a request for an inactive object arrives, the TP Framework obtains a servant and then activates it (by calling its activate_object method). At deactivation time, the TP Framework calls the servant's deactivate_object method and then disposes of the servant.

For this release of BEA WebLogic Enterprise, two phrases in the basic model above need to be further explained. The phrase "the TP Framework obtains a servant" means that when the TP Framework needs a servant to be created, it calls the user-written Server::create_servant method. At that time, the application code must return a pointer to the requested servant. The application almost always does this by using the C++ "new" statement to create a new instance of a servant. The phrase "disposes of the servant" means that the TP Framework deletes it.

The application must be aware that this current behavior of always creating and deleting a servant may change in future versions of this product. The application should not depend on the current behavior, but should write servant code that allows re-use of a servant. Specifically, the servant code must work even if the servant has not been freshly created (by the C++ "new" statement). The TP Framework reserves the right not to delete a servant after it has been deactivated and then to reactivate it. This means that the servant must completely initialize itself at the time of the callback on the servant's activate_object method, not at the time of servant creation (not in the constructor).

Special Cases

There are two techniques an application can use to alter the normal TP Framework use of servants. The first has to do with obtaining a servant and the second has to do with disposing of the servant.

The application can alter the "obtaining" mechanism by using explicit preactivation. In this case, the application creates and initializes a servant before asking the TP Framework to declare it activated. Once such a servant has been turned over to the TP Framework (by the TP::create_active_object_reference call), that servant is treated by the TP Framework just like every other servant. The only difference is in its method of creation and initialization.

The application can alter the "disposing" mechanism by taking the responsibility for disposing of a servant instead of leaving that responsibility with the TP Framework. Once a servant is known to the TP Framework (through Server::create_servant or TP::create_active_object_reference), the TP Framework's default behavior is to dispose of that servant itself. In this case, the application code must no longer use references to the servant after deactivation.

However, the application may tell the TP Framework not to dispose of the servant (not to delete or re-use it) after the TP Framework deactivates it. Taking responsibility for a servant is done on an individual servant basis, not for a whole class of servants, by calling TP::application_responsibility with a parameter identifying the servant. In this case, the TP Framework does nothing further with the servant; the TP Framework does not delete, save, or make any further references to the servant.

The advantage of taking responsibility for the servant is that the servant does not have to be created anew. If obtaining the servant is an expensive proposition, the application may choose to save the servant and re-use it later. This is especially likely to be true for servants for preactivated objects, but is true in general. For example, the next time the TP Framework makes a call on Server::create_servant, the application might return a previously saved servant. It should be remembered that any time a servant is given to the TP Framework (even if it had been previously saved) the TP Framework assumes it has responsibility. Thus, even if the application saved the servant one time after giving the servant to the TP Framework, if the application gives the servant to the TP Framework again and want to save the servant again, the application must again call TP::application_responsibility to save the servant after that use.

Once an application has taken responsibility for a servant, the application must take care to delete the servant when the servant is no longer needed, the same as for any other C++ instance.

The TP::application_responsibility call can only be used after the TP Framework has possession of the servant. It cannot be used, for example, during the servant's activate_object callback because the TP Framework does not yet know about the servant (the servant has not been returned yet).

Saving and Restoring Object State

While CORBA objects are active, their state is contained in a servant. Unless an application uses TP::create_active_object_reference, state must be initialized when the object is first invoked (that is, the first time a method is invoked on a CORBA object after its object reference is created), and on subsequent invocations after they have been deactivated. While a CORBA object is deactivated, its state must be saved outside the process in which the servant was active. The object's state can be saved in shared memory, in a file, or in a database. Before a CORBA object is deactivated, its state must be saved, and when it is activated, its state must be restored.

The programmer determines what constitutes an object's state and what must be saved before an object is deactivated, and restored when an object is activated.

Note On Use of Constructors and Destructors for Corba Objects

The state of CORBA objects must not be initialized, saved, or restored in the constructors or destructors for the servant classes. This is because the TP Framework may reuse an instance of a servant rather than deleting it at deactivation. No guarantee is made as to the timing of the creation and deletion of servant instances.

 


Transactions

The following sections provide information about transaction policies and how to use transactions.

Transaction Policies

Eligibility of CORBA objects to participate in global transactions is controlled by the transaction policies assigned to implementations at compile time. The following policies can be assigned.

Note: The transaction policies are set in an ICF file that is configured at OMG IDL compile time. For a description of the ICF file, refer to Implementation Configuration File (ICF).

Transaction Initiation

Transactions are initiated in one of two ways:

Transaction Termination

In general, the handling of the outcome of a transaction is the responsibility of the initiator. Therefore, the following are true:

The following behavior is enforced by the BEA WebLogic Enterprise system:

Transaction Suspend and Resume

The CORBA object must follow strict rules with respect to suspending and resuming a transaction within a method invocation. These rules and the error conditions that result from their violation are described below.

When a CORBA object method begins execution, it can be in one of the following three states with respect to transactions:

Restrictions on Transactions

The following restrictions apply to BEA WebLogic Enterprise transactions:

SQL and Global Transactions

Adhere to the following guidelines when using SQL and Global Transactions:

Voting on Transaction Outcome

CORBA objects can affect transaction outcome during two stages of transaction processing:

Transaction Time-outs

When a transaction time-out occurs, the transaction is marked so that the only possible outcome is to roll back the transaction, and the CORBA::TRANSACTION_ROLLEDBACK standard exception is returned to the client. Any attempts to send new requests will also fail with the CORBA::TRANSACTION_ROLLEDBACK exception until the transaction has been aborted.

 


TP Framework API

This section describes the TP Framework API. Additional information about how to use this API can be found in Creating CORBA C++ Server Applications.

The TP Framework comprises the following components:

The visible part of the TP Framework consists of two categories of operations:

Server Interface

The Server interface provides callback methods that can be used for application-specific server initialization and termination logic. This interface also provides a callback method that is used to create servants when servants are required for object activation.

The Server interface has the following characteristics:

C++ Declarations

The C++ mapping is as follows:

typedef Tobj_ServantBase* Tobj_Servant;

class Server {
public:
CORBA::Boolean initialize(int argc, char** argv);
void release();
Tobj_Servant create_servant(const char* interfaceName);
};

Note: Programmers must provide definitions for the Server::initialize(), Server::release(), and Server::create_servant methods.

Server::create_servant

Synopsis

Creates a servant to instantiate a C++ object.

C++ Binding

class Server {
public:
Tobj_Servant create_servant(const char* interfaceName);
};

Argument

interfaceName

Specifies a character string that contains the fully qualified interface name for the object. This will be the same interface name that was supplied when the object reference was created (TP::create_object_reference() or TP::create_active_object_reference()) for the object reference used for this invocation. This name can be used to determine which servant needs to be constructed.

Return Value

Tobj_ServantBase

The pointer to the newly created servant (instance) for the specified interface. A NULL value should be returned if create_servant() is invoked with an interface name that it does not recognize or if the servant cannot be created for some reason.

If the create_servant method returns a NULL pointer, activation fails. A CORBA::OBJECT_NOT_EXIST() exception is raised back to the client. Also, the following message is written to the user log (ULOG):

"TPFW_CAT:23: ERROR: Activating object - application raised TobjS::CreateServantFailed. Reason = Application's Server::create_servant returned NULL. Interface = interfaceName, OID = oid"

Where interfaceName is the interface ID of the invoked interface and oid is the corresponding object ID.

Note: The restriction on the length of the ObjectId has been removed in this release.

Description

The create_servant method is invoked by the TP Framework when a request arrives at the server and there is no available servant to satisfy the request. The TP Framework calls the create_servant method with the interface name for the servant to be created. The server application instantiates an appropriate C++ object and returns a pointer to it. Typically, the method contains a switch statement on the interface name and creates a new object, depending on the interface name.

Caution: The server application must not depend on this method being invoked for every activation of a CORBA object. The server application must not do any handling of CORBA object state in the constructors or destructors of any servant classes for CORBA objects. This is because the TP Framework may possibly reuse servants on activation and may possibly not destroy servants on deactivation.

Exception

If an exception is thrown in Server::create_servant(), the TP Framework catches the exception. Activation fails. A CORBA::OBJECT_NOT_EXIST() exception is raised back to the client. In addition, an error message is written to the user log (ULOG) file, as follows, for each exception type:

TobjS::CreateServantFailed

"TPFW_CAT:23: ERROR: Activating object - application raised TobjS::CreateServantFailed. Reason = reason. Interface = interfaceName, OID = oid"

Where reason is a user-supplied reason, and interfaceName and oid are the interface ID and object ID, respectively, of the invoked CORBA object.

TobjS::OutOfMemory

"TPFW_CAT:22: ERROR: Activating object - application raised TobjS::OutOfMemory. Reason = reason. Interface = interfaceName, OID = oid"

Where reason is a user-supplied reason, and interfaceName and oid are the interface ID and object ID, respectively, of the invoked CORBA object.

CORBA::Exception

"TPFW_CAT:28: ERROR: Activating object - CORBA Exception not handled by application. Exception ID = exceptionID. Interface = interfaceName, OID = oid"

Where exceptionID is the interface ID of the exception, and interfaceName and oid are the interface ID and object ID, respectively, of the invoked CORBA object.

Other Exception

"TPFW_CAT:29: ERROR: Activating object - Unknown Exception not handled by application. Exception ID = exceptionID. Interface = interfaceName, OID = oid"

Where exceptionID is the interface ID of the exception, and interfaceName and oid are the interface ID and object ID, respectively, of the invoked CORBA object.

Server::initialize()

Synopsis

Allows the application to perform application-specific initialization procedures, such as logging into a database, creating and registering well-known object factories, initializing global variables, and so forth.

C++ Binding

class Server {
public:

        CORBA::Boolean  initialize(int argc, char** argv);

};

Arguments

The argc and argv arguments are passed from the command line. The argc argument contains the name of the server. The argv argument contains the first command-line option that is specific to the application, if there are any.

Command-line options are specified in the UBBCONFIG file using the CLOPT parameter in the entry for the server in the SERVERS section. System-recognized options come first in the CLOPT parameter, followed by a double-hyphen (--), followed by the application-specific options. The value of argc is one greater than the number of application-specific options. For details, see ubbconfig(5) in the BEA Tuxedo Reference Manual.

Return Value

Boolean TRUE or FALSE. TRUE indicates success. FALSE indicates failure. If an error occurs in initialize(), the application code should return FALSE. The application code should not call the system call exit(). Calling exit() does not give the TP Framework a chance to release resources allocated during startup and may cause unpredictable results.

If the return value is FALSE:

Description

The initialize callback method, which is invoked as the last step in server initialization, allows the application to perform application-specific initialization.

Typically, a server application does the following tasks in Server::initialize:

It is the responsibility of the server application to open any required XA resource managers. This is done by invoking either of the following methods:

Exceptions

If an exception is raised in Server::initialize(), the TP Framework catches the exception. The TP Framework behavior is the same as if initialize() returned FALSE (that is, an exception is considered to be a failure). In addition, an error message is written to the user log (ULOG) file, as follows, for each exception type:

TobjS::InitializeFailed

"TPFW_CAT:1: ERROR: Exception in Server::initialize():IDL:beasys.com/TobjS/InitializeFailed:1.0. Reason = reason"

Where reason is a string supplied by application code. For example:

Throw TobjS::InitializeFailed(
"Couldn't register factory");

CORBA::Exception

"TPFW_CAT:1: ERROR: Exception in
Server::initialize():
exception. Reason = unknown"

Where exception is the interface ID of the CORBA exception that was raised.

Other Exceptions

TPFW_CAT:1: ERROR: Exception in Server::initialize(): unknown exception. Reason = unknown"

Server::release()

Synopsis

Allows the application to perform any application-specific cleanup, such as logging off a database, unregistering well-known factories, or deallocating resources.

C++ Binding

typedef Tobj_ServantBase* Tobj_Servant;

class Server {
public:
void release();
};

Arguments

None.

Return Value

None.

Description

The release callback method, which is invoked as the first step in server shutdown, allows the server application to perform any application-specific cleanup. The user must override the virtual function definition.

Typical tasks performed by the application in this method are as follows:

This method is normally called in response to a tmshutdown command from the administrator or operator.

The TP Framework provides a default implementation of Server::release(). The default implementation closes XA resource managers for the server. The implementation does this by issuing a tx_close() invocation, which uses the default CLOSEINFO configured for the server's group in the UBBCONFIG file.

It is the responsibility of the application to close any open XA resource managers. This is done by issuing either of the following calls:

Exceptions

If an exception is raised in release(), the TP Framework catches the exception. Each exception causes an error message to be written to the user log (ULOG) file, as follows:

TobjS::ReleaseFailed

"TPFW_CAT:2: WARN: Exception in Server::release(): IDL:beasys.com/TobjS/ReleaseFailed:1.0. Reason = reason"

Where reason is a string supplied by application code. For example:

Throw TobjS::ReleaseFailed(
"Couldn't unregister factory");

CORBA::Exception

"TPFW_CAT:2: WARN: Exception in Server::release(): exception. Reason = unknown"

Where exception is the interface ID of the CORBA exception that was raised.

Other Exceptions

"TPFW_CAT:2: WARN: Exception in Server::release(): unknown exception. Reason = unknown"

In all cases, the server continues to exit.

Tobj_ServantBase Interface

The Tobj_ServantBase interface defines operations that allow a CORBA object to assist in the management of its state. Every implementation skeleton generated by the IDL compiler automatically inherits from the Tobj_ServantBase class. The Tobj_ServantBase class contains two virtual methods, activate_object() and deactivate_object(), that may be optionally implemented by the programmer.

Whenever a request comes in for an inactive CORBA object, the object is activated and the activate_object() method is invoked on the servant. When the CORBA object is deactivated, the deactivate_object() method is invoked on the servant. The timing of deactivation is driven by the implementation's activation policy. When the deactivate_object() method is invoked, the TP Framework passes in a reason code to indicate why the call was made.

Note: Tobj_ServantBase::activate_object() and Tobj_ServantBase::deactivate_object() are the only methods that the TP Framework guarantees will be invoked for CORBA object activation and deactivation. The servant class constructor and destructor may or may not be invoked at activation or deactivation time (through the Server::create_servant call for C++ or directly by Java). Therefore, the server application code must not do any state handling for CORBA objects in either the constructor or destructor of the servant class.

Note: The programmer does not need to use a cast or reference to Tobj_ServantBase directly. The Tobj_ServantBase methods show up as part of the skeleton and, therefore, in the implementation class for a servant. The programmer may provide definitions for the activate_object and deactivate_object methods, but the programmer should never make direct invocations on those methods; only the TP Framework should call those methods.

C++ Declaration (in Tobj_ServantBase.h)

The C++ mapping for the Tobj_servantBase interface is as follows:

class Tobj_ServantBase : public PortableServer::ServantBase {
public:
virtual void activate_object(const char * stroid) {}
virtual void deactivate_object(const char*,
TobjS::DeactivateReasonValue) {}
};

Tobj_ServantBase:: activate_object()

Synopsis

Associates an object ID with a servant. This method gives the application an opportunity to restore the object's state when the object is activated. The state may be restored from shared memory, from an ordinary flat file, or from a database file.

C++ Binding

class Tobj_ServantBase : public PortableServer::ServantBase {
public:
virtual void activate_object(const char * stroid) {}
};

Argument

stroid

Specifies the object ID in string format. The object ID uniquely identifies this instance of the class. This is the same object ID that was specified when the object reference was created (using TP:create_object_reference()) or in the TP::create_active_object_reference() for the object reference used for this invocation.

Note: The restriction on the length of the object ID has been removed in this release.

Return Value

None.

Description

Object activation is triggered by a client invoking a method on an inactive CORBA object. This causes the Portable Object Adapter (POA) to assign a servant to the CORBA object. The activate_object() method is invoked before the method invoked by the client is invoked. If activate_object() returns successfully, that is, without raising an exception, the requested method is executed on the servant.

The activate_object() and deactivate_object() methods and the method invoked by the client can be used by the programmer to manage object state. The particular way these methods are used to manage object state may vary according to the needs of the application. For a discussion of how these methods might be used, see Creating CORBA C++ Server Applications.

If the object is currently infected with a global transaction, activate_object() executes within the scope of that same global transaction.

It is the responsibility of the programmer of the object to check that the stored state of the object is consistent. In other words, it is up to the application code to save a persistent flag that indicates whether or not deactivate_object() successfully saved the state of the object. That flag should be checked in activate_object().

Exceptions

If an error occurs while executing activate_object(), the application code should raise either a CORBA standard exception or a TobjS::ActivateObjectFailed exception. When an exception is raised, the TP Framework catches the exception, and the following events occur:

Tobj_ServantBase::deactivate_object()

Synopsis

Removes the association of an object ID with its servant. This method gives the application an opportunity to save all or part of the object's state before the object is deactivated. The state may be saved in shared memory, in an ordinary flat file, or in a database file.

C++ Binding

class Tobj_ServantBase : public PortableServer::ServantBase {
public:
virtual void deactivate_object(const char* stroid,
TobjS::DeactivateReasonValue reason) {}
};

Arguments

stroid

Specifies the object ID in string format. The object ID uniquely identifies this instance of the class.

Note: The restriction on the length of the object ID has been removed in this release.

reason

Indicates the event that caused this method to be invoked. The reason code can be one of the following:

DR_METHOD_END

Indicates that the object is being deactivated after the completion of a method. It is used if the object's deactivation policy is:

  • method

  • transaction (only if there is no transaction in effect)

  • process (if TP::deactivateEnable() called)

DR_SERVER_SHUTDOWN

Indicates that the object is being deactivated because the server is being shut down in an orderly fashion. It is used if the object's deactivation policy is:

  • transaction (only if transaction is active)

  • process

    Note that when a server is shut down in an orderly fashion, all transactions that the server is involved in are marked for rollback.

DR_TRANS_ABORTED

This reason code is used only for objects that have the transaction activation policy. It can occur when the transaction is started by either the client or automatically by the system. When the deactivate_object() method is invoked with this reason code, the transaction is marked for rollback only.

DR_TRANS_COMMITTING

This reason code is used only for objects that have the transaction activation policy. It can occur when the transaction is started by either the client or the TP Framework. It indicates that a Current.commit() operation was invoked for the transaction in which the object is involved. The deactivate_object() method is invoked just before the transaction manager's two-phase commit algorithm begins; that is, before prepare is sent to the resource managers.

The CORBA object is allowed to vote on the outcome of the transaction when the deactivate_object() method is invoked with the DR_TRANS_COMMITTING reason code. By invoking Current.rollback_only(), the method can force the transaction to be rolled back; otherwise, the two-phase commit algorithm continues. The transaction is not necessarily committed just because the Current.rollback_only() is not invoked in this method. Any other CORBA object or resource manager involved in the transaction could also vote to roll back the transaction.

DR_EXPLICIT_DEACTIVATE

Indicates that the object is being deactivated because the application executed a TP::deactivateEnable(-,-,-) on this object. This can happen only for objects that have the process activation policy.

Return Value

None.

Description

Object deactivation is initiated either by the system or by the application, depending on the activation policy of the implementation for the CORBA object. The deactivate_object() method is invoked before the CORBA object is deactivated. For details of these policies and their use, see the section "ICF Syntax".

Deactivation may occur after an execution of a method invoked by a client if the activation policy for the CORBA object implementation is method, or as a result of the end of transactional work if the activation policy is transaction. It may also occur as the result of server shutdown if the activation policy is transaction or process.

In addition, the BEA WebLogic Enterprise software supports the use of user-controlled deactivation of CORBA objects having an activation policy of process or method via the use of the TP::deactivateEnable() and TP::deactivateEnable(-,-,-) methods. TP::deactivateEnable can be called inside a method of an object to cause the object to be deactivated at the end of the method. If TP::deactivateEnable is called in an object with the transaction activation policy, an exception is raised (TobjS::IllegalOperation) and the TP Framework takes no action. TP::deactivateEnable(-,-,-) can be called to deactivate any object that has a process activation policy. For more information, see the section "TP::deactivateEnable".

Note: The deactivate_object method will be called at server shutdown time for every object remaining in the Active Object Map, whether it was entered there implicitly by the TP Framework (the activation-on-demand technique: TP::create_servant and the servant's activate_object method) or explicitly by the user with TP::create_active_object_reference.

The activate_object() and deactivate_object() methods and explicit methods invoked by the client can be used by the programmer to manage object state. The manner in which these methods are used to manage object state may vary according to the needs of the application. For a discussion of how these methods might be used, see Creating CORBA C++ Server Applications.

The CORBA object with transaction activation policy gets to vote on the outcome of the transaction when the deactivate_object() method is invoked with the DR_TRANS_COMMITTING reason code. By calling Current.rollback_only() the method can force the transaction to be rolled back; otherwise, the two-phase commit algorithm continues. The transaction will not necessarily be committed just because Current.rollback_only() is not called in this method. Any other CORBA object or resource manager involved in the transaction could also vote to roll back the transaction.

Restriction

Note that if the object is involved in a transaction when this method is invoked, there are restrictions on what type of processing can be done based on the reason the object is invoked. If the object was involved in a transaction, the activation policy is transaction and the reason code for the call is:

DR_TRANS_ABORTED

No invocations on any CORBA objects are allowed in the method. No tpcall() is allowed. Transactions cannot be suspended or begun.

DR_TRANS_COMMITTING

No invocations on any CORBA objects are allowed in the method. No tpcall() is allowed. Transactions cannot be suspended or begun.

The reason for these restrictions is that the deactivation of objects with activation policy transaction is controlled by a call to the TP Framework from the transaction manager for the transaction. When the call with reason code DR_TRANS_COMMITTING is made, the transaction manager is executing phase 1 (prepare) of the two-phase commit. At this stage, it is not possible to issue a call to suspend a transaction nor to initiate a new transaction. Since a call to a CORBA object that was in another process would require that process to join the transaction, and the transaction manager is already executing the prepare phase, this would cause an error1. Since a call to a CORBA object that had no transactional properties would require that the current transaction be suspended, this would also cause an error. The same is true of a tpcall().

Similarly, when the invocation with reason code DR_TRANS_ABORTED is made, the transaction manager is already aborting. While the transaction manager is aborting, it is not possible to either suspend a transaction or initiate a new transaction. The same restrictions apply as for DR_TRANS_COMMITTING.

Exceptions

If the CORBA object method that is invoked by the client raises an exception, that exception is caught by the TP Framework and is eventually returned to the client. This is true even if deactivate_object() is invoked and raises an exception.

The client will never be notified about exceptions that are raised in deactivate_object(). It is the responsibility of the application code to check that the stored state of the CORBA object is consistent. For example, the application code could save a persistent flag that indicates whether or not deactivate_object() successfully saved the state. That flag can then be checked in activate_object().

If an error occurs while executing deactivate_object(), the application code should raise either a CORBA standard exception or a DeactivateObjectFailed exception. If deactivate_object() was invoked by the TP Framework, the TP Framework catches the exception and the following events occur:

TP Interface

The TP interface supplies a set of service methods that can be invoked by application code. This is the only interface in the TP Framework that can safely be invoked by application code. All other interfaces have callback methods that are intended to be invoked only by system code.

The purpose of this interface is to provide high-level calls that application code can call, instead of calls to underlying APIs provided by the Portable Object Adapter (POA), the CORBA Naming Service, and the BEA Tuxedo system. By using these calls, programmers can learn a simpler API and are spared the
complexity of the underlying APIs.

The TP interface implicitly uses two features of the BEA WebLogic Enterprise software that extend the CORBA APIs:

For information about the FactoryFinder object, see FactoryFinder Interface. For more information about Factory-based routing, see the Administration Guide.

Usage Notes

C++ Declarations (in TP.h)

The C++ mapping is as follows:

class TP {
public:
static CORBA::Object_ptr create_object_reference(
const char* interfaceName,
const char* stroid,
CORBA::NVList_ptr criteria);
static CORBA::Object_ptr create_active_object_reference(
const char* interfaceName,
const char* stroid,
Tobj_Servant servant);
static CORBA::Object_ptr get_object_reference();
static void register_factory(
CORBA::Object_ptr factory_or,
const char* factory_id);
static void unregister_factory(
CORBA::Object_ptr factory_or,
const char* factory_id);
static void deactivateEnable()
static void deactivateEnable(
const char* interfaceName,
const char* stroid,
Tobj_Servant servant);
static CORBA::ORB_ptr orb();
static Tobj_Bootstrap* bootstrap();
static void open_xa_rm();
static void close_xa_rm();
static int userlog(char*, ... );
static char* get_object_id(CORBA::Object_ptr obj);
static void application_responsibility(
Tobj_Servant servant);
};

TP::application_responsibility

Synopsis

Tells the TP Framework that the application is taking responsibility for the servant's lifetime.

C++ Binding

static void application_responsibility(Tobj_Servant servant);

Arguments

servant

A pointer to a servant that is already known to the TP Framework.

Return Values

None.

Description

This method tells the TP Framework that the application is taking responsibility for the servant's lifetime. As a result of this call, when the TP Framework has completed deactivating the object (that is, after invoking the servant's deactivate_object method), the TP Framework does nothing more with the object.

Once an application has taken responsibility for a servant, the application must take care to delete servant when it is no longer needed, the same as for any other C++ instance.

If the servant is not known to the TP Framework (that is, it is not active), this call has no effect.

Exceptions

TobjS::InvalidServant

Indicates that the specified servant is Null.

TP::bootstrap()

Synopsis

Returns a pointer to a Tobj::Tobj_Bootstrap object. The Bootstrap object is used to access initial object references for the FactoryFinder object, the Interface Repository, the TransactionCurrent, and the SecurityCurrent objects.

C++ Binding

static Tobj_Bootstrap* TP::bootstrap();

Arguments

None.

Return Value

Upon successful completion, bootstrap() returns a pointer to the Tobj::Tobj_Bootstrap object that is created by the TP Framework when the server application is started.

Description

The TP Framework creates a Tobj::Tobj_Bootstrap object as part of initialization; it is not necessary for the application code to create any other Tobj::Tobj_Bootstrap objects in the server.

Caution: Because the TP Framework owns the Tobj::Tobj_Bootstrap object, server application code must not dispose of the Bootstrap object.

Exceptions

None.

TP::close_xa_rm()

Synopsis

Closes the XA resource manager to which the invoking process is linked.