///Java and SNA: A case study

Java and SNA: A case study

Java and SNA: A case study

This report describes a Java tool kit for CPI-C programmers. As published by Sun Microsytems, Java supports on sockets programs on IP network. We describe a tool kit that allows programmers to write LU6.2 programs in Java. We also include preliminary performance measurements.

Intranets are hot. So is good barbecue, and while we know what goes into good barbecue[1], there’s a lot of disagreement about what comprises any intranet, let alone a good one. Since an intranet (like barbecue) is likely no better than its components, it’s worth investigating what’s in one.

The word "intranet" is derived from the "Internet," a world-wide collection of interconnected computers. However, an intranet is not merely a collection of interconnected computers–those have existed in enterprises since the 1960s.

Some might try to define an intranet by the networking protocol (or simply "protocol ") used to ship information among computers–that is, intranets are networks of computers communicating via the "Internet Protocol" (IP).

Such a definition is narrow-minded: networking protocols are rather arcane subjects, left to the domain of a few computer bit-heads; the average computer user doesn’t care about how packets are shipped around a network. He does care about applications, since they define how he interacts with his computing environment. The better the applications, the more productive he’ll be. He also cares about cost–who doesn’t?

User productivity is measured by the amount of work each person can complete–in this case by using the applications running on the network. It encompasses such factors as reliability and application "intuitiveness." "Cost" refers not only to the cost of the hardware used to build the network, but also to the cost of operating and servicing the network and the applications running on it.

With these factors in mind, we’ll define an intranet as a low-cost, high-productivity network environment.

It’s clear that for user productivity, IP offers great benefits. Web browsers such as Netscape’s Navigator (Navigator is a trademark of Netscape Corporation) provide an intuitive, graphical way to locate any resource spread throughout IP networks[2] ; SNA applications often present a character-based interface. Furthermore, relative to SNA, IP is quite easy to install on personal computers, thus lowering costs.

However, 70% of business data resides on mainframes and is accessed primarily through SNA, an enterprise-quality, open, networking protocol. The SNA protocol-handling code on most mainframes has been optimized for over a quarter-century and is now lightning fast; the mainframe IP code is still relatively immature and sluggish. So, compared to SNA, IP imposes a large burden on the mainframe and thus increases the cost of productivity.

Even when the mainframe’s IP code matures, SNA will continue to offer benefits. SNA was designed for stability under heavy network loads; IP collapses meekly under similar circumstances [3] . Compared to IP, SNA’s superior reliability characteristics will continue to offer productivity benefits. Furthermore, SNA includes transactional APIs which simplify the development of line-of-business applications.

So there will remain a place for both IP and SNA: IP is quite useful for the general Internet, where ease-of-use and ease-of-install are especially important; SNA is preferable in many intranets, where reliability is crucial.

In this paper, we’ll focus on ways to improve SNA intranets by applying Internet technology.

One Internet technology that has garnered much attention lately is Java (a trademark of Sun Microsystems), a network-enabled computing environment developed by Sun Microsystems. Java is a useful technology for two reasons: It is platform-independent, so applications can be written once and run on a variety of computers; and it can be dynamically downloaded–that is, code can reside on a server and flow to the client as needed, thus reducing client-installation costs.

However, the Sun developers chose to release Java with IP bindings but without SNA bindings. We have removed this limitation. To improve Java’s suitability for enterprise, high-reliability intranets, we’ve created a Java binding to CPI-C, an open API for SNA’s LU6.2.

We recognize that the majority of SNA applications use LU2. We chose to do an LU6.2 binding first because it can run on peer workstations, making it a relatively simple learning platform; LU2 requires mainframe interaction, complicating development. With the skills developed during our LU6.2 work, we plan to push forth to other communications protocols.

To date, we’ve implemented the 16 CPI-C calls needed to write the five "classic transactions": Pipeline, Credit Check, Inquiry, File Transfer, and Database Update. Implementing the remaining 31 calls in CPI-C version 1.2 will be straightforward.

The remainder of the paper discusses our Java binding to CPI-C, including a discussion of the Java/CPI-C API and the development issues that we encountered. For our development, we used the OS/2 Warp operating systems and the CommServer 4.0 SNA stack and CPI-C API. Some familiarity with Java and CPI-C is assumed.

The Java/CPI-C API

While designing our API, our primary goal was to mimic the C version of the CPI-C API and thus leverage C programmers’ learning investment. To a great extent, we’ve accomplished this goal. To current CPI-C programmers, the calls to the CPI-C library will look extremely familiar.

Preserving the look of the actual calls requires some additional work by the programmer, such as creating objects to hold some of the output parameters. This is necessary to resolve an unavoidable conflict: Java uses pass-by-value function calls; CPI-C uses pass-by-reference [4] . Since Java is an object-oriented language, we feel that it is natural to create objects to hold CPI-C parameters, although we do acknowledge that it creates a small amount of extra work for the programmer.

