The purpose of this chapter is to describe the environment in which you will be writing code for a BEA TUXEDO system application.
In addition to the C code that expresses the logic of your application, you will be using the Application-Transaction Monitor Interface (ATMI), which refers to the interface between the BEA TUXEDO system transaction monitor and your application. The ATMI primitives are C language functions that resemble UNIX system calls, but they have the specific purpose of implementing the communication among application modules running under the control of the BEA TUXEDO system transaction monitor, including all the associated resources you need.
As you might remember from the BEA TUXEDO Product Overview, the BEA TUXEDO system uses an enhanced client-server architecture. Chapters 2 through 7 of this book describe how the ATMI primitives are used in writing and debugging clients and services. This chapter provides some of the context within which you will be doing that work.
A client process takes user input and sends it as a service request to a server process that offers the requested service.
A client process uses one ATMI primitive to join an application, allocates a message buffer by using another ATMI primitive, and uses still others to send the buffer to a server and receive the reply.
The operation of a basic client process can be summarized by the pseudo-code shown in Listing 1-1.
The BEA TUXEDO System Development Environment
Client Processes
Basic Client Operation
Listing 1-1
Pseudo-code for a Client
main()
{
allocate a TPINIT buffer
place initial client identification in buffer
enroll as a client of the BEA TUXEDO application
allocate buffer
do while true {
place user input in buffer
send service request
receive reply
pass reply to the user }
leave application
}
Most of the statements in Listing 1-1 are implemented with ATMI primitives. Placing user input in a buffer and passing the reply to the user are implemented with C language functions.
When client programs are ready to test, you use the buildclient
(1) command to compile and link edit them.
A client may send and receive any number of service requests before leaving the application. These can be sent as a series of request/response calls or, if it is important to carry state information from one call to the next, a connection to a conversational server can be set up. The logic within the client program is about the same, but different ATMI primitives are used.
Servers are processes that provide one or more services. They continually check their message queue for service requests and dispatch them to the appropriate service subroutines.
Applications combine their service subroutines with the main()
that BEA TUXEDO provides in order to build server processes. This system supplied main
() is a set of predefined functions. It performs server initialization and termination and allocates buffers to receive and dispatch incoming requests to service routines. All of this processing is transparent to the application.
Server and a service subroutine interaction can be summarized by the pseudo-code shown in Figure 1-1.
Figure 1-1 Pseudo-code for a Request/Response Server and a Service Subroutine
After some initialization a server allocates a buffer, waits until a request message is put on its message queue, dequeues the request, and dispatches it to a service subroutine for processing. If a reply is needed, the reply is considered part of request processing.
The conversational paradigm is somewhat different. Pseudo-code is shown in Figure 1-2.
Figure 1-2 Pseudo-code for a Conversational Service Subroutine
The BEA TUXEDO system-supplied main()
contains the code needed to enroll as a server, advertise services, allocate buffers, and dequeue request messages. The ATMI primitives are used in service subroutines that process requests. When they are ready to compile and test, service subroutines are link edited with the server main()
by means of the buildserver
(1) command to form an executable server.
The serially reusable architecture of servers is particularly significant if the operation requested by the user is logically divisible into several services, or several iterations of the same service. Such operations can be overlapped by having a server assume the role of a client and hand off part of the task to another server as part of fulfilling the original client's request. In such a capacity the server becomes a requester. Both clients and servers can be requesters. In fact, a client can only be a requester. The coding model for such a system is easily accomplished with the routines that are provided by ATMI.
A request/response server can also forward a request to another server. This is different from becoming a requester. In this case, the server does not assume the role of client since no reply is expected by the server that forwards a request. The reply is expected by the original client.
The Application-Transaction Monitor Interface is a reasonably compact set of primitives used to open and close resources, begin and end transactions, allocate and free buffers, and provide the communication between clients and servers. Table 1-1 summarizes them. Each routine is documented in Section 3C of the BEA TUXEDO Reference Manual.
In addition to ATMI's transaction management verbs, the BEA TUXEDO system also supports X/Open's TX Interface for defining and managing transactions. Because X/Open used ATMI's transaction demarcation verbs as the base for the TX Interface, the syntax and semantics of the TX Interface are quite similar to ATMI.
Table 1-2 introduces the routines in the TX Interface and highlights the main differences with their corresponding ATMI routines. For maximum portability, the TX routines can be used in place of the ATMI routines shown in Table 1-2.
An Overview of X/Open's TX Interface
The TX interface requires that Listing 1-2 contains an example of how the TX Interface can be used to support chained transactions. Note that tx_open()
be called before using any other TX verbs. Thus, even if a client or a server is not accessing an XA-compliant resource manager, it must call tx_open()
before it can use tx_begin()
, tx_commit()
, and tx_rollback()
to define transactions.
tx_begin()
must be used to start the first of a series of chained transactions. Also, note that before calling tx_close()
, the application must switch to unchained transactions so that the last tx_commit()
or tx_rollback()
does not start a new transaction.
Listing 1-2
Chained Transactions Using TX Verbs
tx_open();
tx_set_transaction_control(TX_CHAINED);
tx_set_transaction_timeout(120);
tx_begin();
do_forever {
do work as part of transaction;
if (no more work exists)
tx_set_transaction_control(TX_UNCHAINED);
if (work done was successful)
tx_commit();
else
tx_rollback();
if (no more work exists)
break;
}
tx_close();
Messages are passed to servers in typed buffers. Why "typed?" Well, different types of data require different software to initialize the buffer, send and receive the data and perhaps encode and decode it, if the buffer is passed between heterogeneous machines. Buffers are designated as being of a specific type so the routines appropriate to the buffer and its contents can be invoked. These issues are typically not of concern to application developers, but more details can be found in buffer
(3c), tuxtypes
(5), and typesw
(5).
The BEA TUXEDO system provides nine buffer types for messages: STRING
, CARRAY
, VIEW
, VIEW32
, FML
, FML32
, X_OCTET
, X_COMMON
, and X_C_TYPE
. Applications can define additional types as needed. Consult the manual pages referred to above and Administering the BEA TUXEDO System.
The STRING
buffer type is used when the data is an array of characters that terminates with the null character.
The data in a CARRAY
buffer is an undefined array of characters, any of which can be null. The CARRAY
is not self-describing and the length must always be provided when transmitting this buffer type. The X_OCTET
buffer type is equivalent to CARRAY
.
The VIEW
type is a C structure that the application defines and for which there has to be a view description file. Buffers of the VIEW
type must have subtypes, which designate individual data structures. The X_C_TYPE
buffer type is equivalent to VIEW
. The X_COMMON
buffer type is similar to VIEW
but is used for both COBOL and C programs so field types should be limited to short, long, and string. The VIEW32
buffer type is similar to VIEW
but allows for larger character fields, more fields, and larger overall buffers.
An FML
buffer is a proprietary BEA TUXEDO system type of self-defining buffer where each data field carries its own identifier, an occurrence number, and possibly a length indicator. This type provides great flexibility at the expense of some processing overhead in that all data manipulation is done via FML
function calls rather than native C statements.
The FML32 data type is similar to FML but allows for larger character fields, more fields, and larger overall buffers.
If you are using the VIEW
or FML
buffer types, some preliminary work is required to create view description files or field table files. In the case of VIEW
s, a description file must exist and must be available to client and server processes that use a data structure described in the VIEW
. For FML
buffers, a field table file containing descriptions of all fields that may be in the buffer must be available.
There are two kinds of VIEW
buffers. One is based on an FML
buffer. The other VIEW
buffer is independent; it is simply a C structure. Both types are described in view description files and compiled with viewc
(1), the BEA TUXEDO system view compiler. We're going to talk first about the FML variety.
BEA TUXEDO System FML
is a family of functions, some of which convert an FML
buffer into a C structure or vice versa. The C structure that is derived from the fielded buffer is referred to as an FML
VIEW
. The reason for converting FML
buffers to C structures and back again is that while FML
buffers provide data independence and convenience, they do involve processing overhead because they must be manipulated using FML
function calls. C structures, while not providing flexibility, offer the performance required for lengthy manipulations on buffer data. If enough manipulation of the data is called for, you can improve the performance of your programs if you transfer fielded buffer data to C structures, operate on the data using normal C functions, and then put the data back into the FML
buffer for storage or message transmission.
There are slight differences between a view description of an FML
-based view and one that is independent of FML
. Listing 1-3 shows a view description file with all of the available data types. The file is myview.v
and the structure is based on an FML
buffer. Note that the CARRAY1
field has a count of 2 occurrences and has the "C" count flag to indicate that an additional count element should be created in the structure so the application can indicate how many of the occurrences are actually being used. It also has the "L" length flag such that there is a length element (which occurs twice, once for each occurrence of the field) indicating how many of the characters the application has populated.
Listing 1-3 View Description File for FML View
VIEW MYVIEW
$ /* View structure */
#type cname fbname count flag size null
float float1 FLOAT1 1 - - 0.0
double double1 DOUBLE1 1 - - 0.0
long long1 LONG1 1 - - 0
short short1 SHORT1 1 - - 0
int int1 INT1 1 - - 0
dec_t dec1 DEC1 1 - 9,16 0
char char1 CHAR1 1 - - '\0'
string string1 STRING1 1 - 20 '\0'
carray carray1 CARRAY1 2 CL 20 '\0'
END
Field table files are always required when using FML
records, including the use of FML
-dependent VIEWS
. A field table file maps the logical name of a field in an FML
buffer to a field identifier that uniquely identifies the field.
An example that could be used with the view shown in Listing 1-3 is shown in Listing 1-4.
Listing 1-4 The myview.flds Field Table File
# name number type flags comments
FLOAT1 110 float - -
DOUBLE1 111 double - -
LONG1 112 long - -
SHORT1 113 short - -
INT1 114 long - -
DEC1 115 string - -
CHAR1 116 char - -
STRING1 117 string - -
CARRAY1 118 carray - -
Listing 1-5 shows the view description file, similar to the example in Listing 1-3, but for a VIEW
independent from FML
.
Listing 1-5 View Description File for Independent Views
$ /* View data structure */
VIEW MYVIEW
#type cname fbname count flag size null
float float1 - 1 - - -
double double1 - 1 - - -
long long1 - 1 - - -
short short1 - 1 - - -
int int1 - 1 - - -
dec_t dec1 - 1 - 9,16 -
char char1 - 1 - - -
string string1 - 1 - 20 -
carray carray1 - 2 CL 20 -
END
Note that in this view description, the format is similar to the FML
-dependent view, except that the columns fbname
and null
in the file are ignored by the view compiler. These columns are not relevant when an FML
buffer does not stand behind the view, but it is necessary to place some value (a dash, for example) in these columns to serve as a placeholder.
The C
float
and double
fields correspond to COBOL
COMP-1
and COMP-2
, respectively.
The field types long
and short
correspond to S9(9)
COMP-5
and S9(4)
COMP-5
respectively in COBOL
. (The use of COMP-5
is for use with MicroFocus COBOL
so that the COBOL
integer fields match the data format of the corresponding C
fields; the data type for VS
COBOL
II
would simply be COMP
.)
The dec_t
type maps to a COBOL
COMP-3
packed decimal field. Packed decimals exist in the COBOL
environment as two decimal digits packed into each byte with the low-order half byte used to store the sign. The length of a packed decimal may be 1 to 9 bytes with storage available for 1 to 17 digits and a sign. The dec_t
field type is supported within the VIEW
definition for the conversion of packed decimals between the C
and the COBOL
environments. The dec_t
field is defined in a VIEW
with a size of two numbers separated by a comma. The number to the left of the comma is the total number of bytes that the decimal occupies in COBOL
. The number to the right is the number of digits to the right of the decimal point in COBOL
. The formula for conversion to the COBOL
declaration is:
dec_t(m
,n
) <=> S9(2*m
-(n
+1),n
)COMP-3
For example, say a size of 6,4 is specified in the VIEW
. There are 4 digits to the right of the decimal point, 7 digits to the left, and the last half byte stores the sign. The COBOL
application programmer would represent this as 9(7)V9(4)
, with the V
representing the decimal point between the number of digits to each side. Note that there is no dec_t
type supported in FML
; if FML
-dependent VIEWs
are used, then the field must be mapped to a C
type in the VIEW
file (for instance, the packed decimal can be mapped to an FML
string field and the mapping functions do the conversion between the formats).
A decimal field can be initialized and accessed in C using the functions described on the decimal
(3c) reference page.
View description files are source files. To use the view in a program, you need a header file that defines the structures in the view. You can create a header file from the myview.v
view description file by invoking the view compiler, viewc
(1). viewc
creates two files. One is the header file and the other is the binary version of the source description file, myview.V.
This binary file must be in the environment when a VIEW
buffer is allocated. For an FML
-dependent VIEW
, the compiler is invoked as follows.
viewc myview.v
The header file it creates from the myview.v
description file is shown in Listing 1-6.
Listing 1-6 Header File Created for FML View
struct MYVIEW {
float float1;
double double1;
long long1;
short short1;
int int1;
dec_t dec1;
char char1;
char string1[20];
unsigned short L_carray1[2]; /* length array of carray1 */
short C_carray1; /* count of carray1 */
char carray1[2][20];
};
To compile a view description of an independent view, use the -n
option on the command line, as follows.
viewc -n myview.v
The header file created is the same with or without the -n
option. Header files for views must be brought into client programs and service subroutines with #include
statements.
For use with VIEW32
, the viewc32
command should be used.
To create a field header file from the field table file, use the mkfldhdr
(1) command. For example:
mkfldhdr myview.flds
creates a file called myview.flds.h
that can be #include
'd in a service routine or client program so you can refer to fields by their symbolic names. The myview.flds.h
header file produced by mkfldhdr
from this field table file is shown in Listing 1-7.
Listing 1-7 The myview.flds.h Header File
/* fname fldid */
/* ----- ----- */
#define FLOAT1 ((FLDID)24686) /* number: 110 type: float */
#define DOUBLE1 ((FLDID)32879) /* number: 111 type: double */
#define LONG1 ((FLDID)8304) /* number: 112 type: long */
#define SHORT1 ((FLDID)113) /* number: 113 type: short */
#define INT1 ((FLDID)8306) /* number: 114 type: long */
#define DEC1 ((FLDID)41075) /* number: 115 type: string */
#define CHAR1 ((FLDID)16500) /* number: 116 type: char */
#define STRING1 ((FLDID)41077) /* number: 117 type: string */
#defineCARRAY1 ((FLDID)49270) /* number: 118 type: carray */
For use with FML32
, the mkfldhdr32
command should be used.
If you are using FML
or VIEW
typed buffers, #include
the header files generated from their field table files or view description files as described above.
In addition, all BEA TUXEDO system application programs must #include
the atmi.h
header file.
If you are using FML
buffers, #include
the fml.h
header file in your programs.
Environment variables needed either for clients or service routines associated with a server can be set in ENVFILE
s that are specified in the configuration file. The environment variables that might have to be set for field tables and view descriptions, for example, are summarized in Table 1-3.
For the The The location of the BEA TUXEDO system binary files must be known to your application. It is the convention to install the BEA TUXEDO system software under a root directory whose location is specified in the The configuration file specifies the configuration of an application to the BEA TUXEDO system. For a BEA TUXEDO system application in production, it is the responsibility of the BEA TUXEDO system administrator to set up a configuration file that defines the application. In the development environment, the responsibility may be delegated to application programmers to create their own.
If you are faced with the task of creating a configuration file, here are some suggestions:
FML32
and VIEW32
record types, the environment variables are suffixed with 32
, that is, FLDTBLDIR32
, FIELDTBLS32
, VIEWFILES32
, and VIEWDIR32
.
CC
and CFLAGS
environment variables are used by the buildclient
(1) and buildserver
(1) commands. You may want to set them in your environment to make compilation of clients and servers more convenient. Set CC
to the command that invokes the C compiler. It defaults to cc
. Set CFLAGS
to the link edit flags you may want to use on the compile command line. Setting this variable is optional.
TUXDIR
environment variable. $TUXDIR/bin
must be included in your PATH
in order for your application to locate the executables for BEA TUXEDO system commands.
Configuration File
ubbshm
that comes with the sample application is a good starting point.
UID
and GID
parameters so that you are the owner of the configuration.
The configuration file is an ASCII file. To make it usable, you have to run The bulletin board is the BEA TUXEDO system name for a group of data structures in a segment of shared memory that is allocated from information stored in All processes that are part of a BEA TUXEDO application share this IPC resource.
Execute the When it is time to bring the application down, execute the Gateway servers support request/response messages only. The following BEA TUXEDO client API calls for sending and receiving are allowed:
Making the Configuration Usable
tmloadcf
(1) to convert it to a binary file. The TUXCONFIG
environment variable must be set to the pathname for the binary file, and exported.
The Bulletin Board
TUXCONFIG
when the application is booted. Both client and server processes attach to the bulletin board. Part of the bulletin board associates service names with the queue address of servers that advertise that service. Clients send their requests to the name of the service they want to invoke, rather than to a specific address.
Starting and Stopping an Application
tmboot
(1) command to bring up an application. The command gets the IPC resources needed by the application, and starts administrative processes and the application servers.
tmshutdown
(1) command. tmshutdown
stops the servers and releases the IPC resources used by the application, except any that might be used by the database resource manager.
Service Gateway
GWTUX2TE
and GWTE2TUX
are BEA TUXEDO system servers that provide connectivity between BEA TUXEDO and BEA TOP END systems. GWTUX2TE
provides connectivity between BEA TUXEDO clients and BEA TOP END servers. GWTE2TUX
provides connectivity between BEA TOP END clients and BEA TUXEDO servers. One or both of these gateway servers may be configured.
Programming Paradigms
BEA TOP END servers cannot set the The following BEA TOP END client API calls are allowed:
APPL_CONTEXT
flag. If this flag is set, the gateway server dissolves the BEA TOP END dialog and returns an error (TPESVCFAIL
) to the BEA TUXEDO client.
tp_client_send
The gateway servers support BEA TUXEDO The The following example shows how gateway servers are defined in the BEA TUXEDO In this example, a BEA TUXEDO client issues Similarly, a BEA TOP END client issues Buffer Types
CARRAY
(X_OCTET
) buffers only. Attempts to send other types of buffers from a BEA TUXEDO application generate an error (TPESVCFAIL
) which is logged by the gateway server.
Configuration
GWTUX2TE
and GWTE2TUX
gateway servers use the BEA TOP END remote client and remote server services. GWTUX2TE
assumes the role of a BEA TOP END client and makes use of the remote client services. GWTE2TUX
assumes the role of a BEA TOP END server and makes use of the remote server services. Therefore, you must provide a BEA TOP END remote client/server configuration file on any BEA TUXEDO node running these gateway processes.
Examples
UBBCONFIG
file and in the BEA TOP END service definition file.
tpcall
to the RSERVICE
service. The request is forwarded (via the GWTUX2TE
gateway) to a BEA TOP END system (pluto
) and invokes a BEA TOP END service (RPRODUCT:RFUNC
).
tp_client_send
, specifying LPRODUCT
as the PRODUCT
and LFUNC
as the FUNCTION
. The request is forwarded (via the GWTE2TUX
gateway) to the BEA TUXEDO system and invokes a BEA TUXEDO service (LSERVICE
).
Listing 1-8
BEA TUXEDO UBBCONFIG File
##############
#UBBCONFIG
*GROUPS
TOPENDGRP GRPNO=1
#
*SERVERS
GWTE2TUX SRVGRP="TOPENDGRP" SRVID=1001 RESTART=Y MAXGEN=3 GRACE=10
CLOPT="-- -f servicedefs -R 30"
GWTUX2TE SRVGRP="TOPENDGRP" SRVID=1002 RESTART=Y MAXGEN=3 GRACE=10
MIN=5 MAX=5
CLOPT="-- -f servicedefs"
Listing 1-9
BEA TOP END Service Definition File
############
#service definition file
*TE_LOCAL_SERVICES
DEFAULT: PRODUCT=LPRODUCT
LSERVICE FUNCTION=LFUNC
*TE_REMOTE_SERVICES
RSERVICE PRODUCT=RPRODUCT FUNCTION=RFUNC
Listing 1-10
BEA TOP END Remote Configuration File
# TOP END remote configuration file
[top end configuration file]
[component type] remote server
[system] pluto
[primary node] //
topendmach 5000