bea.com | products | dev2dev | support | askBEA

Download Docs
Search

Programming Guide

Performing Your Own Data Translation

This section discusses the following topics:

- Why Perform Your Own Data Translation?

- Using EgenClient Directly

- Translating Buffers from Java to Mainframe Representation

- Translating Buffers from Mainframe Format to Java

Why Perform Your Own Data Translation?

The automatic data translation provided by DataViews can usually fill your needs. The eGen-generated DataViews relieve your application of the burden of translating data between the mainframe EBCDIC environment and the Java runtime environment. In addition, native mainframe data types that are not supported in Java (such as packed, zoned decimal, etc.) are automatically mapped to appropriate Java data types. However, occasionally you may want to bypass these features and create your own data translation. Following are some advantages of bypassing the eGen/DataView infrastructure:

- Unnecessary data translation may be avoided

If the data has been acquired in the appropriate format, it can simply be transmitted to the mainframe bypassing the DataView translation overhead.

- Contents of data buffer may be dynamically determined at runtime

In some cases, this may be preferable to a DataView generated from a copybook containing numerous REDEFINES representing various record types.

Simple interfaces are provided for translating data both from and to the mainframe. In addition, a simple callService() method is available for making mainframe service requests.

Using EgenClient Directly

EgenClient is the WebLogic JAM class responsible for making service calls from WebLogic Server to the mainframe. This class is the foundation of all WebLogic Server to Mainframe communication by eGen-created EJB and Servlet objects. EgenClient may also be used directly by applications to issue mainframe service requests. Listing 6-1 shows the public methods available for your use:

Listing 6-1 EgenClient Public Interface

>     package com.bea.jam.egen;

>     import java.io.IOException;
>     import com.bea.sna.jcrmgw.snaException;

>     public class EgenClient
>     {
>     	public EgenClient();
>     	public EgenClient(String serverURL);
>     	public void setServerURL(String serverURL);
>     	public byte[] callService(String service, byte[] in)
>     		throws snaException, IOException;
>     	public void setUserID(String userid);
>     	public void setPassword(String password);
>     }

Table 6-1 lists the definitions of the public interface methods:

Table 6-1 EgenClient Public Interface Methods

Method | Description
--- | ---
EgenClient() | The default constructor. Constructing an EgenClient class using the default constructor will search for a jam.url property containing the WebLogic JAM Gateway server URL.
EgenClient(URL) | If the EgenClient class is provided a URL at construction, it will be used in place of the search for a jam.url property.
setServerURL(URL) | This method may be used to override the URL set at construction. All service calls following the invocation of this method will use the URL provided.
callService(service, in) | This method is the workhorse of the EgenClient class. The mainframe service in the WebLogic JAM configuration named service will be called and passed the buffer provided by the in parameter. The response buffer of the service is returned from this method.
setUserID(userid) | This method sets the User ID used to access a mainframe service.
setPassword(password) | This method sets the password used to access a mainframe service.

How EgenClient Locates a WebLogic JAM Gateway

The EgenClient class requires a connection to a WebLogic Server running a WebLogic JAM Gateway to communicate with a mainframe. This connection is accomplished via a URL provided by the caller identifying the server, or cluster of servers, hosting the WebLogic JAM Gateway(s). The EgenClient class attempts to obtain this URL from the following sources (listed in priority order):

1. If the EgenClient.setServerURL() method has been called, the URL provided is used to locate a WebLogic JAM Gateway.

2. If a URL was provided on the EgenClient constructor, this URL is used to locate a WebLogic JAM Gateway.

3. EgenClient checks for the existence of a jam.url system property and, if present, uses its value as the URL to locate a WebLogic JAM gateway.

4. EgenClient searches the CLASSPATH for a file named jam.properties. If this properties file is found and contains a jam.url entry, this value is used to locate a WebLogic JAM Gateway.

5. EgenClient assumes that it is running on the same WebLogic Server as the WebLogic JAM Gateway and attempts to establish a local connection.

Using EgenClient to Make a Mainframe Request

Listing 6-2 illustrates calling a mainframe service via the EgenClient class. This example assumes that a properly formatted mainframe buffer is passed as a parameter, and that the URL of a correctly configured WebLogic JAM Gateway is set via the jam.url property.

Listing 6-2 Mainframe Request Using EgenClient

>     import com.bea.jam.egen.EgenClient;
>     import com.bea.sna.jcrmgw.snaException;
>     import java.io.IOException;
>     	.
>     	.
>     public byte[] getPurchaseOrder(byte[] poNum)
>     		throws IOException
>     {
>     	try
>     	{
>     	return(new EgenClient().callService("GetPO", poNum));
>     	}
>     	catch (snaException e)
>     	{
>     		throw new IOException(e.getMessage());
>     	}
>     }

