Appendix C Creating EAServer 1.1 Java Clients


Write the Java source file

Your source implementation must perform these tasks:

  1. Import packages
  2. Create a stub object instance
  3. Execute component methods
  4. JDBC result-set handling
  5. Handle errors
  6. Destroy the stub instance

Import packages

You must either import the necessary EAServer 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.*
com.sybase.jaguar.stub.jdbc11
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 and regenerate stubs. See "Specifying Java package mappings for IDL modules" for more information.

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 EAServer 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, "EAServer 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, "EAServer 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.

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 EAServer holder classes. Holder classes allow pass-by-reference functionality.

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

Note   JDK 1.0.2 types deprecated The EAServer types provided for JDK 1.0.2 compatibility have been deprecated as they are based on deprecated base Java types. You can use these types, but the client runtime itself requires JDK 1.2 or later.

EAServer 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 display type Mode Java
boolean input, return
inout, output
boolean
BooleanHolder
binary input, return
inout, output
byte[]
BytesHolder
date input, return
inout, output
java.sql.Date
com.sybase.jaguar.util.jdbc11.DateHolder
decimal input, return
inout, output
java.math.BigDecimal
com.sybase.jaguar.util.jdbc11.BigDecimalHolder
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
com.sybase.jaguar.util.jdbc11.BigDecimalHolder
string input, return
inout, output
java.lang.String
StringHolder
time input, return
inout, output
java.sql.Time
com.sybase.jaguar.util.jdbc11.TimeHolder
timestamp input, return
inout, output
java.sql.Timestamp
com.sybase.jaguar.util.jdbc11.TimestampHolder )
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 EAServer versions prior to 2.0, this step was required. In the current version, it does nothing but is provided for backward compatibility. EAServer 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 23, "Sending Result Sets".

EAServer component 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 © 2002 Sybase, Inc. All rights reserved.