Oracle9i CORBA Developer's Guide and Reference
Release 1 (9.0.1)

Part Number A90187-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

2
Getting Started

This chapter introduces the basic procedures for creating CORBA applications for Oracle9i. The emphasis in this chapter is to present the basics for developing an Oracle9i CORBA application. For advanced programming techniques and miscellaneous tips for CORBA applications, see Chapter 5, "Advanced CORBA Programming".

This chapter covers the following topics:

A First CORBA Application

This section introduces the Oracle9i CORBA application development process. It tells you how to write a simple but useful program that runs on a client system, connects to Oracle using IIOP, and invokes a method on a CORBA server object that is activated and runs inside the Oracle9i JVM.

Figure 2-1 CORBA Application Components


Text description of idlcomp.gif follows
Text description of the illustration idlcomp.gif

As Figure 2-1 illustrates, a CORBA application requires that you provide the client implementation, the server interface and implementation, and IDL stubs and skeletons. To create this, perform the following steps:

  1. Design and write the object interfaces in IDL.

  2. Generate stubs, skeletons, and helper and holder support classes.

  3. Write the server object implementations.

  4. Write the client implementation. This code runs outside of the Oracle9i data server on a workstation or PC.

  5. Compile the Java server implementation with the client-side Java compiler. In addition, compile all the Java classes generated by the IDL compiler. Generate a JAR file to contain these classes and any other resource files that are needed.

  6. Compile the client code using the JDK Java compiler.

  7. Load the compiled classes into the Oracle9i database using the loadjava tool and specifying the JAR file as its argument. Make sure to include all generated classes, such as stubs and skeletons. Client stubs are required in the server only when the server object acts as a client to another CORBA object.

  8. Publish a name for the objects that are directly accessible, using the CosNaming service, so that you can access them from the client program.

This chapter uses an employee sample to demonstrate the above steps. The example asks the user for an employee number in the EMP table and returns the employee's last name and current salary. It throws an exception if there is no employee in the database with the given ID number.

Writing Interfaces in IDL

When writing a server application, you must create an Interface Definition Language (IDL) file to define the server's interfaces. An interface is a template that defines a CORBA object. As with any object in an object oriented language, it contains methods and data elements that can be read or set. However, the interface is only a definition and so defines what the interface to an object would be if it existed. In your IDL file, each interface describes an object and the operations clients can perform on that object.


Note:

For a full description of IDL, see "The Interface Definition Language (IDL)"


The IDL for the employee example is called employee.idl, and it contains only a single server-side method: getEmployee. The getEmployee method takes an ID number and queries the database for the employee's name and salary.

This interface defines three things:

The contents of the employee.idl file is as follows:

module employee {

  struct EmployeeInfo {
    wstring name;
    long number;
    double salary; 
  };

  exception SQLError {
    wstring message;
  };

  interface Employee {
    EmployeeInfo getEmployee (in long ID) raises (SQLError);
  };
};

Generating Stubs and Skeletons

Use the idl2java compiler to compile the interface description. As shown in Figure 2-2, the compiler generates the interface, implementation template, helper, and holder classes for the three objects in the IDL file, as well as a stub and skeleton class for the Employee interface. See "Using IDL" for more information about these classes and the Oracle9i Java Tools Reference for more information on the idl2java compiler.


Note:

Because this example does not use the Tie mechanism, you can invoke the compiler with the -no_tie option. Two fewer classes will be generated.  


Figure 2-2 IDL Compilation Generates Support Files


Text description of compile.gif follows
Text description of the illustration compile.gif

Compile the IDL as follows:

% idl2java -no_tie -no_comments employee.idl


Note:

Because developing a CORBA application includes many compilation, loading, and publishing steps, Oracle recommends that if you are working in a command-line oriented environment, always use a makefile or a batch file to control the process. Or, you can use IDE products such as Oracle's JDeveloper to control the process.  


When you compile the employee.idl file, the idl2java tool generates the following files:


_example_Employee.java 



Implementation template for server object. 



Employee.java 



Employee interface definition. 



EmployeeInfo.java 



