Chapter 6. Using the Jolt Class Library

The BEA Jolt Class Library provides developers with a set of new object-oriented Java language classes for accessing BEA TUXEDO services. These classes allow you to extend applications for Internet and intranet transaction processing. The application developer can use the Jolt Class Library to customize access to BEA TUXEDO services from Java applets. The following Jolt topics are included in this chapter:

To use the information in the following sections, you need to be generally familiar with the Java programming language and object-oriented programming concepts. All of the programming examples are in Java code.

Note: All of the program examples are only fragments used to illustrate Jolt capabilities. They are not intended to be compiled and run as provided. These program examples require additional code to be fully executable.


Class Library Functionality Overview

The Jolt Class Library provides the TUXEDO application developer with the tools to develop client-side applications or applets that will run in a Java-enabled Web browser or as an independent Java application. The bea.jolt package contains the Jolt Class Library. To use the Jolt Class Library, the client program or applet must import this package. For an example of how to import the bea.jolt package, refer to Listing 6-1.

Java Applications vs. Java Applets

Java programs that run in a browser are called "applets." Applets are intended to be small, easily downloaded parts of an overall application that perform specific functions. Many popular browsers impose limitations on the capabilities of Java applets for the purpose of providing a high degree of security for the users of the browser. The following are some of the restrictions imposed on applets:

Programming workarounds exist for most of the restrictions on Java applets. Check your browser's web site (e.g., www.netscape.com or www.microsoft.com) or developer documentation for specific information about the applet capabilities that the browser supports or restricts. You can also use Jolt Relay to overcome some of the network connection restrictions.

A Java application, however, is not run in the context of a browser and is not restricted in the same ways. For example, a Java application can start another application on the host machine where it is executing. While an applet relies on the windowing environment of a browser or appletviewer for much of its user interface, a Java application requires that you create your own user interface. An applet is designed to be small and highly portable. A Java application, on the other hand, can operate much like any other non-Java program. The security restrictions for applets imposed by various browsers and the scope of the two program types are the most important differences between a Java application and a Java applet.

Jolt Class Library Features

The Jolt Class Library has the following characteristics:

Jolt Class Library Error and Exception Handling

The Jolt Class Library returns both Jolt interpreter and TUXEDO errors as exceptions. The Jolt Class Library Reference contains the Jolt classes and lists the errors or exceptions thrown for each class. Appendix A contains the Error and Exception Class Reference.

Jolt Client/Server Relationship

BEA Jolt works in a distributed client/server environment and connects Java clients to BEA TUXEDO based applications. Figure 6-1 illustrates the client/server relationship between a Jolt program and the Jolt Server.

Figure 6-1 Jolt Client/Server Relationship

.

As illustrated in the diagram, the Jolt Server acts as a proxy for a native BEA TUXEDO client, implementing functionality available through the native BEA TUXEDO client. The BEA Jolt Server accepts requests from BEA Jolt clients and maps those requests into BEA TUXEDO service requests through the BEA TUXEDO ATMI interface. Requests and associated parameters are packaged into a message buffer and delivered over the network to the BEA Jolt Server. The BEA Jolt Connection Manager handles all communication between the BEA Jolt Server and the BEA Jolt applet using the BEA Jolt Transaction Protocol. The BEA Jolt Server unpacks the data from the message, performs any necessary data conversions, such as numeric format conversions or character set conversions, and makes the appropriate service request to BEA TUXEDO as specified by the message.

Once a service request enters the BEA TUXEDO system, it is executed in exactly the same manner as any other BEA TUXEDO request. The results are returned through the ATMI interface to the BEA Jolt Server, which packages the results and any error information into a message that is sent to the BEA Jolt client applet. The BEA Jolt client then maps the contents of the message into the various BEA Jolt client interface objects, completing the request.

On the client side, the user program contains the client application code. The Jolt Class Library packages a JoltSession and JoltTransaction, which in turn handle service requests.

The following table describes the client-side requests and Jolt Server-side actions in a simple example program.

Table 6-1 Jolt Client/Server Interaction

Jolt Client

Jolt Server

1

attr=new JoltSessionAttributes();

attr.setString(attr.APPADDRESS, "//myhost:8000");

Binds the client to the TUXEDO environment

2

session=new JoltSession(attr, username, userRole, userPassword, appPassword);

Logs the client on to TUXEDO

3

withdrawal=new JoltRemoteService( servname, session );

Looks up the service attributes in the Repository

4

withdrawal.addString("accountnumber", "123");

withdrawal.addFloat("amount", (float) 100.00);

Populates variables in the client (no Jolt Server activity)

5

trans=new JoltTransaction( time-out, session);

Begins a new TUXEDO transaction

6

withdrawal.call(trans);

Executes the TUXEDO service

7

trans.commit() or trans.rollback();

Completes or rolls back transaction

8

balance = withdrawal.getFloatDef("balance," (float) 0.0);

Retrieves the results (no Jolt Server activity)

9

session.endSession();

Logs the client off of TUXEDO

The following tasks summarize the interaction shown in Table 6-1 and are the steps involved in beginning a transaction:

  1. Bind the client to the TUXEDO environment using the JoltSessionAttributes class.

  2. Establish a session.

  3. Set variables.

  4. Perform the necessary transaction processing.

  5. Log the client off of the TUXEDO system.

Each of these activities is handled through the use of the Jolt Class Library classes. These classes include methods for setting and clearing data and for handling remote service actions. The following section describes the Jolt Class Library classes in more detail.


Jolt Object Relationships

The following diagram illustrates the relationship between the instantiated objects of the Jolt Class Library classes.

Figure 6-2 Jolt Object Relationships

As objects, the Jolt classes interact in various relationships with each other. In Figure 6-2, the relationships are divided into three basic categories:

Contains-a relationship. At the class level an object can contain other objects. For example, a JoltTransaction stores (or contains) a JoltSession object.

Is-a relationship. The is-a relationship usually occurs at the class instance or sub-object level and denotes that the object is an instance of a particular object.

Uses-a relationship. An object can use another object without containing it. For example, a JoltSession can use the JoltSessionAttributes object to obtain the host and port information.


Jolt Class Functionality

Jolt classes are used to perform the basic functions of transaction processing: log on/log off, synchronous service calling, transaction begin, commit, rollback and subscribe to events or unsolicited messages. The following sections describe how the Jolt classes are used to perform these functions.

Logon/Logoff

The client application must log on to the TUXEDO environment prior to initiating any transaction activity. The Jolt Class Library provides the JoltSessionAttributes class and JoltSession class to establish a connection to a TUXEDO System.

The JoltSessionAttributes class is used to contain the connection properties to a Jolt/TUXEDO system and contains various properties about the Jolt/TUXEDO System. To establish a connection, the client application must create an instance of the JoltSession class. This instance is the JoltSession object. By instantiating a JoltSession object, users log on to Jolt/TUXEDO or log off by calling the endSession method.