Classic Transaction #1: The Pipe

To introduce the API, we’ll start by examining the first classic transaction: the Pipe. We present the example by interleaving code with commentary.

We based our transaction code on that given in CPI-C Programming in C, an excellent reference written by John Q. Walker and Peter J. Schwaller. For further information on CPI-C, we recommend the book highly.

First, we import the CPIC package, our Java/CPI-C bindings. A CPIC object is the interface to our LU6.2 code. It contains many constants defined in CPI-C, such as the length of a conversation ID, along with methods that are passed through to the native CPI-C calls.

The programmer need only declare one CPIC object per class. Java will load the dynamic link library (DLL) containing the native methods when that CPIC object is instantiated.



/*--
* Pipeline transaction, client side.
*--*/
import com.ibm.cali.net.CPIC.*;
public class Pipe extends Object {
public static void main(String args[]) {

// Make a CPIC object
CPIC cpic_obj = new CPIC();

Each type of parameter has its own class, and each of these classes has associated constants defined as class variables. For example, the CPICReturnCode class has the success return code, CM_OK, defined in it.

There were two major reasons for having a class for each type of parameter. Most importantly, because Java passes all parameters by value, there was no way to return data in simple types, such as integer. If we pass an object as a parameter to a method, the method can set a variable in that object, thus returning data to the caller. The second reason to use objects is to encapsulate constants within the objects that understand those constants–a standard information-hiding technique.



// Return Code
CPICReturnCode cpic_return_code =
new CPICReturnCode(CPICReturnCode.CM_OK);

// Request to send received?
CPICControlInformationReceived rts_received =
new CPICControlInformationReceived(
CPICControlInformationReceived.CM_NO_CONTROL_INFO_RECEIVED);

The CPI-C send function expects a C-language buffer–that is, allocated space of no specific type. Unlike C, Java has no facility to allocate untyped memory; besides primitives, everything in Java is an object. So whatever the program wants to send must be converted from its object type into an C-style array of bytes. In fact, for each call, the CPIC library must convert from the Java types to a C type.

Java does provide methods that facilitate such conversions. For example, Java can convert a String into a Java array of bytes. While an array of bytes is an object in Java, Java allows you to extract the data–the bytes–from an array of bytes with a native method.

So the programmer must convert his application data into an array of bytes; our code does not do automatic marshalling. While the conversion is not onerous, as we demonstrate below, we are considering augmenting our code to provide this function.



// String to Send
String sendThis = "Test of the PipeLine Transaction";

// Length of String to send
CPICLength send_length = new CPICLength(sendThis.length());

// Convert String to send to a Java array of bytes
byte[] stringBytes = new byte[ send_length.intValue()];
sendThis.getBytes(0,send_length.intValue(),stringBytes,0);

Like buffer processing, the CPI-C native calls expect symbolic destination names to be C-strings, not Java Strings. Our tool kit automatically converts them from Java Strings to a C-strings as necessary. In general, automatic conversion is possible when the tool kit expects a specific Java type.

The conversation ID is a Java array of bytes that is converted automatically by our tool kit to a C array of bytes–that is, a simple block of bytes.



// this hardcoded sym_dest_name must
// be 8 chars long & blank padded
String sym_dest_name = "PIPE ";

// Space to hold a conversation ID
// (which is just a bunch of bytes)
byte[] conversation_ID = new byte[CPIC.CM_CID_SIZE];

Now the programmer is ready to make the CPIC calls almost exactly as he would in C. The only noteworthy differences are that he prefaces every CPIC call with the name of the CPIC object and that none of the parameters are prefixed by the pass by reference (&) symbol.



//
// Initialize CPI-C
//
cpic_obj.cminit( /* Initialize_Conversation */
conversation_ID, /* O: returned conversation ID */
sym_dest_name, /* I: symbolic destination name */
cpic_return_code); /* O: return code from this call */
//
// ALLOCATE
//
cpic_obj.cmallc( /* Allocate Conversation */
conversation_ID, /* I: conversation ID */
cpic_return_code); /* O: return code from this call */
//
// SEND
//
cpic_obj.cmsend( /* Send_Data */
conversation_ID, /* I: conversation ID */
stringBytes, /* I: send this buffer */
send_length, /* I: length to send */
rts_received, /* O: was RTS received? */
cpic_return_code); /* O: return code from this call */
//
// DEALLOCATE
//
cpic_obj.cmdeal( /* Deallocate */
conversation_ID, /* I: conversation ID */
cpic_return_code); /* O: return code from this call */
} // end main method
} // end the class

That’s the end of the client, so we’ll turn our attention to the server. The server initializes itself, accepts a conversation, receives some data, and prints some diagnostic information. The code is similar to the client code, so we’ll omit discussion of some of the redundant details.

