Skip navigation.

CORBA Programming Reference

  Previous Next vertical dots separating previous/next from contents/index/pdf Contents View as PDF   Get Adobe Reader

TP Framework

This topic includes the following sections:

The BEA Tuxedo CORBA 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 Server Applications.

The TP Framework is required when developing BEA Tuxedo CORBA 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 Tuxedo provides the 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 CORBA servers and ATMI servers.

Before BEA Tuxedo CORBA, 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 Tuxedo CORBA and its TP Framework give customers a way to develop CORBA applications with performance similar to BEA Tuxedo ATMI applications. BEA Tuxedo CORBA servers 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 Tuxedo server environment will be able to access that same CORBA object executing in a BEA Tuxedo 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 Tuxedo CORBA 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 the Implementation Configuration File (ICF) section.

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 reactivated anywhere that is allowed by the BEA Tuxedo 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.

The phase "the TP Framework obtains a servant" means that when the TP Framework needs a servant to be created, it calls a user-written Server method, either Server::create_servant or ServerBase::create_servant_with_id. 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 removes the reference to the servant, which actually deletes it.

The application must be aware that this current behavior of always creating and removing 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 reuse 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 remove 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, ServerBase::create_servant_with_id, or TP::create_active_object_reference), the TP Framework's default behavior is to remove 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 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 Tobj_ServantBase::_add_ref with a parameter identifying the servant.

Note: In applications written using BEA Tuxedo release 8.0 or later, use the Tobj_ServantBase::_add_ref method instead of the TP::application_responsibility() method. Unlike the TP::application_responsibility() method, the add_ref() method takes no arguments.

The advantage of the application 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 reuse 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 or ServerBase::create_servant_with_id, the application might return a previously saved servant.

Additionally, once an application has taken responsibility for a servant, the application must take care to remove the servant (using Tobj_ServantBase::_remove_ref) when the servant is no longer needed, that is, when the reference count drops to zero, the same as for any other C++ instance. For more information about how the _remove_ref() method works, see Tobj_ServantBase::_remove_ref().

For more information on writing single-threaded and multithreaded server applications, see Creating CORBA Server Applications.

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 the Implementation Configuration File (ICF) section.

Note: The optional policy is the only transaction policy that can be influenced by administrative configuration. If the system administrator sets the AUTOTRAN attribute for the interface by means of the UBBCONFIG file or by using administrative tools, the system automatically starts a transaction upon invocation of the object, if it is not already infected with a transaction (that is, the behavior is as if the always policy were specified).

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 Tuxedo 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:

Note: For each CORBA interface, set AUTOTRAN to Yes if you want a transaction to start automatically when an operation invocation is received. Setting AUTOTRAN to Yes has no effect if the interface is already in transaction mode. For more information about AUTOTRAN, see Using CORBA Transactions.

Restrictions on Transactions

The following restrictions apply to BEA Tuxedo CORBA 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:

Note: Users of SQL cursors must be careful when using an object with the method or process activation policy. A process opens an SQL cursor within a client-initiated transaction. For typical SQL database products, once the client commits the transaction, all cursors that were opened within that transaction are automatically closed; however, the object will not receive any notification that its cursor has been closed.

Transaction Timeouts

When a transaction timeout 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.

 


IIOP Client Failover

It is not always possible to determine when a server instance failed with respect to the work it was doing at the time of failure. For example, if a server instance fails after handling a client request but before returning the response, there is no way to tell that the request was handled. A user that does not get a response will most likely retry, resulting in an additional request.

Support for IIOP client failover has been added to BEA Tuxedo CORBA as an availability enhancement. IIOP client failover provides a transparent mechanism for a CORBA remote client to automatically connect to an alternative ISL and then retry the request in case of failure.

IIOP client failover marks an interface implementation as idempotent. An idempotent implementation is one that can be repeated without any negative side-effects. For example, SET BALANCE.

Setting The Retry Policy

In order to mark an interface implementation as idempotent, you must set the retry policy in the implementation configuration file (ICF) using the retry_policy option. For a description of the ICF, refer to the Implementation Configuration File (ICF) section.

The retry_policy option has two settings:

MIB Support

You can also check the retry policy using the TA_RTPOLICY attribute added to the MIB(5) T_IFQUEUE and T_INTERFACE classes. The TA_RTPOLICY attribute value is either never or always.

Initiating IIOP Client Failover

To initiate IIOP client failover support, ISL servers must be specified using the -C warn|none option in the *SERVERS section of the UBBCONFIG file

