Table of Contents Previous Next PDF


Using the Jolt Class Library

Using the Jolt Class Library
The Oracle Jolt Class Library provides developers with a set of object-oriented Java language classes for accessing Oracle Tuxedo services. The class library contains the class files that implement the Jolt API. Using these classes, you can extend applications for Internet and intranet transaction processing. You can use the Jolt Class Library to customize access to Oracle Tuxedo services from Java applets.
This topic includes the following sections:
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:
Class Library Functionality Overview
The Jolt Class Library gives the Oracle Tuxedo application developer 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 the listing “Jolt Transfer of Funds Example (SimXfer.java)” on page 5‑11.
Java Applications Versus Java Applets
Java programs that run in a browser are called applets. Applets are small, easily downloaded parts of an overall application that perform specific functions. Many popular browsers impose limitations on the capabilities of Java applets in order to provide a high degree of security for the users of the browser. Applets have the following restrictions:
Programming workarounds exist for most 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 Oracle Tuxedo errors as exceptions. The Jolt Class Library Reference contains the Jolt classes and lists the errors or exceptions thrown for each class. The Oracle Jolt API Reference contains the Error and Exception Class Reference.
Jolt Client/Server Relationship
Oracle Jolt works in a distributed client/server environment and connects Java clients to Oracle Tuxedo-based applications.
Figure 5‑1 illustrates the client/server relationship between a Jolt program and the Jolt Server.
Figure 5‑1 Jolt Client/Server Relationship
.
As illustrated in the figure, the Jolt Server acts as a proxy for a native Oracle Tuxedo client, implementing functionality available through the native Oracle Tuxedo client. The Oracle Jolt Server accepts requests from Oracle Jolt clients and maps those requests into Oracle Tuxedo service requests through the Oracle Tuxedo ATMI interface. Requests and associated parameters are packaged into a message buffer and delivered over the network to the Oracle Jolt Server. The Oracle Jolt Connection Manager handles all communication between the Oracle Jolt Server and the Oracle Jolt applet using the Oracle Jolt Transaction Protocol. The Oracle 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 Oracle Tuxedo as specified by the message.
Once a service request enters the Oracle Tuxedo system, it is executed in exactly the same manner as any other Oracle Tuxedo request. The results are returned through the ATMI interface to the Oracle Jolt Server, which packages the results and any error information into a message that is sent to the Oracle Jolt client applet. The Oracle Jolt client then maps the contents of the message into the various Oracle 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.
Table 5‑1 describes the client-side requests and Jolt Server-side actions in a simple example program.
 
