• CURRBALANCE—obtains the current balance of a given account
• CREDIT—credits an account by a given dollar amount
• DEBIT—debits an account by a given dollar amountTo wrap these services, the Wrapper sample application includes a separate OMG IDL file that defines a new interface, Teller, which has the following operations:
•
• Each of these operations on the Teller object maps one-to-one to calls on the services in the Oracle Tuxedo ATMI teller application.A typical usage scenario of the Teller object may be the following:
1. The client application invokes the register_for_courses() operation on the Registrar object, which requires a student ID.
2. As part of the registration process, the Registrar object invokes the get_balance() operation on the Teller object, passing an account number.
3. The get_balance() operation on the Teller object puts the account number into a message buffer and sends the buffer to the Oracle Tuxedo ATMI teller application’s CURRBALANCE service.
4.
5. The CURRBALANCE service obtains from the University database the current balance of the account and gives it to the Oracle Tuxedo ATMI teller application.
6.
7. The Teller object extracts the current balance amount from the message buffer and returns the current balance to the Registrar object.For more design information about the Teller object and the Wrapper sample application, see the section “Design Considerations for the Wrapper Sample Application” on page -7.In your application implementation file, you need to allocate the chosen buffer type. You can allocate the buffer in the object’s constructor, because the buffer you allocate does not need to be unique to any particular Teller object instance. This allocation operation typically includes specifying the buffer type, passing any flags appropriate for the procedure call to the Oracle Tuxedo service, and specifying a buffer size.The following code example shows the constructor for the Wrapper application’s Teller object that allocates the Oracle Tuxedo buffer, m_tuxbuf:
The following example shows the implementation of the get_balance() operation in the Wrapper application Teller object. This operation retrieves the balance of a specific account, and the Oracle Tuxedo service being called is CURRBALANCE.The statement in the following code example fills the message buffer, m_tuxbuf, with the student account number. For information about FML, see the Oracle Tuxedo ATMI FML Function Reference.The following statement calls the CURRBALANCE Oracle Tuxedo service, via the tpcall implementation, passing the message buffer. This statement also specifies where the Oracle Tuxedo service response is to be placed, which in this example is also the same buffer as the one in which the request was sent.The last line in the get_balance() operation returns the results to the client application:
• You may not include the tpreturn() or tpforward() Oracle Tuxedo implementations within an object that calls an Oracle Tuxedo service.The basic design considerations for the Wrapper sample application are based on the scenario that is described in this section. When a student registers for a course, the Registrar object performs, as part of its registration process, invocations to the Teller object, which charges the student’s account for the course.
•
•
• In addition, the UBBCONFIG file for the Wrapper sample application specifies the following groups:
1. After the student logon procedure, the client application invokes the get_student_details() operation on the Registrar object. Included in the implementation of the get_student_details() operation is code that retrieves:
• The student’s balance from the account table in the database, which is obtained by invoking the get_balance() operation on the Teller object
3. The client application sends a request to the Registrar object, as with the Transactions sample application scenario, to invoke the register_for_courses() operation. The request continues to include only a list of course numbers and a student ID.
4. While registering the student for the list of courses, the register_for_courses() operation invokes:
• The get_balance() operation on the Teller object, to make sure that the student does not have a delinquent account
• The debit() operation on the Teller object, which is managed by the Billing server application to bill for courses
5. The get_balance() and debit() operations on the Teller object each send a request to the Oracle Tuxedo ATMI Teller application. Encapsulated in the request is an FML buffer containing the appropriate calls, including the account number calls to, respectively, the CURRBALANCE and DEBIT services in the Oracle Tuxedo ATMI Teller application.
6. The CURRBALANCE and DEBIT services perform the appropriate database calls to, respectively, obtain the current balance and debit the student’s account to reflect the charges for the courses for which he or she has registered.If the student has a delinquent account, the Registrar object returns the DelinquentAccount exception to the client application. The client application then rolls back the transaction.If the debit() operation fails, the Teller object invokes the rollback_only() operation on the TransactionCurrent object. Because the Teller and Registrar objects are scoped within the same transaction, this rollback affects the entire registration process and thus prevents the situation where there is an inconsistent database (showing, for example, that the student is registered for the course, but the student’s account balance has not been debited for the course).
7. If no exceptions have been raised, the Registrar object registers the student for the desired courses.
• The TellerFactory object, whose only operation is find_teller(). The find_teller() operation works exactly the same as the find_registrar() operation in the University server RegistrarFactory object.
• The Teller object, which, as mentioned earlier, implements the following operations:
•
• Like the Registrar object, the Teller object has no state data and does not have a unique object ID (OID).
• The Registrar object needs a way to send requests to the Teller object to handle billing operations.Both of these considerations have implications on the UBBCONFIG file for the Wrapper sample application. The following sections discuss these and other additional design considerations in detail.Up until now, all the objects in the University server application have been defined in the same server process. Therefore, for one object to send a request to another object is fairly straightforward, and is summarized in the following steps, using the Registrar and CourseSynopsisEnumerator objects as an example:
1.
2. Using the newly created object reference, the Registrar object sends the request to the CourseSynopsisEnumerator object.
3. If the CourseSynopsisEnumerator object is not in memory, the TP Framework invokes the Server::create_servant() operation on the Server object to instantiate the CourseSynopsisEnumerator object.
• The University server application gets the object reference to the TellerFactory object in the University Server object’s Server::initialize() operation. The University server application then caches the TellerFactory object reference. This introduces a performance optimization because, otherwise, the Registrar object would need to do the following each time it needs a TellerFactory object:
• Invoke the resolve_initial_references() operation on the Bootstrap object to get the FactoryFinder object.
• Invoke the find_one_factory_by_id() operation on the FactoryFinder object to obtain a reference to a TellerFactory object.
• The Billing server process is started before the University server process is started. When the Registrar object subsequently invokes the TellerFactory object, the Registrar object uses the object reference acquired by the Server::initialize() operation (described in the preceding list item). You specify in the UBBCONFIG file the order in which server processes are started.
• To handle billing during the course registration process, the register_for_courses() and get_student_details() operations on the Registrar object are modified to include code that invokes operations on the Teller object.The Wrapper sample application is designed to handle the situation in which the amount owed by the student exceeds the maximum allowed. If the student tries to register for a course when he or she owes more than is permitted by University, the Registrar object generates a user-defined DelinquentAccount exception. When this exception is returned to the client application, the client application rolls back the transaction. For information about how to implement user-defined exceptions, see the section “User-defined Exceptions” on page -17.Another consideration that affects the performance of the Wrapper sample application is setting the appropriate transaction policies for the interfaces of the objects in that application. The Registrar, CourseSynopsisEnumerator, and Teller objects are configured with the always transaction policy. The RegistrarFactory and TellerFactory objects are configured with the ignore transaction policy, which prevents the transactional context from being propagated to these objects, which do not need to be included in transactions.However, since the Billing server application participates in the transactions that register students for courses, the Billing server application must include invocations to the TP::open_xa_rm() and TP::close_xa_rm() operations in the Server object. This is a requirement for any server application that manages an object that is included in any transaction. If that object does not perform any read or write operations on a database, you can specify the NULL resource manager in the following locations:
• In the appropriate group definition in the UBBCONFIG file
• In an argument to the buildobjserver command when you build the server applicationFor information about building, configuring, and running the Wrapper sample application, see the Guide to the CORBA University Sample Applications.