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.
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 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:
Class Library Functionality Overview
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
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.
The Jolt Class Library has the following characteristics:
Jolt Class Library Features
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.
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.
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.
The following tasks summarize the interaction shown in Table 6-1 and are the steps involved in beginning a transaction:
Jolt Class Library Error and Exception Handling
Jolt Client/Server Relationship
Figure 6-1 Jolt Client/Server Relationship
JoltSessionAttributes
class.
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.
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 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.
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.
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.
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:
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.
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:
Transaction Begin, Commit, and Rollback
trans = new JoltTransaction(timeout, session)
Jolt Class Library Walk-through
sattr = new JoltSessionAttributes();
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())
This example does not explicitly catch session = new JoltSession (sattr, userName, userRole,
userPassword, appPassword);SessionException
errors.
JoltSession()
. Refer to the following lines in code Listing 6-1:
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.
withdrawal = new JoltRemoteService("WITHDRAWAL", session);
deposit = new JoltRemoteService("DEPOSIT", session);
The withdrawal.addInt("ACCOUNT_ID", 100000);
withdrawal.addString("SAMOUNT", "100.00");
add*()
methods can throw IllegalAccessError
or NoSuchFieldError
exceptions.
Listing 6-1:
trans = new JoltTransaction(5,session);
withdrawal.call(trans);
trans.rollback();
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
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.
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.
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.
Figure 6-3 Add a TOUPPER Service
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
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.
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:
Figure 6-6 Edit ECHO Service
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());
}
}
}
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.
The tryOnFml.java Client Code
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);
}
}
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
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.
Figure 6-7 illustrates the Jolt Repository Edit Services window with the PASSFML service.
Figure 6-7 Edit the PASSFML Service
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);
}
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:
simpview.java
Jolt client that contains the code used to connect to TUXEDO and uses the VIEW buffer type
simpview.v16
file that contains the TUXEDO VIEW field definitions
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.
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 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.java Client Code
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.)
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);
}
}
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
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:
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);
}
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:
tpacall()
function in TUXEDO.
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.
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.
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 and Non-preemptive Threads
Threads of Control
Note:
The Java VM schedules threads of the same priority to run in a round-robin mode.
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.
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.
If your Jolt-based Java program is running on a non-preemptive threading Virtual Machine (e.g., Sun Solaris), then the program must either:
Preemptive Threading
Non-preemptive Threading
Using Jolt with Non-Preemptive Threading
Thread.yield()
method
The typical usage is to make the following call in all long running code segments or potentially time-consuming loops:
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
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.
You can use threads in Jolt to get asynchronous behavior that is analogous to the A Jolt client-side program or applet is fully thread-safe. Jolt's support of multi-threaded applications includes the following client characteristics:
Thread.currentThread.yield();
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
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
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);
}
}
}
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:
The Jolt Class Library provides four classes that implement the asynchronous notification mechanism for Jolt client applications. These classes are:
API for Event Subscription
For more information about these classes refer to Chapter 7, "Jolt Class Library Reference."
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 The Jolt client provides the call back function by subclassing the JoltSession class and overriding the 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 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 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.
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.
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 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 For STRING and CARRAY buffers, the data will be accessed by the same name as the buffer type, e.g.,:
STRING and CARRAY buffers contain only a single data element: this complete element is returned in the 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 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.
Jolt1.1 only supports notification types of subscriptions. The Jolt 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
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.
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 When unsubscribing, the following considerations apply:
Notification Event Handler
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.
onReply
() method with a user-defined onReply
() method.
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
onReply
() method is invoked for both types of notifications.
Connection Modes
Acknowledged Notifications
Notification Data Buffers
JoltMessage
object and should use the appropriate JoltMessage
class get*()
methods to retrieve the data from this object.
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);
getStringDef ("STRING", null);
getBytesDef ("CARRAY", null);get*()
methods above.
TUXEDO Event Subscription
tpnotify()
or tpbroadcast()
calls.
Supported Subscription Types
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
tpnotify()
or tpbroadcast()
.
Unsubscribing from Notifications
tpsetunsol()
with a NULL handler turns off all subscription notifications.
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 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.
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
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();
}
}
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();
}
}
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;
Stringhost;
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);
}
}
}
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.
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:
Deploying a Jolt Applet
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.
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:
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.
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:
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 The HTML file for the Jolt applet should refer the codebase to the "classes" directory. For example:
The webmaster may specify the "app" applet in ex1.html as:
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:
Client Considerations
<applet code="applet_name.class"> </applet>
Web Server Considerations
<html-dir>/classes/bea/jolt
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").
/export/html/
|___ classes/
| |_____ bea/
| | |______ jolt/
| | |_____ JoltSessionAttributes.class
| | |_____ JoltRemoteServices.class
| | |_____ ...
| |_____ mycompany/
| |________ app.class
|___ ex1.html
|___ ex2.html<applet codebase="classes" code=mycompany.app.class width=400 height=200>
Localizing a Jolt Applet
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.