EmployeeInfo interface definition. 



SQLError.java 



SQLError interface definition. 



_st_Employee.java 



IDL client stub. 



_EmployeeImplBase.java 



IDL server skeleton. 



EmployeeHelper.java 



Helper class for Employee. The most important methods this class provides are the narrow method for typecasting a returned object to be a Employee object, and the id method that returns the interface's identifier. 



EmployeeHolder.java 



Holder class for Employee. The Holder class enables a Java object to pass values back to clients.  



EmployeeInfoHelper.java 



Helper class for EmployeeInfo.  



EmployeeInfoHolder.java 



Holder class for the EmployeeInfo
structure.  



SQLErrorHelper.java 



Helper class for SQLError.  



SQLErrorHolder.java 



Holder class for the SQLError exception.  


Modify the _example_Employee.java file to include your application implementation. First, rename the _example_Employee.java file to a more appropriate name, such as EmployeeImpl.java. Once renamed, modify the file to add your server's implementation. The EmployeeImpl.java file extends the IDL server skeleton, _EmployeeImplBase.java. Add and implement the getEmployee method that is defined in the Employee.java interface definition. Secondly, create the client application that invokes these methods appropriately. "Writing the Server Object Implementation" demonstrates how to create the server implementation of Employee in EmployeeImpl.java.

Writing the Server Object Implementation

An implementation is an instantiation of an interface. That is, the implementation is code that implements all the functions and data elements that were defined in the IDL interface. The following steps describe how to implement the Employee interface:

  1. Modify the EmployeeImpl.java file, which used to be the _example_Employee.java file, to add your server implementation. Notice that the EmployeeImpl extends the IDL-generated skeleton, _EmployeeImplBase.

    As Figure 2-1 illustrates, the _EmployeeImplBase IDL skeleton exists between the ORB and the server application, so any invocation of the server application is performed through it. The skeleton prepares the parameters, calls the server method, and saves any return values or any out or inout parameters.

  2. Implement the getEmployee method to query the database for the employee and return the appropriate name and salary in EmployeeInfo.

    package employeeServer;
    
    import employee.*;
    import java.sql.*;
    
    public class EmployeeImpl extends _EmployeeImplBase {
    
      /*constructor*/
    public EmployeeImpl() { } /*getEmployee method queries database for employee info*/
    public EmployeeInfo getEmployee (int ID) throws SQLError { try { /*create a JDBC connection*/
    Connection conn = new oracle.jdbc.OracleDriver().defaultConnection ();
    /*Create a SQL statement for the database query*/
    PreparedStatement ps = conn.prepareStatement ("select ename, sal from emp where empno = ?"); /*set the employee identifier and execute query. return the result in an EmployeeInfo structure */ try { ps.setInt (1, ID); ResultSet rset = ps.executeQuery (); if (!rset.next ()) throw new SQLError ("no employee with ID " + ID); return new EmployeeInfo (rset.getString (1), ID, rset.getFloat (2)); } finally { ps.close (); } /*If a problem occurs, throw the SQLError exception*/ } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } }

This code uses the JDBC API to perform the database query. The implementation uses a prepared statement to accommodate the variable in the WHERE clause of the query. See the Oracle9i JDBC Developer's Guide and Reference for more about Oracle9i JDBC. You can use SQLJ, instead of JDBC, if your statement is static.

Comparing Oracle9i Server Applications to Other ORB Applications

Most ORB applications must provide a server application that instantiates the server implementation and registers this instance with the CORBA object adapter. However, Oracle9i instantiates the implementation and registers the resulting instance on demand for you. Thus, you do not need to provide code that initializes the ORB, instantiates the implementation, and registers the instance. The only server code that you provide is the actual server implementation. However, your client will not be able to find an active server implementation instance through the ORB, because it is not instantiated until called.

To facilitate this, Oracle9i requires you to publish the implementation object in the Name Service after loading the application into the database. The client retrieves the object from the Name Service through a JNDI lookup. Once retrieved, the client invokes the activate method, which initializes an instance of the object. At this point, the client can invoke methods on the object.

Writing the Client Code

