Using Oracle Jolt

     Previous  Next    Open TOC in new window  Open Index in new window  View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

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: All program examples are only fragments used to illustrate Jolt capabilities. They are not intended to be compiled and run as provided. These program examples require additional code to be fully executable.

 


Class Library Functionality Overview

The Jolt Class Library 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).

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.

Table 5-1 Jolt Client/Server Interaction
Jolt Client
Jolt Server
1
attr=new JoltSessionAttributes();
attr.setString(attr.APPADDRESS, “//myhost:8000”);
Binds the client to the Oracle Tuxedo environment
2
session=new JoltSession(attr, username, userRole, userPassword, appPassword);
Logs the client onto Oracle Tuxedo
3
withdrawal=new JoltRemoteService( servname, session );
Looks up the service attributes in the Repository
4
withdrawal.addString(“accountnumber”, “123”);
withdrawal.addFloat(“amount”, (float) 100.00);
Populates variables in the client (no Jolt Server activity)
5
trans=new JoltTransaction( time-out, session);
Begins a new Tuxedo transaction
6
withdrawal.call(trans);
Executes the Oracle Tuxedo service
7
trans.commit() or trans.rollback();
Completes or rolls back transaction
8
balance=withdrawal.getFloatDef(“balance,” (float) 0.0);
Retrieves the results (no Jolt Server activity)
9
session.endSession();
Logs the client off of Oracle Tuxedo

The following tasks summarize the interaction shown in the previous table, Jolt Client/Server Interaction.

  1. Bind the client to the Oracle Tuxedo environment using the JoltSessionAttributes class.
  2. Establish a session.
  3. Set variables.
  4. Perform the necessary transaction processing.
  5. Log the client off of the Oracle Tuxedo system.

Each of these activities is handled through the use of the Jolt Class Library classes. These classes include methods for setting and clearing data and for handling remote service actions. Jolt Object Relationships 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

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:

 


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. Set the input parameters.
  2. Invoke the service.
  3. Examine the output parameters.

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 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) 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):

  1. Set the connection attributes like hostname and portnumber in the JoltSessionAttribute object.
  2. Refer to this line in the following code listing:

    sattr = new JoltSessionAttributes();
  3. The sattr.checkAuthenticationLevel() allows the application to determine the level of security required to log on to the server.
  4. Refer to this line in the following code listing:

    switch (sattr.checkAuthenticationLevel())
  5. The logon is accomplished by instantiating a JoltSession object.
  6. 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.

  7. All JoltRemoteService calls require a service to be specified and the session key returned from JoltSession().
  8. 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.

  9. Once the service definitions are returned, the application-specific fields such as account number ACCOUNT_ID and withdrawal amount SAMOUNT are automatically populated.
  10. 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.

  11. The JoltTransaction call allows a timeout to be specified if the transaction does not complete within the specified time.
  12. Refer to this line in the following code listing:

    trans = new JoltTransaction(5,session);
  13. Once the withdrawal service definition is automatically populated, the withdrawal service is invoked by calling the withdrawal.call(trans) method.
  14. Refer to this line in the following code listing:

    withdrawal.call(trans);
  15. A failed WITHDRAWAL can be rolled back.
  16. Refer to this line in the following code listing:

    trans.rollback();
  17. Otherwise, once the DEPOSIT is performed, all the transactions are committed. Refer to these lines in the following code listing:
  18. 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: X_OCTET is used identically to CARRAY.
X_COMMON and X_C_TYPE are used identically to VIEW.

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

