Appendix C Creating Jaguar 1.1 Java Clients
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:
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.
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:
JProperties jprops = new JProperties();
// Specify the protocol. See the JProperties documentation for
// more information.
jprops.setProtocol("iiop");
// Connection username is "guest"
jprops.setUserName("guest");
// Connection password is also "guest"
jprops.setPassword("guest");
// Jaguar server runs on host "aakash"
jprops.setMachineName("aakash");
// The port number at which the Jaguar server listens
// for IIOP requests. In Jaguar Manager, this port is
// specified in the server's IIOP listener.
//
// A server may be configured to support multiple ports
// with different security profiles. Choose the port that
// matches the desired security level.
//
// If connecting to a secure port, specify "iiops" when
// calling setProtocol().
//
jprops.setPortNumber("9000");
// Jaguar package name is TPackage1
jprops.setPackageName("TPackage1");
// Jaguar component name is TCComponent1
jprops.setComponentName("TCComponent1");
// Name of the Java package that contains the stub class.
jprops.setStubPackageName("TPackage.TCComponent");
// createInstance returns the stub object. You must
// cast the returned object to the type of the generated
// stub class.
comp = (TCComponent1)
CommunicationManager.createInstance(jprops);
The createInstance(String, Class) reference page in the Jaguar CTS API Reference has an example that shows how to call that method.
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.
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.
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.
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();
}
Call the getMessage() method to retrieve a text description of the error.
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.
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:
When a method returns row results, the values of output parameters are not accurate until all of the row results have been processed and getInOutParams() has been called.
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. |