Oracle8i Enterprise JavaBeans and CORBA Developer's Guide Release 8.1.5 A64683-01 |
|
This section introduces the JServer 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 an Oracle8i Java VM.
This section addresses only the purely mechanical aspects of the development process. Application developers know that for large-scale applications the design is a crucially important step. See "For More Information" for references to documents on CORBA design.
The CORBA application development process has seven phases:
loadjava
tool and specifying the JAR file as its argument. Make sure to include all generated classes, such as stubs and skeletons. (Stubs are required in the server when the server object acts as a client to another CORBA object.)
The remainder of this section describes these steps in more detail, with IDL and Java code examples to illustrate the coding steps.
The first sample application simply asks the user for an employee number in the famous EMP table, and returns the employee's last name and current salary, or throws an exception if there is no employee in the database with that ID number.
From the description above, it is apparent that the application requires only a single server-side object: some code that takes an ID number and queries the database for the other information about the employee.
So the interface requires three things:
The example defines an operation called query
to get the information, uses an IDL struct
to return the information, and defines an exception called SQLError
to signal that no employee was found. Here is the IDL code:
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in long ID) raises (SQLError); }; };
This code specifies the three things listed above: a struct, EmployeeInfo
, an operation or method, getEmployee()
, and the exception, SQLError
.
Use the idl2java
compiler to compile the interface description. Since there is no use of the Tie mechanism in this example, you can invoke the compiler with the -no_tie
option. This means that two fewer classes are generated. The compiler does generate interface, helper, and holder classes for the three objects in the IDL file, as well as a stub and skeleton class for the Employee
interface. (The 12th class is the example for the interface. See "Using IDL" for more information about these classes.)
Compile the IDL as follows:
% idl2java -no_tie -no_comments employee.idl
For this example, you must implement the Employee
interface. The _example_Employee.java
file that the IDL compiler generates can provide a basis for the implementation. Here is the complete code that implements the interface:
package employeeServer; import employee.*; import java.sql.*; public class EmployeeImpl extends _EmployeeImplBase { public EmployeeImpl() { } public EmployeeInfo getEmployee (int ID) throws SQLError { try { Connection conn = new oracle.jdbc.driver.OracleDriver().defaultConnection (); PreparedStatement ps = conn.prepareStatement ("select ename, sal from emp where empno = ?"); 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 (); } } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } }
This code uses the JDBC API to perform the query. Notice the use of a prepared statement to accommodate the variable in the WHERE clause of the query. See the for more about Oracle8i JDBC. Also notice that when a JDBC SQLException
is caught, the IDL-defined SQLError
is thrown back to the client.
To access the server object you must be able to refer to it by name. In step 7 of this process, you will publish the server object in the Oracle8i database. The client code looks up the published name, and activates the server object as a by-product of the look up. There are a number of other operations that go on when code such as that listed below looks up a published object. For example, 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 "Authentication".
After getting parameters such as the name of the object to look up, an IIOP service name, and some authentication information like the database username and password, the client code performs the following four steps:
InitialContext
object with the required connect properties. See "About JNDI".
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. lookup()
returns an object reference to the Employee
CORBA server object. See "Looking Up an Object" for more information.
lookup()
method, invokes the getEmployee()
method on the object in the server. This method returns an EmployeeInfo
class (derived from the IDL EmployeeInfo
struct). For simplicity an employee ID number is hard-coded as a parameter of this method invocation.
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: 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: Employee employee = (Employee)ic.lookup (serviceURL + objectName); // Step 3 (using SCOTT's employee ID number): EmployeeInfo info = employee.getEmployee (7788); // Step 4: System.out.println (info.name + " " + info.number + " " + info.salary); } }
When the client code runs, it should print the line
SCOTT 7788 3000.0
on the client system console.
You run the client-side Java byte code compiler to compile all the Java source that you have created, including the client and server object implementation that you wrote as well as the Java sources for the classes that were generated by the IDL compiler.
For the example shown above, you must compile the following files:
employee/Employee.java
employee/EmployeeHolder.java
employee/EmployeeInfoHolder.java
employee/EmployeeHelper.java
employee/SQLErrorHolder.java
employee/_EmployeeImplBase.java
EmployeeImpl.java
Client.java
Other generated Java files are compiled following the dependencies that the Java compiler uses.
Oracle8i JServer supports the Java JDK compiler, release 1.1.6. You might be able to use other Java compilers, such as a compiler incorporated in an IDE, but only JDK 1.1.6 is supported for this release.
CORBA server objects, such as the EmployeeImpl object that has been created for this example, execute inside the Oracle8i database server. You must load them into the server, so that they can be activated by the ORB as required. You must also load all dependent classes, such as IDL-generated Holder and Helper classes, and classes used by the server object, such as the EmployeeInfo
class of this example.
Use the loadjava
tool to load each of the server classes into the Oracle8i database. For the example in this section, issue the loadjava
command in the following way:
% loadjava -oracleresolver -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
Of course you do not load any client implementation classes, or any other classes that are not used on the server side.
It is sometimes more convenient to combine the server classes into a JAR file, and simply 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
and then give the loadjava
command as simply:
% loadjava -oracleresolver -resolve -user scott/tiger myJar.jar
The final step in preparing the application is to publish the name of the CORBA server object implementation in the Oracle8i database. See "The Name Space" for information about publishing and published objects.
For the example in this section, you can 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:
publish
--run the publish command
republish
--overwrite any published object of the same name
user scott
--scott is the username for the schema doing the publishing
-password tiger
--Scott's password
-schema scott
--the name of the schema in which to resolve classes
-service sess_iiop://localhost:2481:ORCL
--establishes the service name (see also "The Service Context Class")
/test/myEmployee
--the name for the published object
employeeServer.EmployeeImpl
--the name of the class, loaded in the database, that implements the server object
employee.EmployeeHelper
--the name of the helper class
See "publish" for more information about the publish
command and its arguments.
To run this example, simply execute the client class using the client-side Java VM. For this example, you must set the CLASSPATH for the java
command to include
classes.zip
)
vbjapp.jar
and vbjorb.jar
aurora_client.jar
These libraries are located in the lib
directory under the Oracle home location in your installation.
The following invocation of the JDK java
command runs this example. Note that the UNIX shell variable ORACLE_HOME might be represented as %ORACLE_HOME% on Windows NT, and that JDK_HOME is the installation location of the Java Development Kit (JDK), version 1.1.6:
% java -classpath .:$(ORACLE_HOME)/lib/aurora_client.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 the client is invoked with four arguments on the command line:
From the java
command you can see why it is almost always better to use a makefile or a batch file to build CORBA applications.