Synchronous Service Calling

Transaction activities such as requests and replies are handled through the use of a JoltRemoteService object (an instance of the JoltRemoteService class). Each JoltRemoteService object refers to an exported TUXEDO request/reply service. The programmer must provide a service name and a JoltSession object to instantiate a JoltRemoteService object before it can be used.

To use a JoltRemoteService object, the programmer simply:

For efficiency, Jolt does not make a copy of any input parameter object; only the references to the object (e.g., string and byte array) are saved. Since JoltRemoteService object is a stateful object, its input parameters and the request attributes are retained throughout the life of the object. You can use the clear() method to reset the attributes and input parameters, before reusing the JoltRemoteService object.

Since Jolt is designed for a multithreaded environment, multiple JoltRemoteService objects can be invoked simultaneously by using Java's multithreading capability. Refer to "Multithreaded Applications" in this chapter for more information.

Transaction Begin, Commit, and Rollback

In Jolt, a transaction is represented as an object of the class JoltTransaction. The transaction begins when the transaction object is instantiated. The transaction object is created with a time out and JoltSession object parameter:

trans = new JoltTransaction(timeout, session)

Jolt uses an explicit transaction model for any services involved in a transaction. The transaction service invocation requires a JoltTransaction object as a parameter. Jolt also requires that the service and the transaction belong to the same session. Jolt does not allow you to use services and transactions that are not bound to the same session.


Jolt Class Library Walk-through

The example code provided in Listing 6-1 shows how to use the Jolt Class Library and includes the use of the JoltSessionAttributes, JoltSession, JoltRemoteService, and JoltTransaction classes.

The example combines two user-defined TUXEDO services (WITHDRAWAL and DEPOSIT) to perform a simulated TRANSFER transaction. If the WITHDRAWAL operation fails, a rollback is performed. Otherwise, a DEPOSIT is performed and a commit completes the transaction.

The basic steps of the transaction process shown in the example are as follows:

  1. Set the connection attributes like hostname and portnumber in the JoltSessionAttribute object. Refer to the following line in code Listing 6-1:

    sattr = new JoltSessionAttributes();

  2. The sattr.checkAuthenticationLevel() allows the application to determine the level of security required to log on to the server. Refer to the following line in code Listing 6-1:

    switch (sattr.checkAuthenticationLevel())

  3. The logon is accomplished by instantiating a JoltSession object. Refer to the following lines in code Listing 6-1:

    session = new JoltSession (sattr, userName, userRole, 
    userPassword, appPassword);

    This example does not explicitly catch SessionException errors.

  4. All JoltRemoteService calls require a service to be specified and the session key returned from JoltSession(). Refer to the following lines in code Listing 6-1:

    withdrawal = new JoltRemoteService("WITHDRAWAL", session);
    deposit = new JoltRemoteService("DEPOSIT", session);

    These calls bind the service definition of both the WITHDRAWAL and DEPOSIT services, which are stored in the Jolt Repository, to the withdrawal and deposit objects, respectively. The services WITHDRAWAL and DEPOSIT must be defined in the Jolt Repository otherwise a ServiceException will be thrown. This example does not explicitly catch ServiceException errors.

  5. Once the service definitions are returned, the application-specific fields such as account number ACCOUNT_ID and withdrawal amount SAMOUNT are automatically populated. Refer to the following lines in code Listing 6-1:

    withdrawal.addInt("ACCOUNT_ID", 100000);
    withdrawal.addString("SAMOUNT", "100.00");

    The add*() methods can throw IllegalAccessError or NoSuchFieldError exceptions.

  6. The JoltTransaction call allows a timeout to be specified if the transaction does not complete within the specified time. Refer to the following line in code
    Listing 6-1:

    trans = new JoltTransaction(5,session);

  7. Once the withdrawal service definition has been automatically populated, the withdrawal service is invoked by calling the withdrawal.call(trans) method. Refer to the following line in code Listing 6-1:

    withdrawal.call(trans);

  8. A failed WITHDRAWAL can be rolled back. Refer to the following line in code Listing 6-1:

    trans.rollback();

  9. Otherwise, once the DEPOSIT is performed, all the transactions are committed. Refer to the following lines in code Listing 6-1:

    deposit.call(trans);
    trans.commit();

Listing 6-1 shows an example of a simple application for the transfer of funds using the Jolt classes.