Using the STRING buffer type requires two main steps:

  1. Define the Tuxedo service that you will be using with the buffer type.
  2. Write the code that uses the STRING buffer type.

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) 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 for more information about defining your services and adding new parameters.
  1. In the Jolt Repository Editor Logon window, click Services.
  2. Figure 5-3 Add a TOUPPER Service


    Add a TOUPPER Service

  3. In the Services window, select the TOUPPER service in the SIMPSERV package.
  4. Click Edit.
  5. Figure 5-4 Set Input and Output Buffer Types to STRING


    Set Input and Output Buffer Types to STRING

  6. In the Edit Services window, define an input buffer type of STRING and an output buffer type of STRING. Refer to the figure Set Input and Output Buffer Types to STRING.)
  7. For the TOUPPER service, define only one parameter named STRING, which is both an input and an output parameter.
  8. 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: X_OCTET is used identically to CARRAY.

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 for more information about defining your services and adding new parameters.
Figure 5-5 Repository Editor: Add the ECHO Service

Repository Editor: Add the ECHO Service

Use the Repository Editor to add the ECHO service as follows:

  1. In the Repository Editor, add a service called ECHO.
  2. Define the input buffer type and output buffer type as CARRAY.
  3. Define only one parameter named CARRAY, which is both an input and output parameter.
Note: If using the X_OCTET buffer type, you must change the Input Buffer Type and Output Buffer Type fields to X_OCTET.
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.

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 for more information about defining a service.
  1. In the Edit Services window of the Jolt Repository Editor, define the PASSFML service with an input buffer type of FML and an output buffer type of FML.
  2. The figure Repository Editor Window: Edit Services (PASSFML) illustrates the PASSFML service, and Input Buffer and Output Buffer of FML.

    Figure 5-7 Repository Editor Window: Edit Services (PASSFML)


    Repository Editor Window: Edit Services (PASSFML)

  3. Select the input buffer type and output buffer type as FML for the PASSFML service.
  4. Click Edit to display the Edit Parameters window as shown in Figure 5-8.
  5. Figure 5-8 Edit the PASSFML Parameters


    Edit the PASSFML Parameters

  6. Define the parameter for the PASSFML service.
  7. Repeat steps 2-4 for each parameter in the PASSFML service.

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 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 for more information about defining a service.
Figure 5-9 Repository Editor: Add SIMPVIEW Service

Repository Editor: Add SIMPVIEW Service

In the Repository Editor add the VIEW service as follows:

  1. Add a SIMPVIEW service for the SIMPSERV package.
  2. Define the SIMPVIEW service with an input buffer type of VIEW and an output buffer type of VIEW.
  3. Figure 5-10 Repository Editor: Edit SIMPVIEW Service


    Repository Editor: Edit SIMPVIEW Service

  4. Define the parameters for the VIEW service. In this example the parameters are: inInt, inString, outFloat, outInt, outString.
Note: If using the X_COMMON or X_C_TYPE buffer types, you must put the correct buffer type in the Input Buffer Type and Output Buffer Type fields. Additionally, you must choose the corresponding Input View Name and Output View Name fields.

simpview.java Client Code

The listing 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. 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: Similar to CARRAY, the XML buffer type is treated as a byte arrary, not a STRING. Therefore, no data conversion takes place between a Jolt client and an Oracle Tuxedo service.

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 for more information about defining your services and adding new parameters.
Figure 5-11 Repository Editor: Add the XML Service

Repository Editor: Add the XML Service

Use the Repository Editor to add the XML service as follows:

  1. In the Repository Editor, add a service called ECHO_XML.
  2. For the ECHO_XML service, define the input buffer type and output buffer type as XML.
  3. Define the ECHO_XML service with only one parameter named XML, which is both an input and output parameter.
  4. Figure 5-12 Repository Editor: Edit the XML Service


    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: Most Java implementations provide preemptive rather than non-preemptive threads. The difference between these two models can lead to very different performance and programming requirements.

Threads of Control

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

Note: The Java VM schedules threads of the same priority to run in a round-robin mode.

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:

Event Subscription Classes

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

For additional information about these classes refer to the 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: If the user loads a new HTML page into the browser, the applet execution is stopped.

Web Server Considerations

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

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

<html-dir>/classes/bea/jolt

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

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

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

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

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

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

Localizing a Jolt Applet

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

For localization, the Jolt Class Library package relies on the conventions of the Java language and the 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:

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;
    }
}

  Back to Top       Previous  Next