Appendix C Creating Jaguar 1.1 Java Clients


Write the Java applet or application

This section describes how to write Java applets or applications for Jaguar.

To write Java class files for a Java client that executes methods on components, write the code for these tasks in your Java class files:

  1. Import packages - Import Java packages that include the component Java stub class and Java interface that define the methods required to create component objects and invoke methods.
  2. Create a stub object instance - Before executing methods on a component, the component must be instantiated on the Jaguar server, the component Java stub class and interface must be instantiated on the client, and the Java client must retrieve a reference to the instantiated component. Instantiating a component means creating an instance or object of the component.
  3. Execute component methods - Execute methods on the component object reference through the methods in the component Java stub class or interface.
  4. JDBC result-set handling - You must use the Jaguar result set API to process result sets.
  5. Handle errors - Use the try-catch exception-handling technique to respond to errors.
  6. Destroy the stub instance - After all operations have been completed on the component object, you can call destroy on the stub object. In Jaguar versions prior to 2.0, this step was required. In the current release, it does nothing but is provided for backward compatibility.

Import packages

You must either import the necessary Jaguar package names into your client source files or use fully-qualified object names in your source file. Most programmers use import statements rather than fully-qualified names because the resulting code is more readable.

Import the following packages:

com.sybase.jaguar.util.*
com.sybase.jaguar.beans.enterprise.*
stub_package_name.*

where:

stub_package_name is the package name for the stubs that are required to invoke your components. By default, stubs are generated in a Java package that matches the name of the module that contains the component's interface; you can override the default package when you generate stubs. See "Java packages" for more information.

You must also import one of these packages:

To retrieve result sets from components, the Java client must import the packages as shown in the table, Result set packages used by Jaguar 1.1 clients.

Result set packages used by Jaguar 1.1 clients

JDK version

Package import statement

1.1

import java.sql.*;
import java.math.*;
import com.sybase.jaguar.util.jdbc11.*;

1.0.2

import jdbc.sql.*;
import jdbc.math.*;
import com.sybase.jaguar.util.jdbc102.*;

Create a stub object instance

Use the createInstance(String, Class) method or the createInstance(Properties) method to instantiate a stub object. createInstance(String, Class) requires a URL as a parameter; the URL contains details about the component to be instantiated. createInstance(Properties) requires an initialized JProperties object; JProperties provides methods that you call to specify details about the component to be instantiated. Either of these methods performs the following actions:

The createInstance(String, Class) reference page in the Jaguar CTS API Reference has an example that shows how to call that method.

Execute component methods

To execute a component method, execute the corresponding method in the stub interface. Each stub method has a signature that is determined by the parameters specified for the method in Jaguar Manager. Datatypes used in a component method signature are mapped to Java objects or primitive types, as shown in the table, "Jaguar 1.1 client parameter datatypes".

If the method uses a parameter to return a value to the client from the component, make sure you define the parameter with the datatype that corresponds to an inout argument mode.

In this example, the getname component method is executed on the employeeintfobj stub interface. name is an inout parameter that must be defined with the StringHolder wrapper class so the name value can be passed by reference.

StringHolder name = new StringHolder();
employeeintfobj.getname(name);

If a method does not return result sets, the values of inout parameters are available immediately after the method returns. However, when methods return result sets, you must first retrieve the result rows, then the inout parameter values. See "JDBC result-set handling" for more information.

Supported Java datatypes

These supported datatypes are only informational. The Java stub class contains the method signatures, which are all you need to execute component methods.The table, "Jaguar 1.1 client parameter datatypes", lists the Java object and primitive types that match the datatypes used to define return codes or parameters in component methods, and lists the available types for Java method parameters. The left column lists the datatype name as displayed by Jaguar Manager, the middle column lists the argument mode, and the right column lists the corresponding Java object and primitive type used to define the parameter. If the Java object and primitive type is different between JDK 1.0.2 and JDK 1.1, then the version is noted in parentheses.

Parameters that use the input argument type map to base Java objects or primitive types. The input argument mode means "pass by value": the method cannot return an updated parameter value. The inout argument mode means "pass by reference." Parameters that use the inout argument mode map to Jaguar holder classes. Holder classes allow pass-by-reference functionality.

See the jaguar.util.<object>Holder class in the Jaguar CTS API Reference for documentation of the Jaguar holder classes.

Jaguar 1.1 client parameter datatypes

The following table lists type names displayed in Jaguar Manager, and for each type name, the matching Java types for input, return, and inout parameters.

Jaguar Manager

Mode

Java

boolean

input, return
inout, output

boolean
BooleanHolder

binary

input, return
inout, output

byte[]
BytesHolder

date

input, return

inout, output

java.sql.Date (JDK 1.1)
jdbc.sql.Date (JDK 1.0.2)
com.sybase.jaguar.util.jdbc11.DateHolder
(JDK 1.1)
com.sybase.jaguar.util.jdbc102.DateHolder
(JDK 1.0.2)

decimal

input, return

inout, output

java.math.BigDecimal (JDK 1.1)
jdbc.math.BigDecimal (JDK 1.0.2)
com.sybase.jaguar.util.jdbc11.BigDecimalHolder (JDK 1.1)
com.sybase.jaguar.util.jdbc102.BigDecimalHolder (JDK 1.0.2)

double

input, return
inout, output

double
DoubleHolder

float

input, return
inout, output

float
FloatHolder

integer<16>

input, return
inout, output

short
ShortHolder