Listing 6-1 Jolt Transfer of Funds Example (SimXfer.java)
/* Copyright 1996 BEA Systems, Inc.  All Rights Reserved */
import bea.jolt.*;
public class SimXfer
{
public static void main (String[] args)
{
JoltSession session;
JoltSessionAttributes sattr;
JoltRemoteService withdrawal;
JoltRemoteService deposit;
JoltTransaction trans;
String userName=null;
String userPassword=null;
String appPassword=null;
String userRole="myapp";
        sattr = new JoltSessionAttributes();
sattr.setString(sattr.APPADDRESS, "//bluefish:8501");
        switch (sattr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
System.out.println("NOAUTH\n");
break;
case JoltSessionAttributes.APPASSWORD:
appPassword = "appPassword";
break;
case JoltSessionAttributes.USRPASSWORD:
userName = "myname";
userPassword = "mysecret";
appPassword = "appPassword";
break;
}
sattr.setInt(sattr.IDLETIMEOUT, 300);
session = new JoltSession(sattr, userName, userRole,
userPassword, appPassword);
// Simulate a transfer
withdrawal = new JoltRemoteService("WITHDRAWAL", session);
deposit = new JoltRemoteService("DEPOSIT", session);
        withdrawal.addInt("ACCOUNT_ID", 100000);
withdrawal.addString("SAMOUNT", "100.00");
        // Begin the transaction w/ a 5 sec timeout
trans = new JoltTransaction(5, session);
try
{
withdrawal.call(trans);
}
        catch (ApplicationException e)
{
e.printStackTrace();
// This service uses the STATLIN field to report errors
// back to the client application.
System.err.println(withdrawal.getStringDef("STATLIN","NO
STATLIN"));
System.exit(1);
}
        String wbal = withdrawal.getStringDef("SBALANCE", "$-1.0");
        // remove leading "$" before converting string to float
float w = Float.valueOf(wbal.substring(1)).floatValue();
if (w < 0.0)
{
System.err.println("Insufficient funds");
trans.rollback();
System.exit(1);
}
else // now attempt to deposit/transfer the funds
{
deposit.addInt("ACCOUNT_ID", 100001);
deposit.addString("SAMOUNT", "100.00");
            deposit.call(trans);
String dbal = deposit.getStringDef("SBALANCE", "-1.0");
trans.commit();
            System.out.println("Successful withdrawal");
System.out.println("New balance is: " + wbal);
            System.out.println("Successful deposit");
System.out.println("New balance is: " + dbal);
}
        session.endSession();
System.exit(0);
} // end main
} // end SimXfer


Using TUXEDO Buffer Types with Jolt

Jolt supports all of the TUXEDO typed buffers, data types, and buffer types including the built-in TUXEDO buffer types such as FML, VIEW, CARRAY, and STRING. The following sections include examples for using the TUXEDO STRING, CARRAY, FML, and VIEW buffer types.

For information about all of the TUXEDO typed buffers, data types, and buffer types, refer to the TUXEDO System Programmer's Guide, Volume 1 and the TUXEDO System Reference Manual.

Of the TUXEDO built-in buffer types, the Jolt application programmer should be particularly aware of how Jolt handles the CARRAY (character array) and STRING built-in buffer types. The CARRAY type is used to handle data opaquely, (e.g., the characters of a CARRAY data type are not interpreted in any way). No data conversion is performed between a Jolt client and TUXEDO service.

For example, if a TUXEDO service uses a CARRAY buffer type and the user sets a 32-bit integer (in Java the integer is in big-endian byte order), then the data is sent unmodified to the TUXEDO service. If the TUXEDO service is run on a machine whose processor uses little-endian byte-ordering (e.g., Intel processors), the TUXEDO service must convert the data properly before the data can be used.

Using the STRING Buffer Type

The STRING buffer type is a collection of characters. STRING consists of non-null characters and is terminated by a null character. The STRING data type is character and, unlike CARRAY, you can determine its transmission length by counting the number of characters in the buffer until reaching the null character.

Note: During the data conversion from Jolt to STRING, the null terminator is automatically appended to the end of the STRING buffers because a Java string is not null-terminated.

The following ToUpper code fragment, Listing 6-2, illustrates how Jolt works with a service whose buffer type is STRING. The TOUPPER TUXEDO Service is available in the TUXEDO simpapp example.

Define TOUPPER in the Repository Editor

Before running the ToUpper.java example in Listing 6-2, you need to define the TOUPPER service through the Jolt Repository Editor:

Note: If you are not familiar with using the Jolt Repository Editor, refer to "Adding a Service" and "Adding a Parameter" for more information about defining your services and adding new parameters.

  1. Using the Jolt Repository Editor, define the TOUPPER service for the SIMPAPP package.

    Figure 6-3 Add a TOUPPER Service

  2. For the TOUPPER service, define an input buffer type of STRING and an output buffer type of STRING. (See Figure 6-4.)

  3. Define only one parameter for the TOUPPER service named STRING that is both an input and an output parameter.

    Figure 6-4 Set Input and Output Buffer Types to STRING

ToUpper.java Client Code

The ToUppder.java Java code fragment in Listing 6-2 illustrates how Jolt works with a service whose buffer type is STRING. The example shows a Jolt client using a STRING buffer to pass data to a server. The TUXEDO server would take the buffer, convert the string to all uppercase letters and pass the string back to the client. The following example assumes that a session object was already instantiated.

Listing 6-2 Use of the STRING buffer type (ToUpper.java)
/* Copyright 1996 BEA Systems, Inc.  All Rights Reserved */
import bea.jolt.*;
public class ToUpper
{
public static void main (String[] args)
{
JoltSession session;
JoltSessionAttributes sattr;
JoltRemoteService toupper;
JoltTransaction trans;
String userName=null;
String userPassword=null;
String appPassword=null;
String userRole="myapp";
String outstr;
        sattr = new JoltSessionAttributes();
sattr.setString(sattr.APPADDRESS, "//myhost:8501");
        switch (sattr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
appPassword = "appPassword";
break;
case JoltSessionAttributes.USRPASSWORD:
userName = "myname";
userPassword = "mysecret";
appPassword = "appPassword";
break;
}
sattr.setInt(sattr.IDLETIMEOUT, 300);
session = new JoltSession(sattr, userName, userRole,
userPassword, appPassword);
toupper = new JoltRemoteService ("TOUPPER", session);
toupper.setString("STRING", "hello world");
toupper.call(null);
outstr = toupper.getStringDef("STRING", null);
if (outstr != null)
System.out.println(outstr);
        session.endSession();
System.exit(0);
} // end main
} // end ToUpper

Using the CARRAY Buffer Type

The CARRAY buffer type is a simple character array buffer type that is built into the TUXEDO system. With the CARRAY buffer type, because the system does not interpret the data, although the data type is known, there is no way of determining how much data to transmit during an operation. The application is always required to specify a length when passing this buffer type.

Define ECHO in the Repository Editor

Before running the example in Figure 6-3, you must write and boot an ECHO TUXEDO service. The ECHO service takes a buffer and passes it back to the Jolt client. You will also need to use the Jolt Repository Editor to define the ECHO service.

Figure 6-5 Add ECHO Service

In the Repository Editor add the ECHO service as follows:

  1. Add a service named ECHO whose buffer type is CARRAY.

  2. Define the input buffer type and output buffer type as CARRAY for the ECHO service.

    Figure 6-6 Edit ECHO Service

  3. Define the ECHO service with only one parameter named CARRAY that is both an input and output parameter.

tryOnCARRAY.java Client Code

The code in Listing 6-3 illustrates how Jolt works with a service whose buffer type is CARRAY. Since Jolt does not look into the CARRAY data stream, it is the programmer's responsibility to have the matching data format between the Jolt client and the CARRAY service. The following example assumes that a session object was already instantiated.

Listing 6-3 CARRAY Buffer Type
/* Copyright 1996 BEA Systems, Inc.  All Rights Reserved */
  /* This code fragment illustrates how Jolt works with a service  
* whose buffer type is CARRAY.
*/
import java.io.*;
import bea.jolt.*;
class ...
{
...
public void tryOnCARRAY()
{
byte data[];
JoltRemoteService csvc;
DataInputStream din;
DataOutputStream dout;
ByteArrayInputStream bin;
ByteArrayOutputStream bout;
/*
* Use java.io.DataOutputStream to put data into a byte array
*/
bout = new ByteArrayOutputStream(512);
dout = new DataOutputStream(bout);
dout.writeInt(100);
dout.writeFloat((float) 300.00);
dout.writeUTF("Hello World");
dout.writeShort((short) 88);
/*
* Copy the byte array into a new byte array "data". Then
* issue the Jolt remote service call.
*/
data = bout.toByteArray();
csvc = new JoltRemoteService("ECHO", session);
csvc.setBytes("CARRAY", data, data.length);
csvc.call(null);
/*
* Get the result from JoltRemoteService object and use
* java.io.DataInputStream to extract each individual value
* from the byte array.
*/
data = csvc.getBytesDef("CARRAY", null);
if (data != null)
{
bin = new ByteArrayInputStream(data);
din = new DataInputStream(bin);
System.out.println(din.readInt());
System.out.println(din.readFloat());
System.out.println(din.readUTF());
System.out.println(din.readShort());
}
}
}

Using the FML Buffer Type

FML (Field Manipulation Language) is a flexible data structure that can be used as a typed buffer. The FML data structure stores tagged values that are typed, variable in length, and may have multiple occurrences. The typed buffer is treated as an abstract data type in FML.

FML gives you the ability to access and update data values without having to know how the data is structured and stored. In your application program, you simply access or update a field in the fielded buffer by referencing its identifier. To perform the operation, the FML runtime determines the field location and data type.

FML is especially suited for use with Jolt clients as the client and server code may be in two languages (e.g., Java and C), the client/server platforms may have different data type specifications, or the interface between the client and the server changes frequently.

The following tryOnFml examples illustrate the use of the FML typed buffer. The examples show a Jolt client using FML buffers to pass data to a server. The server takes the buffer, creates a new FML buffer to store the data, and passes that buffer back to the Jolt client. The examples consist of the following components.

tryOnFml.java Client Code

The tryOnFml.java Java code fragment in Listing 6-4 illustrates how Jolt works with a service whose buffer type is FML. The following example assumes that a session object was already instantiated.

Listing 6-4 tryOnFml.java Code Example
/* Copyright 1997 BEA Systems, Inc. All Rights Reserved */

import bea.jolt.*;
class ...
{
...
public void tryOnFml ()
{
JoltRemoteService passFml;
String outputString;
int outputInt;
float outputFloat;
...
passFml = new JoltRemoteService("PASSFML",session);
passFml.setString("INPUTSTRING", "John");
passFml.setInt("INPUTINT", 67);
passFml.setFloat("INPUTFLOAT", (float)12.0);
passFml.call(null);
outputString = passFml.getStringDef("OUTPUTSTRING", null);
outputInt = passFml.getIntDef("OUTPUTINT", -1);
outputFloat = passFml.getFloatDef("OUTPUTFLOAT", (float)-1.0);
System.out.print("String =" + outputString);
System.out.print(" Int =" + outputInt);
System.out.println(" Float =" + outputFloat);
}
}

FML Field Definitions

The following entries in tryOnFml.f16 show FML field definitions for the tryOnFml.java example.

Listing 6-5 tryOnFml.f16 Field Definitions
#
# FML field definition table
#
*base 4100
INPUTSTRING 1 string
INPUTINT 2 long
INPUTFLOAT 3 float
OUTPUTSTRING 4 string
OUTPUTINT 5 long
OUTPUTFLOAT 6 float

Define PASSFML in the Repository Editor

In "Using the STRING Buffer Type", Figure 6-3 illustrated the SIMPAPP package with two services. The TOUPPER service was used to illustrate the STRING typed buffer. The other service in SIMPAPP package is the PASSFML service. This service is used with the tryOnFml.java and tryOnFml.c code. Before running the tryOnFml.java example in Listing 6-4, you need to modify the PASSFML service through the Jolt Repository Editor.

Note: If you are not familiar with using the Jolt Repository Editor, refer to "Adding a Service" and "Adding a Parameter" for more information about defining a service.

  1. Using the Jolt Repository Editor, define the PASSFML service with an input buffer type of FML and an output buffer type of FML.

    Figure 6-7 illustrates the Jolt Repository Edit Services window with the PASSFML service.

  2. Define the input buffer type and output buffer type as FML for the PASSFML service.

    Figure 6-7 Edit the PASSFML Service

  3. Define the parameters for the PASSFML service. In this example, the parameters are: INPUTSTRING, OUTPUTINT, INPUTINT, OUTPUTSTRING, OUTPUTFLOAT, INPUTFLOAT.

    Figure 6-8 Edit the PASSFML Parameters

tryOnFml.c Server Code

Listing 6-6, "tryOnFml.c Code Example," illustrates the server side code for using the FML buffer type. The PASSFML service reads in a input FML buffer and outputs a FML buffer.

Listing 6-6 tryOnFml.c Code Example
/*
 * tryOnFml.c 
*
* Copyright (c) 1997 BEA Systems, Inc. All rights reserved
*
* Contains the PASSFML TUXEDO server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "tryOnFml.f16.h"
/*
* PASSFML service reads in a input fml buffer and outputs a fml buffer.
*/
void
PASSFML( TPSVCINFO *rqst )
{
FLDLEN len;
FBFR *svcinfo = (FBFR *) rqst->data;
char inputString[256];
long inputInt;
float inputFloat;
FBFR *fml_ptr;
int rt;
if (Fget(svcinfo, INPUTSTRING, 0, inputString, &len) < 0) {
(void)userlog("Fget of INPUTSTRING failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTINT, 0, (char *) &inputInt, &len) < 0) {
(void)userlog("Fget of INPUTINT failed %s",Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTFLOAT, 0, (char *) &inputFloat, &len) < 0) {
(void)userlog("Fget of INPUTFLOAT failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
/* We could just pass the FML buffer back as is, put lets */
/* store it into another FML buffer and pass it back. */
if ((fml_ptr = (FBFR *)tpalloc("FML",NULL,rqst->len))==(FBFR *)NULL) {
(void)userlog("tpalloc failed in PASSFML %s",
tpstrerror(tperrno));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTSTRING, inputString, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTINT, (char *)&inputInt, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTFLOAT, (char *)&inputFloat, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %d\n", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
tpreturn(TPSUCCESS, 0, (char *)fml_ptr, 0L, 0);
}

Using the VIEW Buffer Type

VIEW is a built-in TUXEDO typed buffer. The VIEW buffer provides a way to use C structures and COBOL records with the TUXEDO system. The VIEW typed buffer enables the TUXEDO run-time system to understand the format of C structures and COBOL records based on the view description which is read at run time.

When allocating a VIEW, your application specifies a buffer type of VIEW and a subtype that matches the name of the view (the name that appears in the view description file). Since the TUXEDO run-time system can determine the space needed based on the structure size, your application need not provide a buffer length. The run-time system can also automatically take care of things, like computing how much data to send in a request or response, and handle encoding and decoding when the message transfers between different machine types.

The following examples show the use of the VIEW buffer type with a Jolt client and its server-side application. The example consists of three parts:

The Jolt client treats a null character in a VIEW buffer string format as an end-of-line character and truncates any part of the string that follows the null.

simpview.java Client Code

Listing 6-7, "simpview.java Code Example," illustrates how Jolt works with a service whose buffer type is VIEW. The client code is identical to the code used for accessing an FML service.

Note: The code in the following listing does not catch any exceptions. Since all Jolt exceptions are derived from java.lang.RunTimeException, the Java Virtual Machine (VM) will catch these exceptions if the application does not. (A well-written application would catch these exceptions, and take appropriate actions.)

Before running the example in Listing 6-7, you need to add the VIEW service to the SIMPAPP package using the Jolt Repository Editor and write the simpview.c TUXEDO application. This service takes the data from the client VIEW buffer, creates a new buffer and passes it back to the client as a new VIEW buffer. The following example assumes that a session object was already instantiated.

Listing 6-7 simpview.java Code Example
/* Copyright 1997 BEA Systems, Inc. All Rights Reserved */
/*
* This code fragment illustrates how Jolt works with a service whose buffer
* type is VIEW.
*/
import bea.jolt.*;
class ...
{
...
public void simpview ()
{
JoltRemoteService ViewSvc;
String outString;
int outInt;
float outFloat;
// Create a Jolt Service for the TUXEDO service "SIMPVIEW"
ViewSvc = new JoltRemoteService("SIMPVIEW",session);
// Set the input parametes required for SIMPVIEW
ViewSvc.setString("inString", "John");
ViewSvc.setInt("inInt", 10);
ViewSvc.setFloat("inFloat", (float)10.0);
// Call the service. No transaction required, so pass
// a "null" parameter
ViewSvc.call(null);
// Process the results
outString = ViewSvc.getStringDef("outString", null);
outInt = ViewSvc.getIntDef("outInt", -1);
outFloat = ViewSvc.getFloatDef("outFloat", (float)-1.0);
// And display them...
System.out.print("outString=" + outString + ",");
System.out.print("outInt=" + outInt + ",");
System.out.println("outFloat=" + outFloat);
}
}

VIEW Field Definitions

The following entries show the TUXEDO VIEW field definitions for the simpview.java example.

Listing 6-8 simpview.v16 Field Definitions
#
# VIEW for SIMPVIEW. This view is used for both input and output. The
# service could also have used separate input and output views.
# The first 3 params are input params, the second 3 are outputs.
#
VIEW SimpView
$
#type cname fbname count flag size null
string inString - 1 - 32 -
long inInt - 1 - - -
float inFloat - 1 - - -
string outString - 1 - 32 -
long outInt - 1 - - -
float outFloat - 1 - - -
END

Define VIEW in the Repository Editor

Before running the simpview.java and simpview.c examples, you need to define the VIEW service through the Jolt Repository Editor.

Note: If you are not familiar with using the Jolt Repository Editor, refer to "Adding a Service" and "Adding a Parameter" for more information about defining a service.

In the Repository Editor add the VIEW service as follows:

  1. Add a VIEWSVC service for the SIMPAPP package.

  2. Define the VIEWSVC service with an input buffer type of VIEW and an output buffer type of VIEW.

  3. Define the parameters for the VIEW service. In this example the parameters are: cname, inString, inInt, inFloat, outString, outInt, outFloat.

simpview.c Server Code

In the following server code, the input and output buffers are VIEW. The code accepts the VIEW buffer data as input and outputs the same data as VIEW.

Listing 6-9 simpview.c Code Example
/*
* SIMPVIEW.c
*
* Copyright (c) 1997 BEA Systems, Inc. All rights reserved
*
* Contains the SIMPVIEW Tuxedo server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "simpview.h"
/*
* Contents of simpview.h.
*
*struct SimpView {
*
* char inString[32];
* long inInt;
* float inFloat;
* char outString[32];
* long outInt;
* float outFloat;
*};
*/
/*
* service reads in a input view buffer and outputs a view buffer.
*/
void
SIMPVIEW( TPSVCINFO *rqst )
{
/*
* get the structure (VIEWSVC) from the TPSVCINFO structure
*/
struct SimpView *svcinfo = (struct SimpView *) rqst->data;
/*
* print the input params to the UserLog. Note there is
* no error checking here. Normally a SERVER would perform
* some validation of input and return TPFAIL if the input
* is not correct.
*/
(void)userlog("SIMPVIEW: InString=%s,InInt=%d,InFloat=%f",
svcinfo->inString, svcinfo->inInt, svcinfo->inFloat);
/*
* Populate the output fields and send them back to the caller
*/

strcpy (svcinfo->outString, "Return from SIMPVIEW");
svcinfo->outInt = 100;
svcinfo->outFloat = (float) 100.00;
/*
* If there was an error, return TPFAIL
* tpreturn(TPFAIL, ErrorCode, (char *)svcinfo, sizeof (*svcinfo), 0);
*/
tpreturn(TPSUCCESS, 0, (char *)svcinfo, sizeof (*svcinfo), 0);
}


Multithreaded Applications

As a Java based set of classes, Jolt supports multithreaded applications. However, various implementations of the Java language differ with respect to certain language and environment features. Jolt programmers need to be aware of the following:

The following section describes the issues arising from using threads with different Java implementations and is followed by an example of the use of threads in a Jolt program.

Preemptive and Non-preemptive Threads

Most Java implementations provide preemptive threads. However, the current Sun Solaris implementation provides non-preemptive threads. The difference between these two models can lead to very different performance and programming requirements.

Threads of Control

Each concurrently operating task in the Java virtual machine is a thread. Threads exist in various states, the important ones being RUNNING, RUNNABLE, or BLOCKED.

Preemptive Threading

The main performance difference between the two threading models arises in telling a running thread to relinquish control of the Java VM. In a preemptive threading environment, the usual procedure is to set a hardware timer that goes off periodically; when the timer goes off, the current thread is moved from the RUNNING to the RUNNABLE state, and another thread is chosen to run.

Non-preemptive Threading

In a non-preemptive threading environment, a thread must volunteer to give up control of the CPU and move to the RUNNABLE state. Many of the methods in the Java language classes contain code that volunteers to give up control, and are typically associated with actions that might take a long time. For instance, reading from the network will generally cause a thread to wait for a packet to arrive. A thread that is waiting on the availability of some event or resource is in the BLOCKED state. When the event occurs or the resource becomes available, the thread becomes RUNNABLE.

Using Jolt with Non-Preemptive Threading

If your Jolt-based Java program is running on a non-preemptive threading Virtual Machine (e.g., Sun Solaris), then the program must either:

The typical usage is to make the following call in all long running code segments or potentially time-consuming loops:

Thread.currentThread.yield();

Without sending this message, the threads used by the Jolt library may never get scheduled, and as such, the Jolt operation will be impaired.

The only virtual machine known to use non-preemptive threading is the Java Developer's Kit (JDK version 1.0, 1.0.1, 1.0.2) machine running on a Sun platform. If you want your applet to work on JDK 1.0, you must make sure to send the yield messages. As mentioned earlier, some methods contain yields. An important exception is the System.in.read method. This method does not cause a thread switch. Rather than rely on these messages, we suggest using yields explicitly.

Note: Sun has indicated that JDK 1.1 will implement preemptive threads, and should alleviate the requirement for yields. Code that includes yields will continue to work; code without yields will begin working with the JDK 1.1 release.

Using Threads for Asynchronous Behavior

You can use threads in Jolt to get asynchronous behavior that is analogous to the tpacall() function in TUXEDO. With this capability, you do not need a asynchronous service request function. You can get this functionality because Jolt is thread safe. For example the client Jolt application can start one thread that sends a request to a TUXEDO service function and then immediately starts another thread that sends another request to a TUXEDO service function. So even though the Jolt tpacall() is synchronous, the application is asynchronous because the two threads are running at the same time.

Using Threads with Jolt

A Jolt client-side program or applet is fully thread-safe. Jolt's support of multi-threaded applications includes the following client characteristics:

The following program illustrates the use of two threads in a Jolt application.

Listing 6-10 Using Multithreads with Jolt (ThreadBank.java)
/* Copyright 1996 BEA Systems, Inc.  All Rights Reserved */
import bea.jolt.*;
public class ThreadBank
{
public static void main (String [] args)
{
JoltSession session;
try
{
JoltSessionAttributes dattr;
String userName = null;
String userPasswd = null;
String appPasswd = null;
String userRole = null;
         // fill in attributes required
dattr = new JoltSessionAttributes();
dattr.setString(dattr.APPADDRESS,"//bluefish:8501");
         // instantiate domain
// check authentication level
switch (dattr.checkAuthenticationLevel())
{
         case JoltSessionAttributes.NOAUTH:
System.out.println("NOAUTH\n");
break;
case JoltSessionAttributes.APPASSWORD:
appPasswd = "myAppPasswd";
break;
case JoltSessionAttributes.USRPASSWORD:
userName = "myName";
userPasswd = "mySecret";
appPasswd = "myAppPasswd";
break;
}
dattr.setInt(dattr.IDLETIMEOUT, 60);
session = new JoltSession (dattr, userName, userRole,
userPasswd, appPasswd);
T1 t1 = new T1 (session);
T2 t2 = new T2 (session);
         t1.start();
t2.start();
         Thread.currentThread().yield();
try
{
while (t1.isAlive() && t2.isAlive())
{
Thread.currentThread().sleep(1000);

}
}
catch (InterruptedException e)
{
System.err.println(e);
if (t2.isAlive())
{
System.out.println("job 2 is still alive");
try
{
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e1)
{
System.err.println(e1);
}
}
else if (t1.isAlive())
{ System.out.println("job1 is still alive");
try
{
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e1)
{
System.err.println(e1);
}
}
}
session.endSession();
}
catch (SessionException e)
{
System.err.println(e);
}
finally
{
System.out.println("normal ThreadBank term");
}
}
}

class T1 extends Thread
{
JoltSession j_session;
JoltRemoteService j_withdrawal;
   public T1 (JoltSession session)
{
j_session=session;
j_withdrawal= new JoltRemoteService("WITHDRAWAL",j_session);
}
public void run()
{
j_withdrawal.addInt("ACCOUNT_ID",10001);
j_withdrawal.addString("SAMOUNT","100.00");
try
{
System.out.println("Initiating Withdrawal from account 10001");
j_withdrawal.call(null);
String W = j_withdrawal.getStringDef("SBALANCE","-1.0");
System.out.println("-->Withdrawal Balance: " + W);
}
catch (ApplicationException e)
{
e.printStackTrace();
System.err.println(e);
}
}
}
class T2 extends Thread
{
JoltSession j_session;
JoltRemoteService j_deposit;
   public T2 (JoltSession session)
{
j_session=session;
j_deposit= new JoltRemoteService("DEPOSIT",j_session);
}
public void run()
{
j_deposit.addInt("ACCOUNT_ID",10000);
j_deposit.addString("SAMOUNT","100.00");
try
{
System.out.println("Initiating Deposit from account 10000");
j_deposit.call(null);
String D = j_deposit.getStringDef("SBALANCE","-1.0");
System.out.println("-->Deposit Balance: " + D);
}
catch (ApplicationException e)
{
e.printStackTrace();
System.err.println(e);
}
}
}


Event Subscription and Notifications

Programmers developing client applications using Jolt can receive event notifications from either TUXEDO Services or other TUXEDO clients. The Jolt Class Library contains classes that support the following types of TUXEDO notifications for handling event-based communication:

API for Event Subscription

The Jolt Class Library provides four classes that implement the asynchronous notification mechanism for Jolt client applications. These classes are:

For more information about these classes refer to Chapter 7, "Jolt Class Library Reference."

Notification Event Handler

For both unsolicited notifications and a brokered event notification, the Jolt client application requires an event handler routine that is invoked upon receipt of a notification. The Jolt 1.1 release only supports a single handler per session. In current TUXEDO versions, it is not possible to determine which event generated a notification. Thus it is not possible to invoke an event-specific handler based on a particular event.

The client application must provide a single handler (by overriding the onReply() method) per session that will be invoked for all notifications received by that client for that session. The single handler call-back function is used for both unsolicited and event notification types. It is up to the (user supplied) handler routine to determine what event caused the handler invocation and take appropriate action. If the user does not override the session handler, then notification messages are silently discarded by the default handler.

The Jolt client provides the call back function by subclassing the JoltSession class and overriding the onReply() method with a user-defined onReply() method.

In TUXEDO/ATMI clients, processing in the handler call-back function is limited to a subset of ATMI calls. This restriction does not apply to Jolt clients. Separate threads are used to monitor notifications and run the event handler method. A Jolt client will be able to perform all Jolt-supported functionality from within the handler. All the rules that apply to a normal Jolt client program apply to the handler, such as a single transaction per session at any time.

Each invocation of the handler method takes place in a separate thread. The application developer should ensure that the onReply() method is either synchronized or written thread-safe, since separate threads could be executing the method simultaneously.

Subscribing to Event Notifications Enables Unsolicited Notifications

Jolt uses an implicit model for enabling the handler routing. When a client subscribes to an event, Jolt will internally enables the handler for that client, thus enabling unsolicited notifications as well. A Jolt client cannot subscribe to event notifications without also receiving unsolicited notifications. In addition, a single onReply() method is invoked for both types of notifications.

Connection Modes

Jolt supports notification receipt for clients working in either connection-retained or connection-less modes of operation. Connection-retained clients receive all notifications. Jolt clients working in connection-less mode will receive notifications while they have an active network connection to the Jolt Session Handler (JSH). When the network connection is closed, the JSH logs and drops notifications destined for the client. Jolt clients operating in a connection-less mode will not receive unsolicited messages or notifications while they do not have an active network connection. All messages received during this time are logged and discarded by the JSH.

Acknowledged Notifications

Connection mode notification handling includes acknowledged notifications for Jolt 1.1 clients in a TUXEDO 6.3 environment. If a JSH receives an acknowledged notification for a client and the client does not have an active network connection, the JSH logs an error and return a failure acknowledgment to the notification.

Notification Data Buffers

When a client receives notification, it is accompanied by a data buffer. The data buffer can be of any TUXEDO data buffer type. Jolt clients (i.e., the handler) will receive these buffers as a JoltMessage object and should use the appropriate JoltMessage class get*() methods to retrieve the data from this object.

The Jolt Repository does not need to have the definition of the buffers used for notification. However, the Jolt client application programmer will need to know field names beforehand.

The Jolt system does not provide functionality equivalent to tptypes() in TUXEDO, so in effect a Jolt 1.1 client is limited to receiving a "known" buffer type. For FML and VIEW buffers, the data will be accessed using the get*() methods with the appropriate field name, for example, enter:

getIntDef ("ACCOUNT_ID", -1);

For STRING and CARRAY buffers, the data will be accessed by the same name as the buffer type, e.g.,:

getStringDef ("STRING", null);
getBytesDef ("CARRAY", null);

STRING and CARRAY buffers contain only a single data element: this complete element is returned in the get*() methods above.

TUXEDO Event Subscription

TUXEDO brokered event notification allows TUXEDO programs to post events without needing to know what other programs are supposed to receive notification of an event's occurrence. The Jolt event notification allows Jolt client applications to subscribe to TUXEDO events that are broadcast or posted using the TUXEDO tpnotify() or tpbroadcast() calls.

Jolt clients are only able to subscribe to events and notifications that are generated by other components in TUXEDO (such as a TUXEDO Service or Client). Jolt 1.1 clients are not able to send events or notifications.

Supported Subscription Types

Jolt1.1 only supports notification types of subscriptions. The Jolt onReply() method is called when a subscription is fulfilled. The Jolt 1.1 API does not support dispatching a service routine or enqueueing a message to an application queue when a notification is received.

Subscribing to Notifications

If a Jolt client subscribes to a single event notifications, the client receives both unsolicited messages and event notification. Subscribing to an event implicitly enables unsolicited notification. This means that if the application creates a JoltUserEvent object for Event "X", the client will automatically receive notifications directed to it as a result of tpnotify() or tpbroadcast().

Note: This is NOT the recommended method for enabling unsolicited notification - if you want unsolicited notification, the application should explicitly do so (as described in the JoltUserEvent class). The reason for this is explained in the following unsubscribe section.

Unsubscribing from Notifications

To stop subscribing to event notifications and/or unsolicited messages, you need to use the JoltUserEvent unsubscribe method. In Jolt, disabling unsolicited notifications with an unsubscribe method does not turn off all subscription notifications. This differs from TUXEDO. In TUXEDO the use of tpsetunsol() with a NULL handler turns off all subscription notifications.

When unsubscribing, the following considerations apply:

If you want to stop unsolicited messages in your client application, you need to make sure that you have unsubscribed to all events.

Note: Jolt 1.1 does not support the wildcard unsubscribe semantics of tpunsubscribe (-1,..). Jolt clients wishing to unsubscribe to all subscriptions will do so by invoking the unsubscribe() method in each event subscription object.

Using the Jolt API to Receive TUXEDO Notifications

The example code provided in Listing 6-11 shows how to use the Jolt Class Library for receiving notifications and includes the use of the JoltSession, JoltReply, JoltMessage and JoltUserEvent classes.

Listing 6-11 Asynchronous Notification
class EventSession extends JoltSession
{
public EventSession( JoltSessionAttributes attr, String user,
String role, String upass, String apass )
{
super(attr, user, role, upass, apass);
}
/**
* Override the default unsolicited message handler.
* @param reply a place holder for the unsolicited message
* @see bea.jolt.JoltReply
*/
public void onReply( JoltReply reply )
{
// Print out the STRING buffer type message which contains
// only one field; the field name must be "STRING". If the
// message uses CARRAY buffer type, the field name must be
// "CARRAY". Otherwise, the field names must conform to the
// elements in FML or VIEW.
        JoltMessage msg = (JoltMessage) reply.getMessage();
System.out.println(msg.getStringDef("STRING", "No Msg"));
}
public static void main( Strings args[] )
{
JoltUserEvent unsolEvent;
JoltUserEvent helloEvent;
EventSession session;
...
        // Instantiate my session object which can print out the
// unsolicited messages. Then subscribe to HELLO event
// and Unsolicited Notification which both use STRING
// buffer type for the unsolicited messages.
        session = new EventSession(...);

helloEvent = new JoltUserEvent("HELLO", null, session);
unsolEvent = new JoltUserEvent(JoltUserEvent.UNSOLMSG, null,
session);
...
// Unsubscribe the HELLO event and unsolicited notification.
helloEvent.unsubscribe();
unsolEvent.unsubscribe();
}
}


Clearing Parameter Values

The Jolt Class Library includes a method (the clear method) that allows the developer to remove an object's existing attributes and in effect provides for the reuse of the object. The reuseSample.java example illustrates how to use the clear method for clearing parameter values.

The reuseSample.java example shows how to reuse the JoltRemoteService parameter values. The example shows that you do not have to destroy the service to reuse it. Instead, the svc.clear(); statement is used to discard the existing input parameters before reusing the addString method.

Listing 6-12 Jolt Object Reuse (reuseSample.java)
/* Copyright 1996 BEA Systems, Inc. All Rights Reserved */
import java.net.*;
import java.io.*;
import bea.jolt.*;
/*
* This is a Jolt sample program that illustrates how to reuse the
* JoltRemoteService after each invocation.
*/
class reuseSample
{
private static JoltSession s_session;
static void init( String host, short port )
{
/* Prepare to connect to the TUXEDO domain. */
JoltSessionAttributes attr = new JoltSessionAttributes();
attr.setString(attr.APPADDRESS,"//"+ host+":" + port);
        String username = null;
String userrole = "sw-developer";
String applpasswd = null;
String userpasswd = null;
        /* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = "secret8";
break;
case JoltSessionAttributes.USRPASSWORD:
username = "myName";
userpasswd = "BEA#1";
applpasswd = "secret8";
break;
}
        /* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
}
    public static void main( String args[] )
{
String host;
short port;
JoltRemoteService svc;
        if (args.length != 2)
{
System.err.println("Usage: reuseSample host port");
System.exit(1);
}
        /* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
        init(host, port);
        /* Get the object reference to the DELREC service.  This
* service has no output parameters, but has only one input
* parameter.
*/
svc = new JoltRemoteService("DELREC", s_session);
try
{
/* Set input parameter REPNAME. */
svc.addString("REPNAME", "Record1");
svc.call(null);
/* Change the input parameter before reusing it */
svc.setString("REPNAME", "Record2");
svc.call(null);
            /* Simply discard all input parameters */
svc.clear();
svc.addString("REPNAME", "Record3");
svc.call(null);
}
catch (ApplicationException e)
{
System.err.println("Service DELREC failed: "+
e.getMessage()+" "+ svc.getStringDef("MESSAGE", null));
}
        /* Logoff now and get rid of the object. */
s_session.endSession();
}
}


Reusing Objects

The following extendSample.java example illustrates one way to subclass the JoltRemoteService class. In this case, a TransferService class is created by subclassing the JoltRemoteService class. The TransferService class extends the JoltRemoteService class, adding a Transfer feature which makes use of the TUXEDO bankapp funds TRANSFER service.

The example uses the "extends" mechanism from the Java language. The extend is used in Java to subclass a base (parent) class. The following code shows only one of many different ways to extend from JoltRemoteService.

Listing 6-13 Extending Jolt Remote Service (extendSample.java)
/* Copyright 1996 BEA Systems, Inc. All Rights Reserved */
import java.net.*;
import java.io.*;
import bea.jolt.*;
/*
* This Jolt sample code fragment illustrates how to customize
* JoltRemoteService. It uses the Java language "extends" mechanism
*/
class TransferService extends JoltRemoteService
{
public String fromBal;
public String toBal;
    public TransferService( JoltSession session )
{
super("TRANSFER", session);
}
    public String doxfer( int fromAcctNum, int toAcctNum, String amount )
{
/* Clear any previous input parameters */
this.clear();
        /* Set the input parameters */
this.setIntItem("ACCOUNT_ID", 0, fromAcctNum);
this.setIntItem("ACCOUNT_ID", 1, toAcctNum);
this.setString("SAMOUNT", amount );
        try
{
/* Invoke the transfer service. */
this.call(null);
            /* Get the output parameters */
fromBal = this.getStringItemDef("SBALANCE", 0, null);
if (fromBal == null)
return "No balance from Account " +
fromAcctNum;
toBal = this.getStringItemDef("SBALANCE", 1, null);
if (toBal == null)
return "No balance from Account " + toAcctNum;
return null;
}
catch (ApplicationException e)
{
/* The transaction failed, return the reason */
return this.getStringDef("STATLIN", "Unknown reason");
}
}
}
class extendSample
{
public static void main( String args[] )
{
JoltSession s_session;
String host;
short port;
TransferService xfer;
String failure;
        if (args.length != 2)
{
System.err.println("Usage: reuseSample host port");
System.exit(1);
}
        /* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
        /* Prepare to connect to the TUXEDO domain.  */
JoltSessionAttributes attr = new JoltSessionAttributes();
attr.setString(attr.APPADDRESS,"//"+ host+":" + port);
        String username = null;
String userrole = "sw-developer";
String applpasswd = null;
String userpasswd = null;
        /* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = "secret8";
break;
case JoltSessionAttributes.USRPASSWORD:
username = "myName";
userpasswd = "BEA#1";
applpasswd = "secret8";
break;
}
        /* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
        /*
* TransferService extends from JoltRemoteService and uses the
* standard TUXEDO BankApp TRANSFER service. We invoke this
* service twice with different parameters. Note, we assume
* that "s_session" is initialized somewhere before.
*/
        xfer = new TransferService(s_session);
if ((failure = xfer.doxfer(10000, 10001, "500.00")) != null)
System.err.println("Tranasaction failed: " + failure);
else
{
System.out.println("Transaction is done.");
System.out.println("From Acct Balance: "+xfer.fromBal);
System.out.println(" To Acct Balance: "+xfer.toBal);
}
        if ((failure = xfer.doxfer(51334, 40343, "$123.25")) != null)
System.err.println("Tranasaction failed: " + failure);
else
{
System.out.println("Transaction is done.");
System.out.println("From Acct Balance: "+xfer.fromBal);
System.out.println(" To Acct Balance: "+xfer.toBal);
}
    } 
}


Application Deployment and Localization

The Jolt Class Library allows you to build Java applications that execute from within a client Web browser. For these types of applications, you need to address the following application development tasks:

The following sections describe these application development considerations.

Deploying a Jolt Applet

When you deploy a Jolt applet, you need to consider the three components that operate together to make the applet function in a Web browser environment:

Information for configuring the TUXEDO server and Jolt Server to work with Jolt is available in Chapter 2, "`Installing Jolt." The following sections describe common client and Web server considerations for deploying Jolt applets.

Client Considerations

When you write a Java applet that incorporates Jolt classes, the applet works just as any other Java applet in an HTML page. A Jolt applet can be embedded in a HTML page using the HTML applet tag:

<applet code="applet_name.class"> </applet>

If the Jolt applet is embedded in an HTML page, the applet downloads when the HTML page loads. You can code the applet to run immediately after it is downloaded, or you can include code that sets the applet to run based upon a user action, a timeout, or a set interval. You can also create an applet that downloads in the HTML page, but opens in another window or, for instance, simply plays a series of sounds or musical tunes at intervals. The programmer has a large degree of freedom in coding the applet initialization procedure.

Note: If the user loads a new HTML page into the browser, the applet execution is stopped.

Web Server Considerations

When you use the Jolt classes in a Java applet, the Jolt Server must run on the same machine as the Web server that downloads the Java applet unless you install Jolt Relay on the Web server.

When a webmaster sets up a Web server, a directory is specified to store all the HTML files. Within that directory, a subdirectory named "classes" must be created to contain all Java class files and packages. For example:

<html-dir>/classes/bea/jolt

Note: You can place the Jolt classes subdirectory anywhere. For convenient access, you may want to place it in the same directory as the HTML files. The only requirements for the Jolt classes subdirectory are that they must be made available to the Web server.

Since all Jolt classes belong to package bea.jolt, all Jolt class files are put in /classes/bea/jolt subdirectory (i.e., "jolt" is a subdirectory of "bea" which is a subdirectory of "classes").

The HTML file for the Jolt applet should refer the codebase to the "classes" directory. For example:

    /export/html/
|___ classes/
| |_____ bea/
| | |______ jolt/
| | |_____ JoltSessionAttributes.class
| | |_____ JoltRemoteServices.class
| | |_____ ...
| |_____ mycompany/
| |________ app.class
|___ ex1.html
|___ ex2.html

The webmaster may specify the "app" applet in ex1.html as:

<applet codebase="classes" code=mycompany.app.class width=400 height=200>

Localizing a Jolt Applet

If your Jolt application is intended for international use, you must address certain application localization issues. Localization considerations apply to applications that execute from a client Web browser and applications that are designed to run outside a Web browser environment. Localization tasks can be divided into two categories:

For localization, the Jolt Class Library package relies on the conventions of the Java language and the TUXEDO system. Jolt transfers Java 16-bit Unicode characters to the JSH. The JSH provides a mechanism to convert Unicode to the local character set.

For information about the Java implementation for Unicode and character escapes, refer to your Java Development Kit (JDK) documentation.