The sections that follow provide information on dynamically creating mainframe buffers and interpreting the responses from mainframe services.

Translating Buffers from Java to Mainframe Representation

Support for creating buffers for input to a mainframe service is provided by the com.bea.base.io.MainframeWriter class. This class functions similar to a Java java.io.DataOutputStream object. It translates Java data types and all mainframe-native data types. For numeric data types, this translation service provides a conversion from Java native numeric types to those available on the mainframe. For string data types, a translation is performed from UNICODE to EBCDIC by default, although the output codepage used is configurable.

MainframeWriter Public Interface

Listing 6-3 shows the public methods provided by the MainframeWriter class.

Listing 6-3 MainframeWriter Class Public Methods

>     package com.bea.base.io;

>     public class MainframeWriter
>     {
>     	public MainframeWriter();
>     	public MainframeWriter(String codepage);
>     	public void setDefaultCodepage(String cp)
>     	public byte[] toByteArray();
>     	public void writeRaw(byte[] bytes
>     		throws IOException;
>     	public void writeFloat(float value)
>     		throws IOException;
>     	public void writeDouble(double value)
>     		throws IOException;
>     	public void write(char c)
>     		throws IOException;
>     	public void writePadded(String s, char padChar, int length)
>     		throws IOException;
>     	public void write16bit(int value)
>     		throws IOException;
>     	public void write16bitUnsigned(int value)
>     		throws IOException;
>     	public void write16bit(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write16bitUnsigned(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write32bit(int value)
>     		throws IOException;
>     	public void write32bitUnsigned(long value)
>     		throws IOException;
>     	public void write32bit(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write32bitUnsigned(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write64bit(long value)
>     		throws IOException;
>     	public void write64bitUnsigned(long value)
>     		throws IOException;
>     	public void write64bitBigUnsigned(BigDecimal value)
>     		throws IOException;
>     	public void write64bit(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write64bit(BigDecimal value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write64bitUnsigned(long value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void write64bitUnsigned(BigDecimal value, int scale)
>     		throws IOException, ArithmeticException;
>     	public void writePacked(BigDecimal value, int digits,
>     		int precision, int scale)
>     		throws ArithmeticException, IOException;
>     	public void writePackedUnsigned(BigDecimal value,
>     		int digits, int precision, int scale)
>     		throws ArithmeticException, IOException;
>     }

Following are the definitions of these methods:

Table 6-2 MainframeWriter Class Public Method Definitions

Method | Description
--- | ---
MainframeWriter() | The default constructor. Constructs a MainframeWriter using the default code page of cp037 (EBCDIC).
MainframeWriter(cp) | Constructs a MainframeWriter using the specified codepage for character field translation.
setDefaultCodepage(cp) | Set the codepage to be used for all future data translations.
toByteArray() | Returns the translated buffer constructed by writing data to the MainframeWriter class as a byte array.
writeRaw(bytes) | Write a raw byte array to the output buffer.
writeFloat(num) | Convert a floating point number from the IEEE Java float data type to IBM 4 byte floating point format. The equivalent COBOL picture clause is PIC S9V9 COMP-1.
writeDouble(num) | Convert a floating point number from the IEEE Java double data type to IBM 8 byte floating point format. The equivalent COBOL picture clause is PIC S9V9 COMP-2.
write(c) | Translate and write a single character to the output buffer. The equivalent COBOL picture clause is PIC X.
writePadded(str, pad, len) | Translate and write a string to a fixed length character field. The passed pad character is used if the length of the passed string is less than len. If the length of the passed string is greater than len, it will be truncated to len characters. The equivalent COBOL picture clause is PIC X(len).
write16bit(num) | Writes a signed 16 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC S9(4) COMP.
write16bitUnsigned(num) | Writes an unsigned 16 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC 9(4) COMP.
write16bit(num, scale) | Writes a signed 16 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write16bit(100, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC S9(4) COMP.
write16bitUnsigned(num, scale) | Writes an unsigned 16 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write16bitUnsigned(100, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC 9(4) COMP.
write32bit(num) | Writes a signed 32 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC S9(8) COMP.
write32bitUnsigned(num) | Writes an unsigned 32 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC 9(8) COMP.
write32bit(num, scale) | Writes a signed 32 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write32bit(100L, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC S9(8) COMP.
write32bitUnsigned(num, scale) | Writes an unsigned 32 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write32bitUnsigned(100L, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC 9(8) COMP.
write64bit(num) | Writes a signed 64 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC S9(15) COMP.
write64bitUnsigned(num) | Writes an unsigned 64 bit binary integer to the output buffer. The equivalent COBOL picture clause is PIC 9(15) COMP.
write64bit(num, scale) | Writes a signed 64 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write64bit(100L, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC S9(15) COMP.
write64bitUnsigned(num, scale) | Writes an unsigned 64 bit integer to the output buffer after moving the implied decimal point left by scale digits. For example, the call write64bitUnsigned(100L, 1) would result in the value 10 being written. The equivalent COBOL picture clause is PIC 9(15) COMP.
writePacked(num, digits, prec, scale) | Writes a decimal number as an IBM signed packed data type with digits decimal digits total and prec digits to the right of the decimal point. Prior to conversion, the number is scaled to the left scale digits. The equivalent COBOL picture clause is PIC S9(digits-prec)V9(prec) COMP-3.
writePackedUnsigned(num, digits, prec, scale) | Writes a decimal number as an IBM unsigned packed data type with digits decimal digits total and prec digits to the right of the decimal point. Prior to conversion the number is scaled to the left scale digits. The equivalent COBOL picture clause is PIC 9(digits-prec)V9(prec) COMP-3.

Using MainframeWriter to Create Data Buffers

As an example of using the MainframeWriter class to create a mainframe data buffer, assume we have a mainframe service which accepts the data record shown in Listing 6-4:

Listing 6-4 Data Record

>     01 INPUT-DATA-REC.
>     	05  FIRST-NAME			PIC X(10).
>     	05  LAST-NAME			PIC X(10).
>     	05  AGE			PIC S9(4) COMP.
>     	05  HOURLY-RATE 			PIC S9(3)V9(2) COMP-3.

Listing 6-5 shows a Java test program that creates a buffer matching this record layout using the MainframeWriter translation class:

Listing 6-5 Java Test Program

>     import java.math.BigDecimal;

>     import com.bea.base.io.MainframeWriter;

>     public class MakeBuffer
>     {
>     	public static void main(String[] args) throws Exception
>     	{
>     		MainframeWriter mf = new MainframeWriter();
>     		mf.writePadded("Edgar", ' ', 10);	// first name
>     		mf.writePadded("Jones", ' ', 10);	// last name
>     		mf.write16bit(22);	// age
>     		mf.writePacked(new BigDecimal(22.50), 5, 2, 0);	// hourly rate
>     		byte[] buffer = mf.toByteArray();
>     		System.out.println(getHexString(buffer));
>     	}

>     	private static String getHexString(byte[] buffer)
>     	{
>     		StringBuffer hexStr = new StringBuffer(buffer.length * 2);
>     		for (int i = 0; i < buffer.length; ++i)
>     		{
>     			int n = buffer[i] & 0xff;
>     			hexStr.append(hex[n >> 4]);
>     			hexStr.append(hex[n & 0x0f]);
>     		}
>     		return(hexStr.toString());
>     	}

>     	private static char[] hex =
>     		{
>     			'0', '1', '2', '3', '4', '5', '6', '7',
>     			'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
>     		};
>     }

The output of running this sample program is:

>     C5848781994040404040D1969585A24040404040001602250C

This buffer breaks down as follows:

>     FIRST-NAME		C5848781994040404040	"Edgar" + 5 spaces in EBCDIC
>     LAST-NAME		D1969585A24040404040	"Jones" + 5 spaces in EBCDIC
>     AGE		0016			22 as 16 bit integer
>     HOURLY-RATE		02250C			22.50 positive packed number
>     					(decimal point is assumed)

Translating Buffers from Mainframe Format to Java

Support for translating data received from the mainframe to Java data types is provided by the com.bea.base.io.MainframeReader class. This class operates in a manner similar to a Java jam.io.DataInputStream, and performs translations from mainframe data types to equivalent types usable by a Java program. Like the MainframeWriter class, the codepage used for string translations may be configured and defaults to EBCDIC.

MainframeReader Public Interface

Listing 6-6 shows the public methods provided by the MainframeReader class.

Listing 6-6 MainframeReader Class Public Methods

>     package com.bea.base.io;

>     public class MainframeReader
>     {
>     	public MainframeReader(byte[] buffer);
>     	public MainframeReader(byte[] buffer, String codepage);
>     	public void setDefaultCodepage(String cp);
>     	public byte[] readRaw(int count) throws IOException;
>     	public float readFloat() throws IOException;
>     	public double readDouble() throws IOException;
>     	public char readChar() throws IOException;
>     	public String readPadded(char padChar, int length)
>     		throws IOException;
>     	public short read16bit() throws IOException;
>     	public int read16bitUnsigned() throws IOException;
>     	public long read16bit(int scale) throws IOException;
>     	public int read32bit() throws IOException;
>     	public long read32bit(int scale)
>     		throws IOException;
>     	public long read32bitUnsigned() throws IOException;
>     	public long read32bitUnsigned(int scale) throws IOException;
>     	public long read64bit() throws IOException;
>     	public long read64bitUnsigned()
>     		throws IOException;
>     	public long read64bit(int scale)
>     		throws IOException;
>     	public BigDecimal read64bitBigUnsigned()
>     		throws IOException;
>     	public BigDecimal read64bitBig(int scale)
>     		throws IOException
>     	public BigDecimal readPackedUnsigned(int digits,
>     		int precision, int scale)
>     		throws ArithmeticException, IOException;
>     	public BigDecimal readPacked(int digits,
>     		int precision, int scale)
>     		throws ArithmeticException, IOException;
>     }

Following are the definitions of these methods:

Table 6-3 MainframeReader Class Public Method Definitions

Method | Description
--- | ---
MainframeReader(buffer) | Constructs a MainframeReader for the passed buffer using the default code page of cp037 (EBCDIC).
MainframeReader(buffer, cp) | Constructs a MainframeReader for the passed buffer using the specified codepage for character field translation.
setDefaultCodepage(cp) | Sets the codepage to be used for all future character translations.
readRaw(count) | Read count characters from the buffer without any translation and return them as a byte array.
readFloat() | Read a 4 byte IBM floating point number and return it as a Java float data type.
readDouble() | Read an 8 byte IBM floating point number and return it as a Java double data type.
readChar() | Read and translate a single character.
readPadded(pad, len) | Read and translate a fixed length character field and return it as a Java String. The length of the field is passed as len and the field pad character is passed as pad. Trailing instances of the pad character are removed before the data is returned.
read16bit() | Read a 16 bit binary integer and return it as a Java short.
read16bitUnsigned() | Read an unsigned 16 bit integer and return it as a Java int.
read16bit(scale) | Read a 16 bit binary integer and scale the value by 10^scale. For example, if the value 10 is read via read16bit(1), the returned value would be 100.
read32bit() | Read a 32 bit binary integer and return it as a Java int.
read32bit(scale) | Read a 32 bit binary integer and scale the value by 10^scale. For example, if the value 10 is read via read32bit(1), the returned value would be 100.
read32bitUnsigned() | Read an unsigned 32 bit integer and return it as a Java long.
read32bitUnsigned(scale) | Read an unsigned 32 bit binary integer and scale the value by 10^scale. For example, if the value 10 is read via read32bit(1), the returned value would be 100.
read64bit() | Read a 64 bit binary integer and return it as a Java long.
read64bitUnsigned() | Read an unsigned 64 bit integer and return it as a Java long.
read64bitUnsigned(scale) | Read an unsigned 64 bit binary integer and scale the value by 10^scale. For example, if the value 10 is read via read32bit(1), the returned value would be 100.
read64bitBigUnsigned() | Read an unsigned 64 bit integer and return it as a Java BigDecimal.
read64bitBig(scale) | Read a signed 64 bit integer and scale the value by 10^scale. The value is returned as a Java BigDecimal.
readPackedUnsigned(digits, prec, scale) | Read an unsigned packed number consisting of digits numeric digits with prec digits to the right of the decimal. The value is scaled by 10^scale returned as a Java BigDecimal.
readPacked(digits, prec, scale) | Read a signed packed number consisting of digits numeric digits with prec digits to the right of the decimal. The value is scaled by 10^scale returned as a Java BigDecimal.

Using MainframeReader to Translate Data Buffers

As an example of using the MainframeReader, class following is a program that translates and displays the fields in the mainframe buffer created above. Our input buffer consists of the binary data:

>     C5848781994040404040D1969585A24040404040001602250C

Listing 6-7 shows the sample program used to process this buffer.

Listing 6-7 Sample Program

>     import java.math.BigDecimal;
>     import com.bea.base.io.MainframeReader;

>     public class ShowBuffer

>     {
>     	public static void main(String[] args) throws Exception
>     	{
>     	String data =
>     		"C5848781994040404040D1969585A24040404040001602250C";
>     	byte[] buffer = buildBinary(data);
>     	MainframeReader mf = new MainframeReader(buffer);
>     	System.out.println(" First Name: " + mf.readPadded(' ', 10));
>     	System.out.println("  Last Name: " + mf.readPadded(' ', 10));
>     	System.out.println("        Age: " + mf.read16bit());
>     	System.out.println("Hourly Rate: " + mf.readPacked(5, 2, 0));
>     	}

>     	private static byte[] buildBinary(String data)
>     	{
>     		byte[] buffer = new byte[data.length() / 2];
>     		for (int i = 0; i < buffer.length; ++i)
>     		{
>     			int msb = hex.indexOf(data.charAt(i * 2));
>     			int lsb = hex.indexOf(data.charAt(i * 2 + 1));
>     			buffer[i] = (byte) (msb << 4 | lsb);
>     		}
>     	return(buffer);
>     	}

>     	private static final String hex = "0123456789ABCDEF";
>     }

When run, the program produces the following output:

>     First Name: Edgar
>     Last Name: Jones
>     Age: 22
>     Hourly Rate: 22.50