This option allows ISL to accept unofficial connection directly from the client orb. ISL servers that are not specified using the -C warn|none option will not be placed in candidate IIOP gateway pools. Consequently, the client will not failover to those ISL servers.

In the following UBBCONFIG file example, the ISL servers specified in lines 1 and 2 will support client failover. The ISL server in line 3 will not.

Listing 3-1 Example UBBCONFIG File IIOP Client Failover Entry

*SERVERS
	ISL SRVGRP=SYS_GRP1 SRVID=10 CLOPT="-A -- -C warn -n //myhost1:2468"
	ISL SRVGRP=SYS_GRP2 SRVID=20 CLOPT="-A -- -C none -n //myhost2:2469"
	ISL SRVGRP=SYS_GRP3 SRVID=30 CLOPT="-A -- -n //myhost3:2470"

IIOP Client Failover Limitations

IIOP Client Failover is not supported under the following three instances:

See Also

 


Weblogic CORBA Clustering and Load Balancing Support

Tuxedo CORBA C++ client supports failover to Weblogic clustering servers and also supports load balancing. For more information, see WebLogic 9.1 documentation - Failover and Replication in a Cluster and Load Balancing in a Cluster.

 


Parallel Objects

Support for parallel objects was added to BEA Tuxedo CORBA in release 8.0 as a performance enhancement. The parallel objects feature enables you to designate all business objects in a particular application as stateless objects. The effect is that, unlike stateful business objects, which can only run on one server in a single domain, stateless business objects can run on all servers in a single domain. Thus, the benefits of parallel objects are as follows:

For more information on parallel objects, see Scaling, Distributing, and Tuning CORBA Applications.

To implement parallel objects, the concurrency policy option has been added to the ICF file. To select parallel objects for a particular application, you set the concurrency policy option to user-controlled. When you select user-controlled concurrency, the business object are not registered with the Active Object Map (AOM) and, therefore, are stateless and can be active on more than one server at a time. Thus, these objects are referred to as parallel objects.

If user-controlled concurrency is selected, the servant implementation must comply with one of the following statements:

In release 8.0 of the BEA Tuxedo software, the Implementation Configuration File (ICF) was modified to support user-controlled concurrency. In Listing 3-2, the changes to add this support are highlighted in bold type. For a description of the ICF syntax, see ICF Syntax.

Listing 3-2 ICF Syntax

[#pragma activation_policy method|transaction|process]
[#pragma transaction_policy never|ignore|optional|always]
[#pragma concurrency_policy user_controlled|system_controlled]
[Module module-name {]
implementation [implementation-name]
{
implements (module-name::interface-name);
[activation_policy (method|transaction|process);]
[transaction_policy (never|ignore|optional|always);]
[concurrency_policy (user_controlled|system_controlled);]
};
[};]

User-controlled concurrency can be used with factory-based routing, all activation policies, and all transaction policies. The interaction with these features is as follows:

Note: There is one restriction with user-controlled concurrency. TP::create_active_object_reference throws a TobjS::IllegalOperation exception if it is passed an interface with user-controlled concurrency set. Since the AOM is not used when user-controlled concurrency is set, there is no way for the TP Framework to connect an active object to this server.

 


TP Framework API

This section describes the TP Framework API. Additional information about how to use this API can be found in Creating CORBA 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:

For a description of the Server interface methods, see ServerBase Interface.

C++ Declarations

For the C++ mappings, seeServerBase Interface.

ServerBase Interface

The serverBase interface allows you to take full advantage of multithreading capabilities. You can create your own Server classes that inherit from the ServerBase class. This provides you with the following:

The ServerBase class provides the same operations that were available in the Server class in earlier releases. The Server class inherits from the ServerBase class.

These methods can be used with single-threaded and multithreaded applications:

These methods can be used with multithreaded server applications only:

Note: Programmers must provide definitions of the Server class methods. The ServerBase class methods have default implementations.

C++ Declarations (in Server.h)

The C++ mapping is as follows:

class OBBEXPDLLUSER ServerBase {
public:
    virtual CORBA::Boolean
initialize(int argc, char** argv) = 0;
    virtual void
release() = 0;
    virtual Tobj_Servant
create_servant(const char* interfaceName) = 0;
       // Default Implementations Supplied
virtual Tobj_Servant
create_servant_with_id(const char* interfaceName,
const char* stroid);
       virtual CORBA::Boolean
thread_initialize(int argc, char** argv);
       virtual void
thread_release();
};
class Server : public ServerBase {
public:
    CORBA::Boolean initialize(int argc, char** argv);
void release();
Tobj_Servant create_servant(const char* interfaceName);
};

 

Skip navigation bar  Back to Top Previous Next