The following tasks summarize the interaction shown in the previous table, “Jolt Client/Server Interaction.”
1.
2.
3.
4.
5.
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. “Jolt Object Relationships” on page 5‑7 describes the Jolt Class Library classes in more detail.
Jolt Object Relationships
Figure 5‑2 illustrates the relationship between the instantiated objects of the Jolt Class Library classes.
Figure 5‑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 relationshipat the class level an object can contain other objects. For example, a JoltTransaction stores (or contains) a JoltSession object.
Is-a relationshipthe 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 relationshipan 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 Library Walkthrough
Use Jolt classes to perform the basic functions of transaction processing: logon/logoff; synchronous service calling; transaction begin, commit, and rollback. The following sections describe how Jolt classes are used to perform these functions.
You can also use the Jolt class library to develop multithreaded applications, define Tuxedo buffer types, and subscribe to events and unsolicited messages. These functions are discussed in later sections.
Logon and Logoff
The client application must log on to the Oracle Tuxedo environment prior to initiating any transaction activity. The Jolt Class Library provides the JoltSessionAttributes class and JoltSession class to establish a connection to an Oracle Tuxedo system.
The JoltSessionAttributes class will contain the connection properties of Jolt and Oracle Tuxedo systems as well as various other properties of the two systems. To establish a connection, the client application must create an instance of the JoltSession class. This instance is the JoltSession object. After the developer instantiates a Jolt Session and Oracle Tuxedo object, the Jolt and Oracle Tuxedo logon capability is enabled. Calling the endSession method ends the session and allows the user to log off.
Synchronous Service Calling
Transaction activities such as requests and replies are handled through a JoltRemoteService object (an instance of the JoltRemoteService class). Each JoltRemoteService object refers to an exported Oracle 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:
1.
2.
3.
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. Because 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.
Because Jolt is designed for a multithreaded environment, you can invoke multiple JoltRemoteService objects simultaneously by using the Java multithreading capability. Refer to “Multithreaded Applications” on page 5‑42 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 timeout 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.
The sample code in the listing “Jolt Transfer of Funds Example (SimXfer.java)” on page 5‑11 describes how to use the Jolt Class Library and includes the use of the JoltSessionAttributes, JoltSession, JoltRemoteService, and JoltTransaction classes.
The same sample combines two user-defined Oracle 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 following programming steps describe the transaction process shown in the sample code listing “Jolt Transfer of Funds Example (SimXfer.java)” on page 5‑11:
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.
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.
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 is thrown. This example does not explicitly catch ServiceException errors.
5.
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.
Refer to this line in the following code listing:
trans = new JoltTransaction(5,session);
7.
Refer to this line in the following code listing:
withdrawal.call(trans);
8.
Refer to this line in the following code listing:
trans.rollback();
9.
deposit.call(trans);
trans.commit();
Listing 5‑1 shows an example of a simple application for the transfer of funds using the Jolt classes.
Listing 5‑1 Jolt Transfer of Funds Example (SimXfer.java)
/* Copyright 1999 Oracle 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 Oracle Tuxedo Buffer Types with Jolt
Jolt supports the following built-in Oracle Tuxedo buffer types:
Note:
Of the Oracle Tuxedo built-in buffer types, the Jolt programmer should be particularly aware of how Jolt handles the CARRAY (character array) and STRING buffer types:
For more information about all the Oracle Tuxedo typed buffers, data types, and buffer types, refer to the following documents:
Using the STRING Buffer Type
The STRING buffer type is an array of non-null characters that terminates with a null character. Unlike CARRAY, you can determine its transmission length by counting the number of characters in the buffer until reaching the null character. Since the STRING buffer is self-describing, the Oracle Tuxedo System can convert data automatically when data is exchanged by machines with different character sets.
Note:
Using the STRING buffer type requires two main steps:
1.
2.
The next two sections provide examples that demonstrate these steps.
The ToUpper code fragment shown in the listing “Use of the STRING Buffer Type (ToUpper.java)” on page 5‑18 illustrates how Jolt works with a service whose buffer type is STRING. The ToUpper Oracle Tuxedo Service is available in the Oracle Tuxedo simpapp example.
Define TOUPPER in the Repository Editor
Before running the ToUpper.java example, you need to define the TOUPPER service through the Jolt Repository Editor.
Note:
Refer to “Using the Jolt Repository Editor” on page 4‑1 for more information about defining your services and adding new parameters.
1.
Figure 5‑3 Add a TOUPPER Service
2.
In the Services window, select the TOUPPER service in the SIMPSERV package.
3.
Click Edit.
Figure 5‑4 Set Input and Output Buffer Types to STRING
4.
5.
6.
Click Save Service.
ToUpper.java Client Code
The ToUpper.java Java code fragment in Listing 5‑2 illustrates how Jolt works with a service with a buffer type of STRING. The example shows a Jolt client using a STRING buffer to pass data to a server. The Oracle 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 5‑2 Use of the STRING Buffer Type (ToUpper.java)
/* Copyright 1996 Oracle 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 Oracle Tuxedo system. Because the system does not interpret the data (although the data type is known) when you use the CARRAY buffer type, you must specify a data length in the Jolt client application. The Jolt client must specify a data length when passing this buffer type.
For example, if an Oracle 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 Oracle Tuxedo service.
To use the CARRAY buffer type, you first define the Tuxedo service that you will be using with the buffer type. Then, write the code that uses the buffer type. The next two sections demonstrate these steps.
Note:
Define the Tuxedo Service in the Repository Editor
Before running the ECHO example, you must write and boot a Tuxedo ECHO service. The ECHO service takes a buffer and passes it back to the Jolt client. You need to define the ECHO service in the Jolt Repository Editor.
Note:
Refer to “Using the Jolt Repository Editor” on page 4‑1 for more information about defining your services and adding new parameters.
 
Figure 5‑5 Repository Editor: Add the ECHO Service
Use the Repository Editor to add the ECHO service as follows:
1.
2.
3.
Note:
Figure 5‑6 Repository Editor: Edit ECHO Service
tryOnCARRAY.java Client Code
The code in the following listing illustrates how Jolt works with a service with a buffer type of CARRAY. Because Jolt does not look into the CARRAY data stream, it is the programmer's responsibility to ensure that the data formats between the Jolt client and the CARRAY service match. The example in Listing 5‑3 assumes that a session object was already instantiated.
Listing 5‑3 CARRAY Buffer Type Example
/* Copyright 1996 Oracle 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 run time determines the field location and data type.
FML is especially suited for use with Jolt clients because the client and server code can be in two languages (for example, Java and C); the client/server platforms can have different data type specifications; or the interface between the client and the server can change 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.
The “tryOnFml.java Code Example” on page 5‑24 is a Jolt client that contains a PASSFML service.
The “tryOnFml.f16 Field Definitions” on page 5‑25 is an Oracle Tuxedo FML field definitions table used by the PASSFML service.
The “tryOnFml.c Code Example” on page 5‑27 is a server code fragment that contains the server side C code for handling the data sent by the Jolt client.
tryOnFml.java Client Code
The tryOnFml.java Java code fragment in Listing 5‑4 illustrates how Jolt works with a service whose buffer type is FML. In this example, it is assumed that a session object was already instantiated.
Listing 5‑4 tryOnFml.java Code Example
/* Copyright 1997 Oracle 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 Field Definitions,” show the FML field definitions for the previous listing, “tryOnFml.java Code Example.”
Listing 5‑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 BULKPKG package contains the PASSFML service, which 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:
Refer to “Using the Jolt Repository Editor” on page 4‑1 for more information about defining a service.
1.
The figure “Repository Editor Window: Edit Services (PASSFML)” on page 5‑26 illustrates the PASSFML service, and Input Buffer and Output Buffer of FML.
Figure 5‑7 Repository Editor Window: Edit Services (PASSFML)
2.
3.
Click Edit to display the Edit Parameters window as shown in Figure 5‑8.
Figure 5‑8 Edit the PASSFML Parameters
4.
5.
tryOnFml.c Server Code
Listing 5‑6 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 5‑6 tryOnFml.c Code Example
/*
* tryOnFml.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the PASSFML Oracle 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 Oracle Tuxedo typed buffer. The VIEW buffer provides a way to use C structures and COBOL records with the Oracle Tuxedo system. The VIEW typed buffer enables the Oracle 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. Because the Oracle 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 “simpview.java Code Example” on page 5‑33 is the Jolt client that contains the code used to connect to Oracle Tuxedo and uses the VIEW buffer type.
The listing “simpview.v16 Field Definitions” on page 5‑34 contains the Oracle Tuxedo VIEW field definitions.
The “simpview.c Code Example” on page 5‑34 contains the server side C code for handling the input from the Jolt client.
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.
Define VIEW in the Repository Editor
Before running the simpview.java and simpview.c examples, you need to define the SIMPVIEW service through the Jolt Repository Editor.
Note:
Refer to “Using the Jolt Repository Editor” on page 4‑1 for more information about defining a service.
Figure 5‑9 Repository Editor: Add SIMPVIEW Service
In the Repository Editor add the VIEW service as follows:
1.
2.
Figure 5‑10 Repository Editor: Edit SIMPVIEW Service
3.
Note:
simpview.java Client Code
The listing “simpview.java Code Example” on page 5‑33 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. Because all Jolt exceptions are derived from java.lang.RunTimeException, the Java Virtual Machine (JVM) catches these exceptions if the application does not. (A well-written application will 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 Oracle 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 5‑7 simpview.java Code Example
/* Copyright 1997 Oracle 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 Oracle Tuxedo service "SIMPVIEW"
ViewSvc = new JoltRemoteService("SIMPVIEW",session);
// Set the input parameters 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 “simpview.v16 Field Definitions” listing shows the Oracle Tuxedo VIEW field definitions for the simpview.java example that were shown in the previous listing.
Listing 5‑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
 
simpview.c Server Code
In Listing 5‑9, the input and output buffers are VIEW. The code accepts the VIEW buffer data as input and outputs the same data as VIEW.
Listing 5‑9 simpview.c Code Example
/*
* SIMPVIEW.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the SIMPVIEW Oracle 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);
}
Using the XML Buffer Type
The XML buffer type enables Oracle Tuxedo applications to use XML documents for exchanging data within and between applications. Oracle Tuxedo applications can send and receive XML buffers, and route those buffers to the appropriate servers. All logic for dealing with XML documents, including parsing, resides in the application.
A well-formed XML document consists of:
To use the XML buffer type, you first define the Tuxedo service that you will be using with the buffer type, and then write the code that uses the buffer type. The next two sections demonstrate these steps.
Note:
Define the Tuxedo Service in the Repository Editor
Before running the XML example, you must write and boot a Tuxedo XML service. The XML service takes a buffer and passes it back to the Jolt client. You need to define the XML service in the Jolt Repository Editor.
Note:
Refer to “Using the Jolt Repository Editor” on page 4‑1 for more information about defining your services and adding new parameters.
Figure 5‑11 Repository Editor: Add the XML Service
Use the Repository Editor to add the XML service as follows:
1.
2.
3.
Define the ECHO_XML service with only one parameter named XML, which is both an input and output parameter.
Figure 5‑12 Repository Editor: Edit the XML Service
simpxml.java Client Code
The code in the following listing illustrates how Jolt works with a service with an XML type buffer. Because Jolt does not look into the XML data stream, it is the programmer's responsibility to ensure that the data formats between the Jolt client and the XML service match. The example in Listing 5‑10 assumes that a session object was already instantiated.
Listing 5‑10 XML Buffer Type Example
/* Copyright 2001 Oracle Systems, Inc. All Rights Reserved */
/*
* This code fragment illustrates how Jolt works with a service whose buffer
* type is XML.
*/
import java.io.*;
import java.lang.*;
import bea.jolt.*;
public class xmldoc {
public static void main (String[] args) {
JoltSessionAttributes sattr;
JoltSession session;
JoltRemoteService echo_xml;
String inString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ORDER><HEADER DATE=\"05/13/1999\" ORDERNO=\"22345\"/><COMPANY>ACME</COMPANY><LINE><ITEM MODEL=\"Pabc\" QUANTITY=\"5\">LAPTOP</ITEM></LINE><LINE><ITEM MODEL=\"P500\" QUANTITY=\"15\">LAPTOP</ITEM></LINE></ORDER>";
byte data[];
DataInputStream din;
DataOutputStream dout;
ByteArrayInputStream bin;
ByteArrayOutputStream bout;
byte odata[];
String outString = null;
String appAddress = null;
//...Create Jolt Session
try {
/*
* Use java.io.DataOutputStream to put data
* into a byte array
*/
bout = new ByteArrayOutputStream(inString.length());
dout = new DataOutputStream(bout);
dout.writeBytes(inString);
/*
* Copy the byte array into a new byte array "data".
* Then issue the Jolt remote service call.
*/
data = bout.toByteArray();
} catch (Exception e) {
System.out.println("toByteArray error");
return;
}
try {
echo_xml = new JoltRemoteService("ECHO_XML", session);
System.out.println("JoltRemoteService Created");
echo_xml.setBytes("XML", data, data.length);
} catch (Exception e) {
System.out.println("RemoteService call error" + e);
return;
}
echo_xml.call(null);
System.out.println("Service Call Returned");
odata = echo_xml.getBytesDef("XML", null);
try {
System.out.println("Return String is:" + new String(odata));
} catch (Exception e) {
System.err.println("getByteDef Error");
}
}
}
// end of class
 