After writing the server object, you must create the client implementation. In order for the server object to be accessed by the client, you must publish the server object in the Oracle9i database. The client code looks up the published name and activates the server object as a by-product of the look up. You can look up any server object either through JNDI or CosNaming. The example below demonstrates the JNDI method for retrieving the server object reference. See "JNDI Connection Basics" for more information on JNDI and CosNaming.

When you perform the JNDI lookup, the ORB on the server side is started and the client is authenticated using the environment properties supplied when the initial context object is created. See "IIOP Security".

To retrieve the object from the Name Service, you must provide the following:

Object name

The object name specifies the complete path name of the published object that you want to look up. For example: /test/myServer.

See "Retrieving the JNDI InitialContext" for further information about the lookup() method.

IIOP Service Name

The service name specifies a service that an IIOP presentation manages, and it represents a database instance. "Accessing CORBA Objects Without JNDI" explains the format of the service URL. Briefly, the service name specifies the following components:

A typical example of a service name is sess_iiop://localhost:2481:ORCL, where sess_iiop is the URL prefix for the service, localhost defaults to the host of the local database, 2481 is the default listener port for IIOP connections, and ORCL is the SID.

Client Authentication Information

You must authenticate yourself to the database each time you connect. The type of authentication information depends on how you want to authenticate--through a username/password combination, or SSL certificates. See "IIOP Security" for more information.

Client Example

