Programming Guide |
Initiates a service call from a client agent
service_callserviceName
([requestMsg
] [[,]replyMsg
])
[callOption
]...
serviceName
- Any JIF-defined service, specified as a variable or quoted string. The service name can be up to 15 characters long.
requestMsg
- Message data supplied by this client to the server, where
requestMsg
's data type is defined in the JIF's definition of this service. For more information on message data types, refer to "Service Messages and Data Types" in JetNet/Oracle Tuxedo Guide.replyMsg
- Specifies the variables to receive the data that the service returns to the client. The format of the return data is specified in the JIF's definition of the service. If the service call also specifies request message data, separate the two messages with a comma. For more information on message data types, refer to "Service Messages and Data Types" in JetNet/Oracle Tuxedo Guide.
callOption
- One or more options that control service call behavior. Each call option can be set through the service's JIF definition; unless the command specifies otherwise, the service call uses the JIF settings.
service_call
call options always have precedence over their corresponding JIF settings. You set call options through these key words:
ASYNC
- Specifies to let the client resume processing immediately after issuing the call without waiting for a response. If you omit this option, all processing on the client is suspended until the service call returns.
NOTIMEOUT
- If service calls are blocked (the
tp_block
property is set to Yes), this option overrides the blocking timeout and blocks the call indefinitely.NOREPLY
- Use only in
ASYNC
mode to inform Panther that this service call expects no reply, so there is no need to poll for one.Note: From the client's perspective, Panther makes no attempt to poll for a reply or to receive one; however, Panther might quietly poll for a reply if required by the middleware to end the client-server connection.
The following restrictions apply to the use of
NOREPLY
:
- (Oracle Tuxedo only) The
NOREPLY
option cannot be used with a service request that is part of a transaction. To remove a service request from an active transaction use theOUTSIDE_TRANSACTION
option.OUTSIDE_TRANSACTION
(Oracle Tuxedo only)- Specifies to execute the service call independently of the active transaction, if one exists. Use this option in order to prevent events generated by this request from being affected by commits or rollbacks of the current transaction. If you specify this option, transaction-level exception and unload handlers are not executed when their corresponding events are generated.
EXCEPTION_HANDLER
handler
- Specifies an exception handler to install at the request scope, where handler is a Panther variable or a string. This handler handles any exceptions that result from the request or its response.
The handler is installed just before service invocation, that is, after all parsing, interpretation, and validation of the command has occurred. For more information on exception events and handlers, refer to "Exception Handlers"in JetNet/Oracle Tuxedo Guide.
UNLOAD_HANDLER
handler
- Specifies an unload handler to install at the request scope, where handler is a Panther variable or a string. This handler handles any unload events that might result from receiving the service's response. The service must be called synchronously (without the
ASYNC
option).The handler is installed just before service invocation. For more information on unload events and handlers, refer to "Unload Handlers" in JetNet/Oracle Tuxedo Guide.
PRIORITY
priority
- A signed or unsigned integer that sets the priority for
serviceName
. If unsigned, priority overrides this service's predefined priority; if signed, priority is added or subtracted from the predefined priority. In both cases, a service's priority level must be between 1 and 100. If you omit this option, the middleware uses the priority that is set in the JIF or (under Oracle Tuxedo), in theTUXCONFIG
configuration file.
JetNet, Oracle Tuxedo
Client, Server
The
service_call
command invokes a service request that can be issued by a client or a server. A server that requests a service acts in the role of a client. The JIF is accessed at runtime to determine predefined service attributes such as message data type.
service_call
can specify zero to two messages that enable exchange of data between the calling client and the server that processes the requested service. Depending on how the JIF defines the service's transport method, message data can have one of these forms:
- ()—No data sent or received.
The JIF also defines each message's data type. For more information, refer to "Service Messages and Data Types"in JetNet/Oracle Tuxedo Guide.
If the JIF defines a service to use the transaction manager, any data that the transaction manager needs for a database operation or that it returns is automatically appended to the corresponding request or reply message. For example, service
customer_s
specifiesSelect
as its transaction type. When that service is called, the middleware appends to the request message any data that the transaction manager needs to construct aSELECT
statement. When the service returns, the middleware appends the query results to the reply message.When
service_call
calls a service that uses the transaction manager, the command must always specify one or both messages, according to the transaction's type. Thus, a service that specifiesSelect
as its transaction type must be called with both messages; a service definition that specifiesDelete
as its transaction type can be called with only a single (request) message.If a
service_call
command has no message data of its own, the command must use the default mapping format for one or both messages:{...}
. For example, aservice_call
command can invoke thecustomer_s
service as follows:service_call "customer_s" ({...}, {...})
By default, a service call is issued in synchronous mode—that is, processing on the client is suspended until it receives a reply from the service. You can specify asynchronous mode for a service call through the
ASYNC
option. In this case, client processing continues without waiting for a response from the service.Asynchronous processing might be desired if a client transaction includes several service calls that can be executed simultaneously. For example, a bank account transfer procedure requiring a debit to one account and a credit to another might be performed simultaneously as one transaction. If there is an error in the execution of one service, the entire transaction can be rolled back (Oracle Tuxedo only).
Asynchronous service calls can be issued by clients and servers, with these differences:
- For clients, Panther polls continuously for a reply from the service. This guarantees that requested data is returned when the service completes.
When a client agent initiates a service call, events are raised depending on the
service_call
options used. Figure 2-1 shows the sequence of events as the service call is processed.
Figure 2-1 Event stream generated by a service_call
Refer to Chapter 6, "JetNet/Oracle Tuxedo Event Processing," in JetNet/Oracle Tuxedo Guide for information on middleware-related events, and how handlers can be used to customize your application's response to specific service calls.
The following scenarios illustrate a variety of ways of using
service_call
:
If service
INQUIRY
is defined in the JIF to allow only incomingJAMFLEX
data, you can pass the string"Brontis"
to the service as follows:service_call "INQUIRY" ({"Brontis"})
The following code calls the same service in asynchronous mode, passing the content of variable
name
to the service:service_call "INQUIRY" ({name}) ASYNC
If service
GET_NAME
is defined in the JIF to allow only outgoingJAMFLEX
data, you can designate variablename
to receive string data from the service as follows:service_call "GET_NAME" ({name})This code also calls the
GET_NAME
service, this time specifying an unload handler (name_unload
) to unload the data:service_call "GET_NAME" ({name}) UNLOAD_HANDLER "name_unload"
The four examples illustrate how the service
DEPOSIT
is called. The service can be defined in the JIF to useJAMFLEX
buffer types for messages.
- Call the
DEPOSIT
service and designate the content of the variablesACCOUNT_ID
andAMOUNT
asIN
parameters, and designate the content ofMESSAGE
andACCOUNT_BAL
as the data to receive back from the service:
service_call "DEPOSIT" ({ACCOUNT_ID, AMOUNT},\
{MESSAGE, ACCOUNT_BAL})- Call the
DEPOSIT
service and map local variable id toACCOUNT_ID
and local variableamt
toAMOUNT
in asynchronous mode with theNOREPLY
option:
service_call "DEPOSIT" ({ACCOUNT_ID=id, AMOUNT=amt})\
ASYNC NOREPLY- Call the
DEPOSIT
service and map the local variable id toACCOUNT_ID
and local variableamt
toAMOUNT
, and map the receivingMESSAGE
into the local variable msg, andACCOUNT_BAL
into the local variablebal
:
service_call "DEPOSIT" ({ACCOUNT_ID=id, AMOUNT=amt},\
{MESSAGE=msg, ACCOUNT_BAL=bal})- Call the
DEPOSIT
service with a relative priority of +50:
service_call "DEPOSIT" PRIORITY +50 \
({ACCOUNT_ID, AMOUNT},{MESSAGE, ACCOUNT_BAL})
Under Oracle Tuxedo, the same service can be defined to use FML buffer types. This requires that the FML file contain the following entries for FML fields for the
bankapp
database:
Name Number Type Comments
ACCOUNT_ID
101
long
Account No.
ACCOUNT_BAL
117
float
Account balance
AMOUNT
111
float
Transaction amount
MESSAGE
126
string
Message text
The screen variables have identical names to the FML fields.
Table 2-1 shows which application properties are affected when
service_call
executes:
service_call
can generate the following exceptions:
The following procedure
init_atm
initiates the client identification process when a user logs on as an ATM customer. FML buffers are used in a call to theVAL_PIN
service. For the server end of this process, refer to the receive command.proc init_atm ()
vars message...
@app()->hdl_exception = "exc_hand"
@app()->hdl_jif_changed = "jchhandc"client_init client last_name user "Customer" \
notification poll
if ((@app()->tp_severity) > TP_WARNING)
{
// initiating a connection was unsuccessful
message = @app()->tp_exc_msg
msg quiet message
...
return 0
}
// validate PIN given by the customer
service_call service "VAL_PIN" ({last_name, pin}, \
{message, owner_ssn = user_info})
// check if validation was not successful
if ((@app()->tp_severity > TP_WARNING) || \
(@app()->tp_svc_outcome == TP_FAILURE))
{
msg quiet message
client_exit
...
}
...
return 0
}
receive, service_cancel, service_forward, wait