Using the MBSTRING Buffer Type
Starting with Tuxedo 9.0, Jolt supports the MBSTRING buffer type which is already supported by Tuxedo ATMI as of Tuxedo 8.1.
Since Java uses Unicode as the standard for multi byte character encoding and provides String class for handling Unicode string data, Jolt MBSTRING support will use the String class as the MBSTRING container on the Java client side. Jolt automatically converts the Unicode MBSTRING data in a String object between byte array MBSTRING data, which is the ATMI’s MBSTRING representation, when the data is transferred between a Jolt client and a Tuxedo server.
The following methods are added to bea.jolt.Message interface and to bea.jolt.JoltMessage and bea.jolt.JoltRemoteService classes.
addMBString
setMBString
setMBStringItem
getMBStringDef
getMBStringItemDef
The usage of the MBSTRING buffer type is very similar to the STRING buffer type except that the buffer type specified in the Jolt Repository Editor is “MBSTRING” and the Java methods used for setting and getting the MBSTRING data are listed above.
In addition, the following Java system properties are used to specify the character encoding name for MBSTRING data sent to Tuxedo servers.
bea.jolt.mbencoding
The Tuxedo encoding name used for converting Unicode MBSTRING data to the corresponding byte array MBSTRING data while sending MBSTRING data to a Tuxedo server. If this property is not specified, the Java default character encoding name is used and mapped to the corresponding Tuxedo encoding name. For example, the default Japanese Windows encoding name “MS932” should be mapped to the corresponding Tuxedo encoding name “CP932” and specified in this property.
bea.jolt.mbencodingmap
The full path name for the file which specifies character encoding name mapping between Jolt clients and Tuxedo servers. This mapping is necessary because the character encoding name for the same character encoding is sometimes different between Java and Tuxedo. For example, the default Japanese Windows encoding name is MS932 in Java, but in Tuxedo it is CP932. If this property is not specified, mapping is not done.
This means that the Java character encoding name is directly set in the MBSTRING data sent to the Tuxedo server, and the encoding name which is set in the received MBSTRING data from the Tuxedo server is used as the Java encoding name. This may cause a conversion error if the encoding name is not supported by Java or Tuxedo.
To specify the bea.jolt.mbencoding or bea.jolt.mbencodingmap, jolti18n.jar must be included in the CLASSPATH. If jolti18n.jar is not included in the CLASSPATH, the encoding name is set to “ISO-8859-1” and no encoding name is done between Java and Tuxedo even if these properties are specified in the Java command line.
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:
“Threads of Control” 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:
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.
Note:
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 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 generally causes 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) machine running on a Sun platform. If you want your applet to work on JDK 1.3, 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 Oracle 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 an Oracle Tuxedo service function and then immediately start another thread that sends another request to an Oracle 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:
Listing 5‑11 illustrates the use of two threads in a Jolt application.
Listing 5‑11 Using Multiple Threads with Jolt (ThreadBank.java)
/* Copyright 1996 Oracle 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 Oracle Tuxedo Services or other Oracle Tuxedo clients. The Jolt Class Library contains classes that support the following types of Oracle Tuxedo notifications for handling event-based communication:
Unsolicited Event Notificationsthese are notifications that a Jolt client receives as a result of an Oracle Tuxedo client or service issuing a broadcast using either a tpbroadcast() or a directly targeted message via a tpnotify() ATMI call.
Brokered Event Notificationsthese notifications are received by a Jolt client through the Oracle Tuxedo Event Broker. The notifications are only received when the Jolt client subscribes to an event and any Oracle Tuxedo client or server issues a system-posted event or tppost() call.
Event Subscription Classes
The Jolt Class Library provides four classes that implement the asynchronous notification mechanism for Jolt client applications:
JoltSessionthe JoltSession class includes an onReply() method for receiving notifications and notification messages.
JoltReplythe JoltReply class gives the client application access to any messages received with an event or notification.
JoltMessagethe JoltMessage class provides get() methods for obtaining information about the notification or event.
JoltUserEventthe JoltUserEvent class supports subscription to both unsolicited and event notification types.
For additional information about these classes refer to the Oracle Jolt API Reference.
Notification Event Handler
For both unsolicited notifications and a brokered event notification, the Jolt client application requires an event handler routine that is invoked upon receipt of a notification. Jolt only supports a single handler per session. In Oracle 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 to 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 Oracle 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, because 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 Oracle 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 Oracle Tuxedo data buffer type. Jolt clients (for example, the handler) 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 Oracle 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 by the preceding get*() methods.
Oracle Tuxedo Event Subscription
Oracle Tuxedo brokered event notification allows Oracle 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 Oracle Tuxedo events that are broadcast or posted using the Oracle Tuxedo tpnotify() or tpbroadcast() calls.
Jolt clients can only subscribe to events and notifications that are generated by other components in Oracle Tuxedo (such as an Oracle Tuxedo service or client). Jolt clients can not 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:
Subscribing to single event notification is not the recommended method for enabling unsolicited notification. If you want unsolicited notification, the application should explicitly subscribe to unsolicited notifications (as described in the JoltUserEvent class). The next section is about unsubscribing from notifications.
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 Oracle Tuxedo. In Oracle 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 Oracle Tuxedo Notifications
The “Asynchronous Notification” 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 5‑12 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 contains the clear() method, which allows you to remove existing attributes from an object and, in effect, provides for the reuse of the object. The “Jolt Object Reuse (reuseSample.java)” listing illustrates how to use the clear() method to clear parameter values and how to reuse the JoltRemoteService parameter values; 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 5‑13 Jolt Object Reuse (reuseSample.java)
/* Copyright 1999 Oracle 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 listing, “Extending Jolt Remote Service (extendSample.java),” 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 that makes use of the Oracle Tuxedo BANKAPP funds TRANSFER service.
Listing 5‑14 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 one of many ways to extend from JoltRemoteService.
Listing 5‑14 Extending Jolt Remote Service (extendSample.java)
/* Copyright 1999 Oracle 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 Oracle 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);
}
}
}
 
Deploying and Localizing Jolt Applets
Using the Jolt Class Library, you can build Java applications that execute from within a client Web browser. For these types of applications, perform the following application development tasks:
The following sections describe these application development considerations.
Deploying a Jolt Applet
When you deploy a Jolt applet, consider the following:
Information for configuring the Oracle Tuxedo server and Jolt server to work with Jolt is available in Installing the Oracle 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:
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:
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 Oracle 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.
Using SSL
Jolt can use SSL as the preferred secure transport mechanism instead of default Link Level Encryption. To enable Jolt to use SSL, the JSL must be configured with '-s secure_port' in the TUXEDO UBBCONFIG file.
Jolt client library automatically chooses SSL if the JSL connection port is the SSL port. The SSL requires Jolt client to provide information about the location of the X.509 certificate, the private key, and passphrase that is used to encrypt the passphrase.
There are five attributes added to the JoltSessionAttributes class to handle these requirement:
KEYSTORE—file path for client private key and X.509 certificate
KSPASSPHRASE—key store passphrase
TRUSTSTORE—trust store file path for trusted X.509 certificates
TSPASSPHRASE—trust store passphrase
KEYPASSPHRASE—private key passphrase
Jolt client library uses the third-party Java Secure Socket Extension (JSSE) implementation for SSL communication. The following JSSE implementations have been tested:
Listing 5‑15 is the sample Jolt client code to make it possible to use SSL when communicate with JSL/JSH.
Listing 5‑15 Using SSL in Jolt Client Code
import java.util.*;
import bea.jolt.*;
public class simpcl extends Object {
private String userName = null;
private String userRole = null;
private String appPassword = null;
private String userPassword = null;
private JoltSessionAttributes attr = null;
private JoltSession session = null;
private JoltRemoteService toupper = null;
private JoltTransaction trans = null;
 
// JSL is configured with '-s 5555'
// the communication between jolt client and JSH will use SSL
private String address = new String('//cerebrum:5555');
 
public static void main(String args[]) {
simpcl c = new simpcl();
c.doTest();
}
 
public void doTest() {
attr = new JoltSessionAttributes();
 
// adding these session attribute
attr.setString(attr.APPADDRESS, address);
attr.setString(attr.TRUSTSTORE,'c:\\samples\\samplecacerts');
attr.setString(attr.KEYSTORE, 'c:\\samples\\client\\testkeys');
 
// Only key store and key will be protected by passphrase in this sample.
// But optionly the trust store can also be protected by a passphrase
// although it is not in this sample.
attr.setString(attr.KSPASSPHRASE, 'passphrase');
attr.setString(attr.KEYPASSPHRASE, 'passphrase');
attr.setInt(attr.IDLETIMEOUT, 300);
 
userName = 'juser';
userRole = 'JUSER';
userPassword = 'abcd';
appPassword = 'abcd';
 
session = new JoltSession(attr, userName, userRole, userPassword,
appPassword);
 
// access a Tuxedo TOUPPER service
toupper = new JoltRemoteService('TOUPPER', session);
toupper.addString('STRING', 'string');
trans = new JoltTransaction(60, session);
try {
toupper.call(trans);
} catch (ApplicationException ae) {
ae.printStackTrace();
System.exit(1);
}
 
String retString = toupper.getStringDef('STRING', null);
trans.commit();
System.out.println(' returned: ' + retString);
session.endSession();
return;
}
}
 
 

Copyright © 1994, 2017, Oracle and/or its affiliates. All rights reserved.