The client invokes the getEmployee method through the following steps:

  1. Instantiates and populates a JNDI InitialContext object with the required connect properties, including authentication information. See "JNDI Connection Basics".

  2. Invokes the lookup() method on the initial context, with a URL as a parameter that specifies the service name and the name of the object to be found. The lookup() method returns an object reference to the Employee CORBA server object. See "Using JNDI to Access Bound Objects" for more information.

  3. Using the object reference returned by the lookup() method invokes the getEmployee() method on the object in the server. This method returns an EmployeeInfo class, which is derived from the IDL EmployeeInfo struct. For simplicity, an employee ID number is hard-coded as a parameter of this method invocation.

  4. Prints the values returned by getEmployee() in the EmployeeInfo class.

    import employee.*;
    import oracle.aurora.jndi.sess_iiop.ServiceCtx;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import java.util.Hashtable;
    
    public class Client {
      public static void main (String[] args) throws Exception {
        String serviceURL = "sess_iiop://localhost:2481:ORCL";
        String objectName = "/test/myEmployee";
     
    // Step 1: Populate the JNDI properties with connect and authentication 
    // information Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); env.put (Context.SECURITY_PRINCIPAL, "SCOTT"); env.put (Context.SECURITY_CREDENTIALS, "TIGER"); env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN); Context ic = new InitialContext (env); // Step 2: Lookup the object providing the service URL and object name Employee employee = (Employee)ic.lookup (serviceURL + objectName); // Step 3 (using SCOTT's employee ID number): Invoke getEmployee EmployeeInfo info = employee.getEmployee (7788); // Step 4: Print out the returned values. System.out.println (info.name + " " + info.number + " " + info.salary); } }

When you execute the client code, it prints the following on the client console:

SCOTT 7788 3000.0

Compiling the Java Source

Run the client-side Java byte code compiler, javac, to compile all the Java source that you have created. The Java source includes the client and server object implementations, as well as the Java classes generated by the IDL compiler.

For the Employee example, you compile the following files:

Compile other generated Java files following the dependencies that the Java compiler uses.

Oracle9i JVM supports the Java JDK compiler, releases 1.1.6 or 1.2. Alternatively, you might be able to use other Java compilers, such as a compiler incorporated in an IDE.

Loading the Classes into the Database

CORBA server objects, such as the EmployeeImpl object created for this example, execute inside the Oracle9i database server. Load all your classes into the server--through the loadjava command-line tool--so that they can be activated by the ORB upon demand. In addition, load all dependent classes, such as IDL-generated Holder and Helper classes, and classes the server object uses, such as the EmployeeInfo class of this example.

Use the loadjava tool to load each of the server classes into the Oracle9i database. For the Employee example, issue the loadjava command in the following way:

% loadjava -resolve -user scott/tiger 
   employee/Employee.class employee/EmployeeHolder.class 
   employee/EmployeeHelper.class employee/EmployeeInfo.class 
   employee/EmployeeInfoHolder.class employee/EmployeeInfoHelper.class 
   employee/SQLError.class employee/SQLErrorHolder.class 
   employee/SQLErrorHelper.class employee/_st_Employee.class 
   employee/_EmployeeImplBase.class employeeServer/EmployeeImpl.class


Note:

Do not load any client implementation classes or any other classes not used on the server side. 


It is sometimes convenient to combine the server classes into a JAR file and use that file as the argument to the loadjava command. In this example, you could issue the command:

% jar -cf0 myJar.jar employee/Employee.class employee/EmployeeHolder.class \
   employee/EmployeeHelper.class employee/EmployeeInfo.class \
   employee/EmployeeInfoHolder.class employee/EmployeeInfoHelper.class \
   employee/SQLError.class employee/SQLErrorHolder.class \
   employee/SQLErrorHelper.class employee/_st_Employee.class \
   employee/_EmployeeImplBase.class employeeServer/EmployeeImpl.class

Then, execute the loadjava command as follows:

% loadjava -resolve -user scott/tiger myJar.jar

Publishing the Object Name

The final step in preparing the application is to publish the name of the CORBA server object implementation in the Oracle9i database. See "The Name Space" and the publish section in the Oracle9i Java Tools Reference for information about publishing objects.

For the example in this section, publish the server object, using the publish command, as follows:

% publish -republish -user scott -password tiger -schema scott 
    -service sess_iiop://localhost:2481:ORCL 
    /test/myEmployee employeeServer.EmployeeImpl employee.EmployeeHelper

This command specifies the following:

Running the Example

To run this example, execute the client class using the client-side JVM. For this example, you must set the CLASSPATH for the java command to include:

If you are using JDBC, include one of the following JAR files:

If you are using SSL, include one of the following JAR files:

You can locate these libraries in the lib and jlib directories, under the Oracle home location in your installation.

The following invocation of the JDK java command runs this example.


Note:

The UNIX shell variable $ORACLE_HOME might be represented as %ORACLE_HOME% on Windows NT. The JDK_HOME is the installation location of the Java Development Kit (JDK). 


% java -classpath .:$(ORACLE_HOME)/lib/aurora_client.jar			|
:$(ORACLE_HOME/lib/mts.jar |
:$(ORACLE_HOME)/jdbc/lib/classes111.zip: |
$(ORACLE_HOME)/sqlj/lib/translator.zip:$(ORACLE_HOME)/lib/vbjorb.jar: |
$(ORACLE_HOME)/lib/vbjapp.jar:$(JDK_HOME)/lib/classes.zip |
Client |
sess_iiop://localhost:2481:ORCL |
/test/myEmployee |
scott tiger

This example assumes that you invoke the client with the following arguments on the command line:

The Interface Definition Language (IDL)

CORBA provides language independence: CORBA objects written in one language can send requests to objects implemented in a different language. Objects implemented in an object-oriented language such as Java or Smalltalk can talk to objects written in C or COBOL, and the converse.

CORBA achieves language independence through the use of a specification meta-language that defines the interfaces that an object--or a piece of legacy code wrappered to look like an object--presents to the outside world. As in any object-oriented system, a CORBA object can have its own private data and its own private methods. The specification of the public data and methods is the interface that the object presents to the outside world.

IDL is the language that CORBA uses to specify its objects. You do not write procedural code in IDL--its only use is to specify data, methods, and exceptions.

Each CORBA vendor supplies a compiler that translates IDL specifications into a specific language. Oracle9i uses the idl2java compiler from Inprise. The idl2java compiler translates your IDL interface specifications into Java classes. See the Oracle9i Java Tools Reference for more information on this tool.


Note:

The idl2java compiler accepts only ASCII characters. Do not use ISO Latin-1 or other non-ASCII globalization characters in IDL files. 


Using IDL

The following example demonstrates the IDL for the HelloWorld example. See "Basic Example" for the complete example.

module hello {
  interface Hello {
    wstring helloWorld();
  };
};

IDL consists of a module, which contains a group of related object interfaces. The IDL compiler uses the module name to name a directory where the Java classes are placed after generation. In addition, the module name is used to name the Java package for the resulting classes.

This module defines a single interface: Hello. The Hello interface defines a single operation: helloWorld, which takes no parameters and returns a wstring (a wide string, which is mapped to a Java String).


Note:

This guide does not specify IDL data and exception types, such the wstring shown in the preceding example. Some of the IDL to Java bindings are listed in this guide (for example, see "IDL Types"); however, CORBA developers should refer to the OMG specification for complete information about IDL and IDL types.  


The module and interface names must be valid Java identifiers and valid file names for your operating system. When naming interfaces and modules, remember that both Java and CORBA objects are portable, and that some operating systems are case sensitive and some are not, so be sure to keep names distinct in your project.

Nested Modules

You can nest modules. For example, an IDL file that specifies the following modules maps to the Java package hierarchy package org.omg.CORBA.

module org {
  module omg {
     module CORBA {
       ...
     };
    ...
  };
   ...
};

Running the IDL Compiler

Assume that the HelloWorld IDL is saved in a file called hello.idl. When you run idl2java to compile the hello module, eight Java class files are generated and are placed in a subdirectory named hello, in the same directory as the IDL file:

% idl2java hello.idl
Traversing hello.idl
Creating: hello/Hello.java
Creating: hello/HelloHolder.java
Creating: hello/HelloHelper.java
Creating: hello/_st_Hello.java
Creating: hello/_HelloImplBase.java
Creating: hello/HelloOperations.java
Creating: hello/_tie_Hello.java
Creating: hello/_example_Hello.java

The ORB uses these Java classes to invoke a remote object, pass and return parameters, and perform other functions. You can control the files that are generated, where they are put, and other aspects of IDL compiling--such as whether the IDL compiler generates comments in the Java files. See the complete description of the idl2java compiler in the Oracle9i Java Tools Reference.

The following describes each of the files generated:

Hello

This specifies, in Java, what the interface to a Hello object looks like. In this case, the interface is:

package hello;
public interface Hello extends org.omg.CORBA.Object {
  public java.lang.String helloWorld();
}

Because the file is put in a hello directory, it takes the package spec from that name. All CORBA basic interface classes subclass, directly or indirectly, the following:
org.omg.CORBA.Object.

You must implement the methods in the interface. It is recommended that you name the implementation class for the hello.java interface helloImpl, but this naming convention is not a requirement.

HelloHolder

The application uses the holder class when parameters in the interface operation are of the types out or inout. Because the ORB passes Java parameters by value, special holder classes are necessary to provide for parameter return values.

HelloHelper

The helper classes contain methods that read and write the object to a stream, and cast the object to and from the type of the base class. For example, the helper class has a narrow() method that is used to cast an object to the appropriate type, as in the following code:

    LoginServer lserver = LoginServerHelper.narrow
          (orb.string_to_object (loginIOR));

Note that when you get an object reference using the JNDI InitialContext lookup() method, you do not have to call the helper narrow() method--the ORB calls it automatically for you.

_st_Hello

The generated files that have _st_ prefixed to the interface name are the stub files or client proxy objects. (_st_ is a VisiBroker-specific prefix.)

These classes are installed on the client that calls the remote object. In effect, when a client calls a method on the remote object, it is really calling into the stub, which then performs the operations necessary to perform a remote method invocation. For example, it must marshall parameter data for transport to the remote host.

_HelloImplBase

Generated source files of the form _<interfaceName>ImplBase are the skeleton files. A skeleton file is installed on the server and communicates with the stub file on the client, in that it receives the message on the ORB from the client and upcalls to the server. The skeleton file also returns parameters and return values to the client.

HelloOperations
_tie_Hello

The server uses these two classes for Tie implementations of server objects. See "Using the CORBA Tie Mechanism" for information about Tie classes.

_example_Hello

The _example_<interfaceName> class provides you with a template for your server object implementation. You can copy the example code to the directory where you will implement the Hello server object, rename it, and implement the methods. HelloImpl.java is used in the examples in this guide.

IDL Interface Body

An IDL interface body contains the following kinds of declarations:

types

type definitions

exceptions

exception structures exported by the interface

attributes

any associated attributes exported by the interface

operations

methods supported by the interface

IDL Types

This section gives a brief description of IDL datatypes and their mapping to Java datatypes. For more information about IDL types that are not covered here, see the CORBA specifications and the books cited in "For More Information".

Basic Types

The mapping between IDL basic types and Java primitive types is straightforward. Table 2-1 shows the mappings, as well as possible CORBA exceptions that can be raised on conversion.

Table 2-1 IDL to Java Datatype Mappings  
CORBA IDL Datatype  Java Datatype  Exception 

boolean 

boolean 

 

char 

char 

CORBA::DATA_CONVERSION 

wchar 

char 

 

octet 

byte 

 

string 

java.lang.String 

CORBA::MARSHAL 

 

 

CORBA::DATA_CONVERSION 

wstring 

java.lang.String 

CORBA::MARSHAL 

short 

short 

 

unsigned short 

short 

 

long 

int 

 

unsigned long 

int 

 

long long 

long 

 

unsigned long long 

long 

 

float 

float 

 

double 

double 

 

The IDL character type char is an 8-bit type, representing an ISO Latin-1 character that maps to the Java char type, which is a 16-bit unsigned element representing a Unicode character. On parameter marshalling, if a Java char cannot be mapped to an IDL char, a CORBA DATA_CONVERSION exception is thrown.

The IDL string type contains IDL chars. On conversion between Java String, and IDL string, a CORBA DATA_CONVERSION can be thrown. Conversions between Java strings and bounded IDL string and wstring can throw a CORBA MARSHALS exception if the Java String is too large to fit in the IDL string.

Constructed Types

Perhaps the most useful IDL constructed (aggregate) type for the Java developer is the struct. The IDL compiler converts IDL structs to Java classes. For example, the IDL specification:

module employee {
  struct EmployeeInfo {
    long empno;
    wstring ename;
    double sal; 
  };
  ...

causes the IDL compiler to generate a separate Java source file for an EmployeeInfo class. It looks like this:

package employee;
final public class EmployeeInfo {
  public int empno;
  public java.lang.String ename;
  public double sal;
  public EmployeeInfo() {
  }
  public EmployeeInfo(
    int empno,
    java.lang.String ename,
    double sal
  ) {
    this.empno = empno;
    this.ename = ename;
    this.sal = sal;
  }
 ...

The class contains a public constructor with parameters for each of the fields in the struct. The field values are saved in instance variables when the object is constructed. Typically, these are passed by value to CORBA objects.

Collections

The two types of ordered collections in CORBA are sequences and arrays. An IDL sequence maps to a Java array with the same name. An IDL array is a multidimensional aggregate, whose size in each dimension must be established at compile time.

The ORB throws a CORBA MARSHAL exception at runtime if sequence or array bounds are exceeded when Java data is converted to sequences or arrays.

IDL also generates a holder class for a sequence. The holder class name is the sequence's mapped Java class name with Holder appended to it.

The following IDL code shows how you can use a sequence of structs to represent information about employees within a department:

module employee {
  struct EmployeeInfo {
    long empno;
    wstring ename;
    double sal; 
  };

  typedef sequence <EmployeeInfo> employeeInfos;

  struct DepartmentInfo {
    long deptno;
    wstring dname;
    wstring loc;
    EmployeeInfos employees;
  };

The following code is the Java class code that the IDL compiler generates for the DepartmentInfo class:

package employee;
final public class DepartmentInfo {
  public int deptno;
  public java.lang.String dname;
  public java.lang.String loc;
  public employee.EmployeeInfo[] employees;
  public DepartmentInfo() {
  }
  public DepartmentInfo(
    int deptno,
    java.lang.String dname,
    java.lang.String loc,
    employee.EmployeeInfo[] employees
  ) {
    this.deptno = deptno;
    this.dname = dname;
    this.loc = loc;
    this.employees = employees;
  }

Notice that the sequence employeeInfos is generated as a Java array EmployeeInfo[].

Specify an array in IDL, as follows:

const long ArrayBound = 12;
typedef long larray[ArrayBound];

The IDL compiler generates this as:

public int[] larray;

When you use IDL constructed and aggregate types in your application, you must make sure to compile the generated .java files and load them into the Oracle9i database when the class is a server object. You should scan the generated .java files and make sure that all required files are compiled and loaded. Study the Makefile (UNIX) or the makeit.bat batch file (Windows NT) of CORBA examples that define these types to see how the set of IDL-generated classes is compiled and loaded into the data server.

Exceptions

You can create new user exception classes in IDL with the exception key word. For example:

  exception SQLError {
    wstring message;
  };

The IDL can declare that operations raise user-defined exceptions. For example:

interface employee {
  attribute name;
  exception invalidID {
    wstring reason;
  };
  ...
  wstring getEmp(long ID)
    raises(invalidID);
  };
};

CORBA System Exceptions

Mapping between OMG CORBA system exceptions and their Java form is straightforward. Table 2-2 contains these mappings:

Table 2-2 CORBA and Java Exceptions
OMG CORBA Exception  Java Exception 

CORBA::PERSIST_STORE 

org.omg.CORBA.PERSIST_STORE 

CORBA::BAD_INV_ORDER 

org.omg.CORBA.BAD_INV_ORDER 

CORBA::TRANSIENT 

org.omg.CORBA.TRANSIENT 

CORBA::FREE_MEM 

org.omg.CORBA.FREE_MEM 

CORBA::INV_IDENT 

org.omg.CORBA.INV_IDENT 

CORBA::INV_FLAG  

org.omg.CORBA.INV_FLAG 

CORBA::INTF_REPOS 

org.omg.CORBA.INTF_REPOS 

CORBA::BAD_CONTEXT  

org.omg.CORBA.BAD_CONTEXT 

CORBA::OBJ_ADAPTER 

org.omg.CORBA.OBJ_ADAPTER 

CORBA::DATA_CONVERSION 

org.omg.CORBA.DATA_CONVERSION 

CORBA::OBJECT_NOT_EXIST 

org.omg.CORBA.OBJECT_NOT_EXIST 

CORBA::TRANSACTIONREQUIRED 

org.omg.CORBA.TRANSACTIONREQUIRED 

CORBA::TRANSACTIONROLLEDBACK 

org.omg.CORBA.TRANSACTIONROLLEDBACK 

CORBA::INVALIDTRANSACTION 

org.omg.CORBA.INVALIDTRANSACTION 

Getting by Without IDL

The Oracle9i JVM development environment offers the Inprise Caffeine tools, which enable development of pure Java distributed applications that follow the CORBA model. You can write your interface specifications in Java and use the java2iiop tool to generate CORBA-compatible Java stubs and skeletons.

Developers can also use the java2idl tool to code in pure Java, and generate the IDL required for customers who are using a CORBA server that does not support Java. This tool generates IDL from Java interface specifications.

See the Oracle9i Java Tools Reference for more information about java2iiop and java2idl.

Activating ORBs and Server Objects

A CORBA application requires that an ORB be active on both the client system and the system running the server. This section presents more information about how the ORB is activated.

Client Side

The client-side ORB is normally initialized in one of two ways:

Server Side

The presentation that manages IIOP requests starts the ORB on the server when the session is created. If you want to retrieve the ORB instance, use the CORBA oracle.aurora.jndi.orb_dep.Orb.init method. See "Oracle9i ORB Interface" for a full explanation of this method.

About Object Activation

Objects are activated on demand. When a client looks up an object, the ORB loads the object into memory and caches it. To activate the object, the ORB looks up the class by the fully-qualified class name under which the object was published. The class name is resolved in the schema defined at publication time, rather than the caller's schema. See the description of the command-line tool publish in the Oracle9i Java Tools Reference for more information.

When the class is located, the ORB creates a new instance of the class, using newInstance(). For this reason, the no-argument constructor of a persistent object class must be public. If the class implements the oracle.aurora.AuroraServices.ActivatableObject interface (as determined by the Java reflection API), then the _initializeAuroraObject()message is sent to the instance. See "Using the CORBA Tie Mechanism" for an example that requires _initializeAuroraObject().

There is no need for the server implementation to register its published objects with the object adapter using a boa.obj_is_ready() call--the Oracle9i ORB performs this automatically.

You register transient objects generated by other objects, such as persistent published objects, with the BOA using obj_is_ready(). For an example, see the factory demo in the $ORACLE_HOME/javavm/demo/corba/basic/factory directory of the product CD.

CORBA Interceptors

Visibroker enables you to implement interceptors. You can find instructions on how to create them in the Visibroker documentation.

Debugging Techniques

Until Java IDEs and JVMs support remote debugging, you can adopt several techniques for debugging your CORBA client and server code.

  1. Use JDeveloper for debugging any Java applications. JDeveloper has provided a user interface that utilizes the Oracle9i debugging facilities. You can successfully debug an object loaded into the database by using JDeveloper's debugger. See the JDeveloper documentation for instructions.

  2. Use a prepublished DebugAgent object for debugging objects executing on a server. See "Using a Debug Agent for Debugging Server Applications" for more information.

  3. Perform standalone ORB debugging, using one machine and ORB tracing.

    Debug by placing both the client and server in a single address space in a single process. Use of an IDE for client or server debugging is optional, though highly desirable.

  4. Use Oracle9i trace files.

    In the client, the output of System.out.println() goes to the screen. However, in the Oracle9i ORB, all messages are directed to the server trace files. The directory for trace files is a parameter specified in the database initialization file. Assuming a default install of the product into a directory symbolically named $ORACLE_HOME, the trace file appears, as follows:

    ${ORACLE_HOME}/admin/<SID>/bdump/ORCL_s000x_xxx.trc
    
    

    where ORCL is the SID, and x_xxx represents a process ID number. Do not delete trace files after the Oracle instance has been started--if you do, no output will be written to a trace file. If you do delete trace files, stop and then restart the server.

  5. Use a single Oracle MTS server.

    For debugging only, set the MTS_SERVERS parameter in your INITSID.ORA file to MTS_SERVERS = 1, and set the MTS_MAX_SERVERS to 1. Having multiple MTS servers active means that a trace file is opened for each server process, and, thus, the messages get spread out over several trace files, as objects get activated in more than one session.

  6. Use the printback example to redirect System.out. This example is available in the
    $ORACLE_HOME/javavm/demo/examples/corba/basic/printback directory.

Using a Debug Agent for Debugging Server Applications

The procedure for setting up your debugging environment is discussed fully in the Oracle9i Java Developer's Guide. However, it discusses starting the debug agent using a DBMS_JAVA procedures. Within a CORBA application, you can start, stop, and restart the debug agent using the oracle.aurora.debug.DebugAgent class methods. These methods perform exactly as their DBMS_JAVA counterparts perform.

public void start( java.lang.String host, int port, long timeout_seconds) 
throws DebugAgentError public void stop() throws DebugAgentError public void restart(long timeout) throws DebugAgentError

Example 2-1 Starting a DebugAgent on the Server

The following example shows how to debug an object that exists on the server. First, you need to start a debug proxy through the debugproxy command-line tool. This example informs the debugproxy to start up the jdb debugger when contacted by the debug agent.

Once you execute this command, start your client, which will lookup the intended object to be debugged, lookup the DebugAgent that is prepublished as "/etc/debugagent", and start up the DebugAgent.

Once the DebugAgent starts, the debugproxy starts up the jdb debugger and allows you to set your breakpoints. Since you have a specified amount of time before the DebugAgent times out, the first thing you should do is suspend all threads. Then, set all of your breakpoints before resuming. This suspends the timeout until you are ready to execute.


Text description of corba2.gif follows
Text description of the illustration corba2.gif


Go to previous page Go to next page
Oracle
Copyright © 1996-2001, Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback