Oracle8i Enterprise JavaBeans and CORBA Developer's Guide Release 8.1.5 A64683-01 |
|
This section provides a short introduction to CORBA, and should give you some idea of how CORBA is typically used in the Oracle8i server environment. Providing a complete introduction to CORBA is beyond the scope of this Guide. See the references in "For More Information" for suggested further reading. This first section gives a very high-level overview of CORBA itself.
CORBA stands for Common Object Request Broker Architecture, and it is an acronym that is not self-explanatory. (See "Acronyms".) What is common about CORBA is that it integrates ideas from several of the original proposers. CORBA did not just follow the lead of a single large corporation, and it is very deliberately vendor neutral. The CORBA architecture specifies a software component, a broker, that mediates and directs requests to objects that are distributed across a network (or several networks), that might have been written in a different language from that of the requestor, and that might (and in fact, usually are) running on a completely different hardware architecture from that of the requestor.
You can begin to get an idea of the tremendous advantages of CORBA from the preceding paragraph. CORBA allows your application to tie together components from various sources. Also, and unlike a typical client/server application, a CORBA application is not inherently synchronous. It is not necessarily typical that a CORBA requestor (a client) invokes a method on a server component, and waits for a result. Using asynchronous method invocations, event interfaces, and callbacks from server object to the client ORB, you can construct elaborate applications that link together many interacting objects, and that access one or many data sources and other resources under transactional control. CORBA allows you go beyond the bounds of the traditional client/server application in many imaginative ways.
CORBA is specified and advanced by the Object Management Group (OMG), which is a non-profit and vendor-neutral organization. See "For More Information" to see how to learn more about the OMG.
CORBA achieves its flexibility in several ways:
CORBA provides bindings for many languages, including both non-object languages such as COBOL and C and object-oriented languages such as Smalltalk and Java.
CORBA specifies over 12 services. Most of these are not yet implemented by CORBA ORB vendors.
The remainder of this section introduces some of the essential building blocks of an Oracle8i JServer CORBA application. These include:
Note: The Java code examples used in this chapter are available on line. You can study the complete examples (see Appendix A, "Example Code: CORBA"), compile and run them, and then modify them for your own use. You can of course cut and paste the code from the on-line or PDF files, but it is more convenient to access the examples on disk. If you do not know the location where the example code has been installed from the CD, ask your DBA or system administrator. |
The object request broker, or ORB, is the fundamental part of a CORBA implementation. It is the ORB that makes it possible for a client to send messages to a server, and the server to returns values to the client. The ORB handles all communication between a client and a server object.
The JServer ORB is based on code from Inprise's VisiBroker for Java. The ORB that executes on the server side has been slightly modified from the VisiBroker code, to accommodate the different Oracle8i object location and activation model. The client-side ORB has been changed very little.
In some CORBA implementations, the application programmer and the server object developer must be aware of the details of how the ORB is activated on the client and the server, and include code in their objects to start up the ORBs and activate objects. The Oracle8i ORB, on the other hand, makes these details largely transparent to the application developer. As you will see from the Java code examples later in this chapter, and in Appendix A, it is only in certain circumstances that the developer needs to control the ORB directly. These occur, for example, when coding callback mechanisms, or when there is a need to register transient objects with the basic object adapter.
One of the key factors in the success of CORBA is language independence. CORBA objects written in one language can send requests to objects that were implemented in a different language. Objects implemented in an object-oriented language like Java or Smalltalk can talk to objects that were written in C or COBOL, and vice-versa.
Language independence is achieved through the use of a specification meta-language that defines the interfaces that an object (or a piece of legacy code that is 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 language code. Oracle8i JServer uses the idl2java
compiler from Inprise (see "Miscellaneous Tools"). idl2java
translates your IDL interface specifications into Java classes, that are then compiled by the Java compiler into byte codes that are loaded into the Oracle8i database for execution.
Here is an example of a short IDL file. It is the IDL for the HelloWorld
example (see "helloworld" for the complete example):
module hello { interface Hello { wstring helloWorld(); }; };
The IDL consists of a module, which contains a group of usually related object interfaces. By default, the module name is used by the IDL compiler to name a directory where the IDL compiler puts the Java classes that it generates, and this maps to a Java package.
This module has only a single interface: Hello
. The Hello
interface defines a single operation: helloWorld
. helloWorld
takes no parameters, and returns a wstring
(a wide string, which is mapped to a Java String).
Note: IDL data and exception types, such the wstring shown above, are not specified in this guide. Although some of the IDL to Java bindings are listed in this guide (for example see "IDL Types"), CORBA developers should have access to the OMG specifications for complete information about IDL and IDL types. See "For More Information". |
The module and interface names must be valid Java identifiers, and also 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.
Modules can be nested. For example, an IDL file that specifies
module org { module omg { module CORBA { ... }; ... }; ... };
would map to the Java package hierarchy package org.omg.CORBA
.
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 put 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
These eight Java classes are used by the ORB to invoke a remote object, pass and return parameters, and do various other things supported by the ORB. Note that you can control to some extent the files that get 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 Chapter 6, "Tools".
Each of the eight files generated by the compiler is described briefly below.
Hello |
This is the interface file, that 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(); }
Note that since the file is put in a
The server object developer must implement the methods in the interface. It is typical of the examples in this guide that the implementation class for an interface named |
HelloHolder |
The holder class is used by the application when parameters in the interface operation are of types |
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 LoginServer lserver = LoginServerHelper.narrow (orb.string_to_object (loginIOR));
(Note that when you get an object reference using the JNDI |
_st_Hello |
The generated files that have _st_ prefixed to the interface name are the stub files, or client proxy objects. (
These classes are installed on the client that calls the remote object (the |
_HelloImplBase |
Generated source files of the form
In earlier CORBA implementations, the skeleton files were named |
HelloOperations |
These two classes are used by the server for Tie implementations of server objects. See "Using the CORBA Tie Mechanism" for information about Tie classes. |
_example_Hello |
The
You can copy the example code to the directory where you will implement the |
An IDL interface body contains the following kinds of declarations:
This section gives a very brief description of IDL datatypes, and their mapping to Java datatypes. For more information and for information about IDL types not covered here, see the CORBA specifications and the books cited in "For More Information".
Mapping between IDL basic types and Java primitive types is very straightforward. The mappings are shown in Table . Possible CORBA exceptions that can be raised on conversion are also shown in the table.
The IDL character type char
is an 8-bit type, representing an ISO Latin-1 character. It is mapped 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.
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.
There are two kinds of ordered collections in CORBA: 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 will 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 Java class code that the IDL compiler generates for the DepartmentInfo
class is:
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 to load them into the Oracle8i database when the class is a server object. You should scan the generated .java
files, and make sure that each of them that is required is 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. A good example is "lookup".
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); }; };
Mapping between OMG CORBA system exceptions and their Java form is also quite straightforward. These mappings are shown in Table 3-2.
The Oracle8i Java VM development environment offers the Visigenic (Inprise) Caffeine tools, that let you develop 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, but still have IDL available that can be shipped to customers who are using a CORBA server that does not support Java. This tool generates IDL from Java interface specifications. See Chapter 6, "Tools", for more information about java2iiop
and java2idl
.