As in the client, we instantiate classes to hold the CPI-C parameters, many of which have only an integer as instance data; recall that by using objects, we can mimic call by reference. We also allocate a byte array to hold the received data.



/*--
* Pipeline transaction, server side.
*--*/
import com.ibm.cali.net.CPIC.*;
import Java.io.IOException;

public class PipeServer extends Object {
public static void main(String args[]) {

CPIC cpic_obj = new CPIC();

// Space to hold the received data
byte[] data_buffer;
data_buffer = new byte[101];

CPICLength requested_length = new CPICLength(101);
CPICDataReceivedType data_received =
new CPICDataReceivedType(0);
CPICLength received_length = new CPICLength(0);
CPICStatusReceived status_received =
new CPICStatusReceived(0);
CPICControlInformationReceived rts_received =
new CPICControlInformationReceived(0);
CPICReturnCode cpic_return_code =
new CPICReturnCode(0);

// Space to hold a conversation ID -- a bunch of bytes)
byte[] conversation_ID;
conversation_ID = new byte[cpic_obj.CM_CID_SIZE];

The CPI-C receive call returns a Java array of bytes, while the Pipe transaction expects a String. The programmer can translate the array of bytes into a String by using the String class-constructor that takes an array of bytes as an argument.



//
// ACCEPT
//
cpic_obj.cmaccp( /* Accept_Conversation */
conversation_ID, /* O: returned conversation ID */
cpic_return_code); /* O: return code */
//
// RECEIVE
//
cpic_obj.cmrcv( /* Receive */
conversation_ID, /* I: conversation ID */
data_buffer, /* I: where to put received data */
requested_length, /* I: maximum length to receive */
data_received, /* O: data complete or not? */
received_length, /* O: length of received data */
status_received, /* O: has status changed? */
rts_received, /* O: was RTS received? */
cpic_return_code); /* O: return code from this call */
//
// Do some return code processing
//
System.out.println(" Data from Receive:");
System.out.println(" cpic_return_code = " +
cpic_return_code.intValue());
System.out.println(" cpic_data_received = " +
data_received.intValue());
System.out.println(" cpic_received_length = " +
received_length.intValue());
System.out.println(" cpic_rts_received = " +
rts_received.intValue());
System.out.println(" cpic_status_received = " +
status_received.intValue());
// Create a Java String from the array of bytes that you received
// and print it out.
String receivedString = new String(data_buffer,0);
System.out.println(
" Recevied string = "
+ receivedString );

//
// BLOCK so that the Server Window doesn't disappear
//
try{
System.out.println("Press any key to continue");
System.in.read();
}
catch
(IOException e){ e.printStackTrace(); }
}
}

Classic Transaction #5: The Database Update

Now that we’ve looked at the Pipe, the simplest of the classic transactions, we will look at the most complex transaction, Update, and study the differences.

In the Update transaction, a client requests information from a server, modifies the information, and returns it to the server. It demonstrates a "conversational transaction"–that is, it includes multiple sends and receives within a single conversation. Because the code follows directly from our prior discussion, we omit a detailed explanation of the transaction; the code is included in the appendix.

More interesting than the transaction itself is the use of an extended CPIC class. The update transaction requires two actions that are among the "building blocks" described in Walker and Schwaller’s book. They place these actions in C functions (DOCPIC.C in the book) that are easily reused.

In JAVA we can take advantage of inheritance and can extend the CPIC class to include these new actions. We created a CPICClassic5 class that extends (Java’s term for inheritance) the CPIC class and added the new actions to the CPICClassic5 class.

When a user instantiates a CPICClassic5 object (rather than a CPIC object) the user now gets all of the CPIC methods, augmented by the code developed for this transaction. The user of the CPICClassic5 object cannot distinguish between the native CPIC methods and the added function.

This example illustrates an important point: Because the CPIC tool kit is object-oriented, users can customize and extend it to fit their needs, seamlessly extending the base function. This opportunity does not exist in C.

Native Calls

Note that a CPIC user can’t tell whether the package is included in the standard Java distribution or calls an add-on DLL. In fact, what is and isn’t included in standard Java depends largely on what Sun chooses to include. When standard function is lacking, programmers can compensate by implementing libraries that call native methods. Of course, it then becomes their responsibility to provide cross-platform support–something lacking in the prototype.

Diversion: Native Calls and Applets

There is one drawback to implementing native methods: They can’t be called from applets. If the reader were to download our library, write an applet that used it, and then try to run the applet on (for example) a Netscape browser, he would trigger a security exception.

The reason is simple: Applets are not permitted to make native calls. ("delete *.*" is a native call–do you want arbitrary applets issuing that?) However, in an intranet, certain applets will be trusted, at least sufficiently trusted to call another networking protocol. We expect that browser manufactures will implement more flexible applet-security policies. Until then, SNA applications will have to be run as applications.