integer<32>

input, return
inout, output

int
IntegerHolder

integer<64>

input, return
inout, output

long
LongHolder

money

input, return

inout, output

java.math.BigDecimal (JDK 1.1)
jdbc.math.BigDecimal (JDK 1.0.2)
com.sybase.jaguar.util.jdbc11.BigDecimalHolder
(JDK 1.1)
com.sybase.jaguar.util.jdbc102.BigDecimalHolder
(JDK 1.0.2)

string

input, return
inout, output

java.lang.String
StringHolder

time

input, return

inout, output

java.sql.Time (JDK 1.1)
jdbc.sql.Time (JDK 1.0.2)
com.sybase.jaguar.util.jdbc11.TimeHolder
(JDK 1.1)
com.sybase.jaguar.util.jdbc102.TimeHolder
(JDK 1.0.2)

timestamp

input, return

inout, output

java.sql.Timestamp (JDK 1.1)
jdbc.sql.Timestamp (JDK 1.0.2)
com.sybase.jaguar.util.jdbc11.TimestampHolder
(JDK 1.1)
com.sybase.jaguar.util.jdbc102.TimestampHolder
(JDK 1.0.2)

WARNING!

Null parameter values are not supported for input or inout parameters. Use an output parameter instead. For input parameters that extend java.lang.Object, you must pass an initialized object of the indicated type. When using holder objects to pass inout parameters, you must set the holder object's value field to a valid object reference or use the holder constructor that takes an initial value.

Handle errors

The createInstance methods throw exceptions of the EnterpriseBeanException class. The generated stub methods throw JException if the method call fails on the server or in response to internal errors in the stub itself. The stub methods also throw JException if an ActiveX or Java component returns with an exception, or if a C component calls the JagSendMsg routine.

In this example, the code catches EnterpriseBeanException and JException and prints the stack trace and a message to standard output.

StringHolder name = new StringHolder();
String EmpName = new String();

try {
String URL =
"ejb:jdbc//jagserv:9000:Guest:Guest:Company/Company/Employee";
Employee employeeobj = (Employee)
CommunicationManager.createInstance (URL, null);

} catch (EnterpriseBeanException be) {
System.out.println(be.toString());
be.printStackTrace();
}
try {
EmpName = employeeintfobj.getname(name);
} catch (JException je) {
System.out.println(je.toString());
be.printStackTrace();
}

Exception handling with the JException class

Call the getMessage() method to retrieve a text description of the error.

Destroy the stub instance

After all operations have been completed on the component object, you can call destroy on the stub object. In Jaguar versions prior to 2.0, this step was required. In the current version, it does nothing but is provided for backward compatibility. The Jaguar server determines when to destroy the server component instance based on the component's implementation and properties.

JDBC result-set handling

This section describes how to code the client to retrieve result sets from a component. For information about how to code the component to return result sets to the client, see Chapter 27, "Sending Result Sets".

Jaguar methods can return one or more sets of row results. Client applications receive the rows as a java.sql.ResultSet object. When a method returns row results, all of the result sets must be processed before output parameter values can be fetched. (This constraint is due to the order in which row results and updated parameter values arrive over the connection; row results must be read before parameter values can be read.) In addition, output parameters are not available if an exception is caught while processing results.

Stub classes inherit the following JJDBCStub methods for handling row results:

The following code fragment demonstrates how these methods are used after a method call:

try {
// Call the method.
IntegerHolder ih_number = new IntegerHolder();
stock.listTicker(ih_number);

// Retrieve the result sets returned by the method.
do {
rs = stock.getResultSet();

// Retrieve the metadata; we need the number of columns.
ResultSetMetaData rsmd = rs.getMetaData();
int numColumns = rsmd.getColumnCount();
// Print or don't print column names as desired
... GUI code deleted ...
      // Fetch and print rows.
for (int rowNum = 1; rs.next(); rowNum++)
{
// Fill a StringBuffer with the column values
rowText = new StringBuffer("");
for (int colNum = 1; colNum <= numColumns; colNum++)
{
rowText.append(rs.getString(colNum));
if (colNum != numColumns)
{
rowText.append("\t");
}
}
// Print the StringBuffer containing the column values
... GUI code deleted ...
}

} while (stock.getMoreResults() == true);

// Call stock.getInOutParams() to set output values
// of INOUT parameters
stock.getInOutParams();
}
catch (Exception e) {
if (e instanceof JException || e instanceof SQLException)
{
System.err.println("JException: " + e.getMessage());
}
else
{
System.err.println("Unexpected exception: "
+ e.getMessage());
e.printStackTrace();
}
}

Note that JDBC returns column names in the first retrieved row if your code does not call the ResultSet.getMetaData() method. Call the ResultSet.next() method to discard the column names before retrieving the data rows if you do not call ResultSet.getMetaData() and you do not need to display the column names.

When calling the getMoreResults() method, you must handle result sets using the DO-WHILE style as opposed to WHILE-DO style. For example, you could write the following method to get multiple result sets for the stock component:

    do 
{
rs = stock.getResultSet();
if (rs == null)
{
break;
}
// Loop over this Result set and retrieve
// each row and process as desired.
}
while (stock.getMoreResults() == true);

If you use the WHILE-DO style, the execution path never enters the loop, since the condition evaluates to false as the following example demonstrates:

    while (stock.getMoreResults() == true);

{
// Code never executed
}

 


Copyright © 2000 Sybase, Inc. All rights reserved.