BEA Logo BEA Jolt Release 1.2

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   Jolt Doc Home   |   Jolt Developer's Guide   |   Previous Topic   |   Next Topic   |   Contents   |   Index

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. Using these classes, you can extend applications for Internet and intranet transaction processing. You can use the Jolt Class Library to customize access to BEA Tuxedo services from Java applets.

"Usingthe Jolt Class Library" covers the following topics:

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 the programming examples are in Java code.

Note: All 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 run as independent Java applications or in a Java-enabled Web browser. 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 4-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 (for example, 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 work around 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:

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. The BEA Jolt 1.2 Online API Javadoc 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 4-1 illustrates the client/server relationship between a Jolt program and the Jolt Server.

Figure 4-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 4-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 onto 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, which summarize the interaction shown in Table 4-1,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 next section describes the Jolt Class Library classes in more detail.

Jolt Object Relationships

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

Figure 4-2 Jolt Object Relationships

As objects, the Jolt classes interact in various relationships with each other. In the previous figure, 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. You must provide a service name and a JoltSession object to instantiate a JoltRemoteService object before it can be used.

To use a JoltRemoteService object, simply:

For efficiency, Jolt does not make a copy of any input parameter object; only the references to the object (for example, 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, you can invoke multiple JoltRemoteService objects simultaneously by using the Java multithreading capability. Refer to "Multithreaded Applications" in this chapter for additional 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 4-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 this line in the following code listing:

    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 this line in the following code listing:

    switch (sattr.checkAuthenticationLevel())

  3. The logon is accomplished by instantiating a JoltSession object.

    Refer to these lines in the following code listing:

    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 these lines in the following code listing:

    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 these lines in the following code listing:

    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 this line in the following code listing:

    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 this line in the following code listing:

    withdrawal.call(trans);

  8. A failed WITHDRAWAL can be rolled back.

    Refer to this line in the following code listing:

    trans.rollback();

  9. Otherwise, once the DEPOSIT is performed, all the transactions are committed. Refer to these lines in the following code listing:

    deposit.call(trans);

    trans.commit();

The following listing shows an example of a simple application for the transfer of funds using the Jolt classes.

Listing 4-1 Jolt Transfer of Funds Example (SimXfer.java)


/* Copyright 1999 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 the following built-in Tuxedo buffer types:

For information about all 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, (for example, 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 (for example, 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 4-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 the next listing, 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 "Using the Jolt Repository Editor" for more information about defining your services and adding new parameters.

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

    Figure 4-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 the following figure.)

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

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

ToUpper.java Client Code

The ToUpper.java Java code fragment in the following listing 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 4-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.

Note: X_OCTET is used identically to CARRAY.

Define ECHO in the Repository Editor

Before running the example in the "Add a TOUPPER Service" figure, you must write and boot an ECHO Tuxedo service. The ECHO service takes a buffer and passes it back to the Jolt client. You also need to use the Jolt Repository Editor to define the ECHO service.

Figure 4-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 4-6 Edit ECHO Service

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

    Note: If using the X_OCTET buffer type, you must change the Input Buffer Type and Output Buffer Type fields to X_OCTET.

tryOnCARRAY.java Client Code

The code in the following listing 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 4-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 (for example, 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 buffer type. 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 the following listing illustrates how Jolt works with a service whose buffer type is FML. The following example assumes that a session object was already instantiated.

Listing 4-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 entries in the following listing, tryOnFml.f16, show FML field definitions for the tryOnFml.java example.

Listing 4-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

The"Using the STRING Buffer Type" figure 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, 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 "Using the Jolt Repository Editor" 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.

    The following figure 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.

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

    Figure 4-7 Edit the PASSFML Service

    Figure 4-8 Edit the PASSFML Parameters

tryOnFml.c Server Code

The following listing illustrates the server side code for using the FML buffer type. The PASSFML service reads in an input FML buffer and outputs a FML buffer.

Listing 4-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 that is read at run time.

When allocating a VIEW, your application specifies a VIEW buffer type and a subtype that matches the name of the view (the name that appears in the view description file). The parameter name must match the field name in that view. 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 handle such things as 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

The following listing 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 (JVM) 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 the following listing, 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 has already been instantiated.

Listing 4-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 4-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 "Using the Jolt Repository Editor" for more information about defining a service.

Figure 4-9 Add SIMPVIEW Service

In the Repository Editor add the VIEW service as follows:

  1. Add a SIMPVIEW service for the SIMPSERV package.

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

    Figure 4-10 Edit SIMPVIEW Service

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

    Note: If using the X_COMMON or X_C_TYPE buffer types, you must put the correct buffer type in the Input Buffer Type and Output Buffer Type fields. Additionally, you must choose the corresponding Input View Name and Output View Name fields.

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 4-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.

Note: Most Java implementations provide preemptive rather than 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 example, 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 (such as Sun Solaris), 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 is 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.

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 an asynchronous service request function. You can get this functionality because Jolt is thread-safe. For example, the Jolt client application can start one thread that sends a request to a Tuxedo service function and then immediately start 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 support of multithreaded applications includes the following client characteristics:

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

Listing 4-10 Using Multiple Threads 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 with 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:

For additional information about these classes refer to the "API Reference in Javadoc."

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.Jolt only supports a single handler per session. In Tuxedo versions, you cannot determine which event generated a notification. Therefore, you cannot 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 can 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.

Jolt uses an implicit model for enabling the handler routine. When a client subscribes to an event, Jolt 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 receipts 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 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 do 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.

Connection mode notification handling includes acknowledged notifications for Jolt clients in the Tuxedo 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 returns 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 (for example, 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 needs to know field names.

The Jolt system does not provide functionality equivalent to tptypes() in Tuxedo. For FML and VIEW buffers, the data is accessed using the get*() methods with the appropriate field name, for example:

getIntDef ("ACCOUNT_ID", -1);

For STRING and CARRAY buffers, the data is accessed by the same name as the buffer type:

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 knowing 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 clients are not able to send events or notifications.

Supported Subscription Types

Jolt only supports notification types of subscriptions. The Jolt onReply() method is called when a subscription is fulfilled. The Jolt 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 notification, 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 automatically receives 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 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.

Using the Jolt API to Receive Tuxedo Notifications

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

Listing 4-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 you to remove existing attributes from an object 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 4-12 Jolt Object Reuse (reuseSample.java)


/* Copyright 1999 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 keyword from the Java language. The extends keyword 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 4-13 Extending Jolt Remote Service (extendSample.java)


/* Copyright 1999 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 Installing the BEA Tuxedo System. 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 an 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 is downloaded 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

Or, you can set the CLASSPATH to include the jolt.jar file that contains all the Jolt classes.

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 requirement for the Jolt classes subdirectory is that the classes must be made available to the Web server.

The HTML file for the Jolt applet should refer the codebase to the jolt.jar file or 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 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.