Performance

Because Java is an interpreted language, many people are concerned about its performance. We conducted an experiment to determine Java’s impact on network performance.

For our benchmark, we used the Update transaction. Update requires three network flows: a "request" from the client to the server; a "reply" from the server to the client; and an "update" from the client to the server. In our experiment, each of the flows contained the same number of bytes.

Our server was a 150 MHz Pentium Pro ™ computer with 32MB of RAM running OS/2 Warp and CommServer for OS/2 with the Access Feature. Our client was also 150 MHz Pentium Pro ™ computer running OS/2 Warp and CommServer for OS/2 with the Access Feature; the client had 64MB of RAM. The test was conducted on an isolated 16Mbit/sec token ring.

We wrote the Update client in both C and in Java; the server was written in C and was pre-loaded. We measured only the time to execute a 2,000 iteration transaction loop; the start-up time for the Java interpreter was not included. We ran each client five times, for a total of 10,000 iterations. The standard deviation among the five trials was less than 2%.

The times per transaction are given below:

Bytes/Send C client (msec) Java client (msec) Difference (msec)
256 10.9 16.2 5.3
1024 12.4 17.5 5.1
4096 15.7 20.9 5.2
16384 36.4 41.5 5.1

Switching from C to Java results in a small, constant performance loss of about 5.2 msec per transaction on the client. Since the amount of Java code executed–the only difference between the two clients–does not depend on the number of bytes sent, the constant variation is unsurprising. Since the difference is so slight, it will be unnoticed during interactive work.

It is important to note that there is no performance impact on the server. The server is written in C and is identical for both clients. Thus, implementing the client in Java does not reduce the number of server transactions.

CPIC Calls That Have Been Implemented

The following CPIC calls have been implemented to date. This includes all those calls necessary to implement the Classic 5 Transactions.

cmaccp Accept Conversation
cmallc Allocate Conversation
cmcfm Confirm
cmcfmd Confirmed
cmdeal Deallocate Conversation
cmecs Extract Conversation State
cminit Initialize Conversation
cmrcv Receive
cmsdt Set Deallocate Type
cmsend Send
cmserr Send Error
cmsmn Set Mode Name
cmspln Set Partner LU Name
cmssl Set Sync Level
cmsst Set Send Type
cmstpn Set TP Name

(Walker & Schwaller’s book contains a complete list of the CPI-C calls.)

Conclusions

As we demonstrated above, it’s a fairly straightforward design exercise to create a Java-callable CPI-C library. The biggest problem–the conflicting method-calling conventions–is solved by passing objects.

More importantly, we have shown that Java needn’t be considered an IP-only tool. Enterprises use SNA and will continue to demand its reliability and stability. We’ve shown that Intranet technologies such as Java do not exclude SNA networks. We expect enterprises to benefit from the combination of Java’s strengths (such as platform-independence and dynamic download) and SNA’s mission-critical reliability.

[1]

Footnotes

1/3 cup butter, 2T water, 2T vinegar, 1T worchestershire sauce, 1t sugar, 1t onion salt, 1/2t garlic powder, 1/2t pepper, dash ground red pepper–Betty Crocker’s Cookbook, 1989, Western Publishing Company, Inc. Return to text.

[2] Using AnyNet’s sockets over SNA function, Web browsers can run over SNA. Return to text.

[3] Lap Huynh, "Performance comparison between TCP slow-start and a new adaptive rate-based congestion avoidance scheme," Proceedings of the IEEE International Workshop on Modeling, Analysis, and Simulation of Computer and Telecommunications Systems, 1994. Return to text.

[4] CPI-C was designed from the beginning to be cross-language-enabled. Clearly, the Java architects did not interact with the CPI-C architects. Return to text.

Note: This paper was originally published as an IBM Technical Report (TR 29.2168).

2010-05-26T17:17:12+00:00 May 24th, 2003|Java|0 Comments
Matt MacKinnon received a BS in Computer Science from Penn State University in 1994. He joined IBM in Research Triangle Park in 1995, where he works on CommServer for OS/2, along with Java projects.


Adam King is a Senior Associate Programmer working on an advanced technology Java project. Adam received BSs in Computer Science and Computer Science/Mathematics from Furman University in 1989 and an MS in Computer Science from Clemson University in 1991. He has been with IBM in RTP since 1991.


David Kaminsky is an Advisory Programmer and the team lead for an advanced technology Java project. David received a BA in Mathematics from the University of Virginia in 1988, an MS and MPhil in Computer Science from Yale University in 1990, and a Ph.D. from Yale in 1994. Dr. Kaminsky's dissertation investigated parallel programming over networks of workstations.


Leave A Comment