CORBA Programming Reference
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.
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:
The TP Framework, in conjunction with the ORB and the POA, controls the flow of the application program by doing the following:
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.
TP Framework transaction integration provides the following features:
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.
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 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.
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:
method
(This is the default activation policy.)The activation of the CORBA object (that is, the association between the object ID and the servant) lasts until the end of the method. At the completion of a method, the object is deactivated. When the next method is invoked on the object reference, the CORBA object is activated (the object ID is associated with a new servant). This behavior is similar to that of a BEA Tuxedo stateless service.
transaction
The activation of the CORBA object (that is, the association between the object ID and the servant) lasts until the end of the transaction. During the transaction, multiple object methods can be invoked. The object is activated before the first method invocation on the object and is deactivated in one of the following ways:
tmshutdown
or tmadmin
command. These commands are described in the BEA Tuxedo Command Reference online document.The transaction
activation policy provides a means for an object to vote on the outcome of the transaction prior to the execution of the two-phase commit algorithm. An object votes to roll back the transaction by calling Current.rollback_only()
in the Tobj_ServantBase::deactivate_object
method. It votes to commit the transaction by not calling Current.rollback_only()
in the method.
Note: This is a model of resource allocation that is similar to that of a BEA Tuxedo conversational service. However, this model is less expensive than the BEA Tuxedo conversational service in that it uses fewer system resources. This is because of the BEA Tuxedo ORB's multicontexted dispatching model (that is, the presence of many servants in memory at the same time for one server), which makes it possible for a single server process to be shared by many concurrently active servants that service many clients. In the BEA Tuxedo system, the process would be dedicated to a single client and to only one service for the duration of a conversation.
process
The activation of the CORBA object begins when it is invoked while in an inactive state and, by default, lasts until the end of the process.
Note: The TP Framework API provides an interface method (TP::deactivateEnable
) that allows the application to control the timing of object deactivation for objects that have the activation policy
set to process
. For a description of this method, see the section TP::deactivateEnable().
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.
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.
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.
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.
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::deactivateEnabl
e) 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.
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.
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).
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.
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.
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.
The following sections provide information about transaction policies and how to use transactions.
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.
never
The implementation is not transactional. Objects created for this interface can never be involved in a transaction. The system generates an exception (INVALID_TRANSACTION
) if an implementation with this policy is involved in a transaction. An AUTOTRAN
policy specified in the UBBCONFIG
file for the interface is ignored.
ignore
The implementation is not transactional. This policy instructs the system to allow requests within a transaction to be made of this implementation. An AUTOTRAN
policy specified in the UBBCONFIG
file for the interface is ignored.
optional
(This is the default transaction_policy
.)The implementation may be transactional. Objects can be involved in a transaction if the request is transactional. Servers containing transactional objects must be configured within a group associated with an XA-compliant resource manager. If the AUTOTRAN
parameter is specified in the UBBCONFIG
file for the interface, AUTOTRAN
is on.
always
The implementation is transactional. Objects are required to always be involved in a transaction. If a request is made outside a transaction, the system automatically starts a transaction before invoking the method. The transaction is committed when the method ends. (This is the same behavior that results from specifying AUTOTRAN
for an object with the option transaction policy, except that no administrative configuration is necessary to achieve this behavior, and it cannot be overridden by administrative configuration.) Servers containing transactional objects must be configured within a group that is associated with an XA-compliant resource manager.
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).
Transactions are initiated in one of two ways:
CosTransactions::Current::begin()
operation. This can be done in either the client or the server. For a description of this operation, see Using CORBA Transactions.For more information, see Using CORBA Transactions.
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:
CORBA::OBJ_ADAPTER
exception is raised to the client application. This exception is raised because the transaction was initiated in the server application; therefore, the client application would not expect a transactional error condition such as TRANSACTION_ROLLEDBACK
.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:
CORBA::TRANSACTION_ROLLEDBACK
exception to the client application and the transaction is rolled back by the BEA Tuxedo system.AUTOTRAN
or transaction policy always
behavior.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.
Note: Not recommended. The transaction may be timed out and aborted before the method causes the transaction to be resumed.
CORBA::OBJ_ADAPTER
exception to the client, and the transaction is rolled back by the system. The CORBA::OBJ_ADAPTER
exception is raised because the client application did not initiate the transaction, and, therefore, does not expect transaction error conditions to be raised. CORBA::OBJ_ADAPTER
exception to the client application and the transaction is rolled back by the BEA Tuxedo system. The CORBA::OBJ_ADAPTER
exception is raised because the client application did not initiate the transaction, and, therefore, does not expect transaction error conditions to be raised. The following restrictions apply to BEA Tuxedo CORBA transactions:
CORBA::INVALID_TRANSACTION
exception is returned.CORBA::OBJ_ADAPTER
exception is raised.Server::initialize(),
it must either commit or roll back the transaction before returning from the method. If the application does not, the TP Framework shuts down the server. This is because the application has no predictable way of regaining control after completing the Server::initialize
method.transaction
, and if the reason code passed to the method is either DR_TRANS_COMMITTING
or DR_TRANS_ABORTED
, no invocation on any CORBA object can be done from within the Tobj_ServantBase::deactivate_object
method. Such an invocation results in a CORBA::BAD_INV_ORDER
exception.Adhere to the following guidelines when using SQL and Global Transactions:
Note: This is not an issue when an application uses the XA library to connect to the Oracle server because those applications can operate only on global transactions. The Oracle server does not allow local transactions when it is using XA.
Current.begin()
or started implicitly by the system. Check the database vendor documentation for each database product for other possible restrictions when using global transactions.CORBA objects can affect transaction outcome during two stages of transaction processing:
The Current.rollback_only
method can be used to ensure that the only possible outcome is to roll back the current transaction. Current.rollback_only()
can be invoked from any CORBA object method.
CORBA objects that have the transaction activation policy are given a chance to vote whether the transaction should commit or roll back after transactional work is completed. These objects are notified of the completion of transactional work prior to the start of the two-phase commit algorithm when the TP Framework invokes their deactivate_object
method.
Note that this behavior does not apply to objects with process
or method
activation policies. If the CORBA object wants to roll back the transaction, it can call Current::rollback_only
. If it wants to vote to commit the transaction, it does not make that call. Note, however, that a vote to commit does not guarantee that the transaction is committed, since other objects may subsequently vote to roll back the transaction.
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.
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.
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
.
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:
never:
The default setting. It indicates that the interface implementation is not idempotent and that requests should never be automatically retried.always:
Indicates that the interface implementation is idempotent and that requests should always be retried in case of failure.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
.
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 is not supported under the following three instances:
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.
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.
[#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:
If the user specifies factory-based routing when creating the object, then the object will route to a server in that group. The object key contains the group selected during factory-based routing, but the client routing code will recognize that the interface has user-controlled concurrency and specify the desired group. This is accomplished using normal BEA Tuxedo routing.
The TP Framework handles active user-controlled concurrency objects in the same manner as system-controlled concurrency objects. The TP Framework stores information about objects in the local AOM, and calls the activate_object
and deactivate_object
methods at the appropriate times. However, the object will not have an entry in the AOM and the TP Framework will not call any AOM routines. For example, on shutdown, since an active object will not have an AOM handle, calls to remove the entry from the AOM will not be invoked.
The TP Framework handles active user-controlled concurrency objects in the same manner as system-controlled concurrency objects. The TP Framework is called back for transaction events and the TP Framework stores information about transactional user-controlled objects in the local AOM. The main differences when using parallel objects in transactions as opposed to stateful objects are that the AOM is not used for GTRID information and the AOM routines are not called to update or retrieve transactional information.
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.
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:
Server
C++ class, which has virtual methods for application-specific server initialization and termination logicServerBase
C++ class, which has virtual methods for multithreaded server applications.Tobj_ServantBase
C++ class, which has virtual methods for object state managementTP
C++ class, which provides methods to:ULOG
) fileThe visible part of the TP Framework consists of two categories of operations:
Tobj_ServantBase
and Server
classes. These operations are intended to be called by TP Framework code only. The application code should never call the methods of these classes. If it does, unpredictable results may occur.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:
Server
class is a C++ native class. Server.h
file contains the declarations and definitions for the Server class.For a description of the Server interface methods, see ServerBase Interface.
For the C++ mappings, seeServerBase 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:
create_servant_with_id()
method to support implementations requiring knowledge of the target object during the creation of a servantThe 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.
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);
};