![]() |
![]() |
BEA WebLogic Enterprise 4.2 Developer Center |
![]() HOME | SITE MAP | SEARCH | CONTACT | GLOSSARY | PDF FILES | WHAT'S NEW |
||
![]() DEVELOPING APPLICATIONS | TABLE OF CONTENTS | PREVIOUS TOPIC | NEXT TOPIC | INDEX |
This chapter presents an overview of one way in which you can call a BEA TUXEDO service from within an object managed by a WebLogic Enterprise server application, using the Wrapper sample application as an example.
This chapter includes the following topics:
The Wrapper sample application delegates a set of billing operations to a BEA TUXEDO teller application, which contains a set of services that perform basic billing procedures. The approach in this chapter shows one technique for incorporating a BEA TUXEDO application into a WebLogic Enterprise domain.
The examples shown in this chapter demonstrate a one-to-one relationship between operations on an object and calls to specific services within a BEA TUXEDO server application. In a sense, the calls to the BEA TUXEDO services are wrapped as operations on a CORBA object; thus, the object delegates its work to the BEA TUXEDO application. If you have a set of BEA TUXEDO services that you want to use in a WebLogic Enterprise server application, the technique shown in this chapter may work for you.
This chapter does not provide any details about BEA TUXEDO applications. For information about how to build and configure BEA TUXEDO applications, and for information about how they work, see the BEA TUXEDO information set.
The process described in this chapter for wrapping a set of BEA TUXEDO services encompasses the following steps:
Overview of Wrapping a BEA TUXEDO Service
The following figure shows a high-level view of the relationship among the client application, the CORBA object managed by the WebLogic Enterprise server application, and the BEA TUXEDO application that implements the services called from the CORBA object.
The first step described in this chapter is designing the object that wraps the calls to the BEA TUXEDO application. For example, the goal for the Wrapper sample application is to add billing capability to the student registration process, which can be done by delegating a set of billing operations to an existing BEA TUXEDO teller application.
The BEA TUXEDO teller application used by the Wrapper sample application contains the following services:
CURRBALANCE
-- Obtains the current balance of a given account
Each of these operations on the A typical usage scenario of the Teller
object maps one-to-one to calls on the services in the BEA TUXEDO teller application.
Teller
object may be the following:
register_for_courses()
operation on the
Registrar
object, which requires a student ID.
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 6-8.
The next step described in this chapter is creating the buffer within which messages are sent between the object and the BEA TUXEDO service. There are a number of buffer types that may be used by various BEA TUXEDO applications, and the examples used in this chapter are based on the FML buffer type. For more information about buffer types in the BEA TUXEDO system, see the BEA TUXEDO information set.
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 BEA TUXEDO service, and specifying a buffer size.
You also need to add to your implementation's header file the definition of the variable that represents the buffer.
The following code example shows the constructor for the Wrapper application's Teller
object that allocates the BEA TUXEDO buffer, m_tuxbuf
:
Teller_i::Teller_i() :
m_tuxbuf((FBFR32*)tpalloc("FML32", "", 1000))
{
if (m_tuxbuf == 0) {
throw CORBA::INTERNAL();
}
}
Note the following about the line that allocates the FML buffer:
The object's implementation file should also deallocate the buffer in the destructor, as in the following statement from the Wrapper application implementation file:
tpfree((char*)m_tuxbuf);
The next step is implementing the operations on the object that wraps calls to the BEA TUXEDO application. In this step, you choose the implementation of how the BEA TUXEDO services are called from the object. The Wrapper sample application uses the tpcall
implementation.
An operation on an object that wraps a BEA TUXEDO service typically includes statements that do the following:
The following example shows the implementation of the In this code example, note the following:
The following statement fills the message buffer, The following statement calls the The following statement extracts the balance from the returned BEA TUXEDO message buffer:
The last line in the Note the following restrictions regarding how you can incorporate BEA TUXEDO services within a WebLogic Enterprise domain:
get_balance()
operation in the Wrapper application Teller
object. This operation retrieves the balance of a specific account, and the BEA TUXEDO service being called is CURRBALANCE
.
CORBA::Double Teller_i::get_balance(BillingW::AccountNumber account)
{
// "marshal" the "in" parameters (account number)
Fchg32(m_tuxbuf, ACCOUNT_NO, 0, (char*)&account, 0);
long size = Fsizeof32(tuxbuf);
// Call the CURRBALANCE TUXEDO service
if (tpcall("CURRBALANCE", (char*)tuxbuf, 0,
(char**)&tuxbuf, &size, 0) ) {
throw CORBA::PERSIST_STORE();
}
// "unmarshal" the "out" parameters (current balance)
CORBA::Double currbal;
Fget32(m_tuxbuf, CURR_BALANCE, 0, (char*)&currbal, 0);
return currbal;
}m_tuxbuf
, with the student account number. For information about FML, see the BEA TUXEDO Reference Manual: Section 3FML, FML pages.
Fchg32(m_tuxbuf, ACCOUNT_NO, 0, (char*)&account, 0);
CURRBALANCE
BEA TUXEDO service, via the tpcall
implementation, passing the message buffer. This statement also specifies where the BEA 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.
if (tpcall("CURRBALANCE", (char*)tuxbuf, 0,
(char**)&tuxbuf, &size, 0) ) {
throw CORBA::PERSIST_STORE();
}Fget32(m_tuxbuf, CURR_BALANCE, 0, (char*)&currbal, 0);
get_balance()
operation returns the results to the client application:
return currbal;
Restrictions
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 This section describes the design for the Wrapper sample application, which incorporates an additional server application, Billing, into the configuration. Therefore, the Wrapper sample application consists of the following four server applications:
Design Considerations for the Wrapper Sample Application
Registrar
object performs, as part of its registration process, invocations to the Teller
object, which charges the student's account for the course.
RegistrarFactory
, Registrar
, and CourseSynopsisEnumerator
objects
TellerFactory
and Teller
objects
CURRBALANCE
, CREDIT
, and DEBIT
services
In addition, the UBBCONFIG
file for the Wrapper sample application specifies the following groups:
The configuration of the WebLogic Enterprise domain in the Wrapper sample application is shown in the following figure.
Incorporating a BEA TUXEDO application into the University sample applications makes sense from the standpoint of using the Process-Entity design pattern. BEA TUXEDO applications generally implement the Process-Entity design pattern, which are also used in the University sample applications.
The University database is updated to include a new table containing account information for each student. Therefore, when services in the BEA TUXEDO Teller Application process billing data, they perform transactions using the University database.
A typical usage scenario in the Wrapper sample application encompasses the following sequence of events:
How the Wrapper University Sample Application Works
get_student_details()
operation on the Registrar
object. Included in the
implementation of the get_student_details()
operation is code that retrieves:
register_for_courses()
operation invokes:
get_balance()
operation on the Teller
object, to make sure that the student does not have a delinquent account
get_balance()
and debit()
operations on the Teller
object each send a
request to the BEA TUXEDO 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 BEA
TUXEDO Teller application.
If the student has a delinquent account, the If the Registrar
object returns the DelinquentAccount
exception to the client application. The client application then rolls back the transaction.
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).
Registrar
object registers the student for
the desired courses.
The following interface definitions are defined for the Billing server application:
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.
Teller
object, which, as mentioned earlier, implements the following operations:
The following additional considerations influence the design of the Wrapper sample application:
Additional Design Considerations for the Wrapper Sample Application
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:
Registrar
object creates an object reference to the
CourseSynopsisEnumerator
object.
However, now that there are two server processes running, and an object in one process needs to send a request to an object managed by the second process, the procedure is not quite so straightforward. For example, the notion of getting an object reference to an object in another server process has important implications. For one, the second server process has to be running when the request is made. Also, the factory for the object in the other server process must be available.
The Wrapper sample application addresses this by incorporating the following configuration and design elements:
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:
resolve_initial_references()
operation on the Bootstrap object to get the FactoryFinder object
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.
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 5-20.
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.
As mentioned earlier, the Billing server application is configured in a group separate from the group containing the University database and the University, BEA TUXEDO Teller, and Oracle7 transaction manager server (TMS) applications.
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:
UBBCONFIG
file
buildobjserver
command when you build the server application
For information about building, configuring, and running the Wrapper sample application, see the Guide to the University Sample Applications.