Oracle8i Enterprise JavaBeans and CORBA Developer's Guide Release 8.1.5 A64683-01 |
|
Overview ======== The clientside example shows how to do transaction management for CORBA server objects from the client application, using the XA JTS methods. This example also shows a server object that uses SQLJ in its methods. Source files ============ employee.idl ------------ The CORBA IDL for the example. Defines: An EmployeeInfo struct A SQLError exception An Employee interface, with EmployeeInfo getEmployee () void updateEmployee () The SQLError exception is used so that SQLException messages can be passed back to the client. Client.java ----------- You invoke the client program from a command prompt, and pass it four arguments, the - service URL (service ID, hostname, port, and SID if port is a listener) - name of the published server object to lookup and instantiate - username - password that authenticates the client to the Oracle8i database server For example: % java -classpath LIBs Client sess_iiop://localhost:2481:ORCL \ /test/myEmployee scott tiger where LIBs is the classpath that must include $ORACLE_HOME/lib/aurora_client.jar $ORACLE_HOME/jdbc/lib/classes111.zip $ORACLE_HOME/lib/vbjorb.jar $ORACLE_HOME/lib/vbjapp.jar $JAVA_HOME/lib/classes.zip (Note: for NT users, the environment variables would be %ORACLE_HOME% and %JAVA_HOME%.) The client code performs the following steps: - gets the arguments passed on the command line - creates a new JNDI Context (InitialContext()) - initializes the Aurora transaction service - looks up the myEmployee CORBA published object on the server (this step also authenticates the client using NON_SSL_LOGIN and activates the server object) - starts a new transaction: TS.getTS().getCurrent().begin(); - gets and prints information about the employee SCOTT - increases SCOTT's salary by 10% - updates the EMP table with the new salary by calling the updateEmployee() method on the employee object - gets and prints the new information - commits the update: TS.getTS().getCurrent().commit(false); The printed output is: SCOTT 7788 3000.0 SCOTT 7788 3300.0 employeeServer/EmployeeImpl.sqlj -------------------------------- Implements the Employee interface. This file implements the two methods specified in the IDL: getEmployee() and updateEmployee(), using SQLJ for ease of DML coding. If the SQLJ code throws a SQLException, it is caught, and a CORBA-defined SQLError is thrown. This in turn would be propagated back to the client, where it is handled. Compiling and Running the Example ================================= UNIX ---- Enter the command 'make all' or simply 'make' in the shell to compile, load, and deploy the objects, and run the client program. Other targets are 'run' and 'clean'. Make sure that a shell environment variable ORACLE_HOME is set to point to the home location of the Oracle installation. This is operating system dependent, so see the Installation documentation that came with your system for the location. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. Windows NT ---------- On Windows NT, run the batch file makeit.bat from a DOS command prompt to compile, load, and deploy the objects. Run the batch file runit.bat to run the client program, and see the results. Make sure that the environment variables %ORACLE_HOME%, %CLASSPATH%, and %SERVICE% are set appropriately for the DOS command window. You can set these as either user or system environment variables from the Control Panel. Double click on System in the Control Panel then on the Environment tab to set these variables. Start a new DOS window after setting environment variable values. See the Installation documentation that came with your Oracle8i system for the values of these variables. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. You can also set an environment variable %JAVA_HOME% to point to the root of your Java JDK. For example, SET JAVA_HOME=C:\JDK1.1.6.
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in wstring name) raises (SQLError); void updateEmployee (in EmployeeInfo name) raises (SQLError); }; };
import employee.*; import oracle.aurora.jndi.sess_iiop.ServiceCtx; import oracle.aurora.jts.client.AuroraTransactionService; import oracle.aurora.jts.util.*; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; public class Client { public static void main (String[] args) throws Exception { if (args.length != 4) { System.out.println ("usage: Client serviceURL objectName user password"); System.exit (1); } String serviceURL = args [0]; String objectName = args [1]; String user = args [2]; String password = args [3]; Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); env.put (Context.SECURITY_PRINCIPAL, user); env.put (Context.SECURITY_CREDENTIALS, password); env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN); Context ic = new InitialContext (env); AuroraTransactionService.initialize (ic, serviceURL); Employee employee = (Employee)ic.lookup (serviceURL + objectName); EmployeeInfo info; TS.getTS ().getCurrent ().begin (); info = employee.getEmployee ("SCOTT"); System.out.println (info.name + " " + info.number + " " + info.salary); info.salary += (info.salary * 10) / 100; employee.updateEmployee (info); info = employee.getEmployee ("SCOTT"); System.out.println (info.name + " " + info.number + " " + info.salary); TS.getTS ().getCurrent ().commit (true); } }
package employeeServer; import employee.*; import java.sql.*; public class EmployeeImpl extends _EmployeeImplBase { public EmployeeInfo getEmployee (String name) throws SQLError { try { int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void updateEmployee (EmployeeInfo employee) throws SQLError { try { #sql { update emp set ename = :(employee.name), sal = :(employee.salary) where empno = :(employee.number) }; } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } }
Overview ======== The serversideJDBC example shows how to do transaction management for CORBA server objects from objects themselves, using SQL transaction control statements in the JDBC calls. Source files ============ employee.idl ------------ The CORBA IDL for the example. Defines: An EmployeeInfo struct A SQLError exception An Employee interface, with EmployeeInfo getEmployee (in wstring name) void updateEmployee (in EmployeeInfo name) void commit() The SQLError exception is used so that SQLException messages can be passed back to the client. Client.java ----------- You invoke the client program from a command prompt, and pass it four arguments, the - service URL (service ID, hostname, port, and SID if port is a listener) - name of the published server object to lookup and instantiate - username - password that authenticates the client to the Oracle8i database server For example: % java -classpath LIBs Client sess_iiop://localhost:2481:ORCL \ /test/myEmployee scott tiger where LIBs is the classpath that must include $ORACLE_HOME/lib/aurora_client.jar $ORACLE_HOME/jdbc/lib/classes111.zip $ORACLE_HOME/lib/vbjorb.jar $ORACLE_HOME/lib/vbjapp.jar $JAVA_HOME/lib/classes.zip The client code performs the following steps: - gets the arguments passed on the command line - creates a new JNDI Context (InitialContext()) - looks up the myEmployee CORBA published object on the server (this step also authenticates the client using NON_SSL_LOGIN and activates the server object) - gets and prints information about the employee SCOTT - increases SCOTT's salary by 10% - updates the EMP table with the new salary by calling the updateEmployee() method on the employee object - commits the update by invoking employee.commit() In other words, this client does everything that the ../clientside/Client.java program did, but does the transaction handling (a commit only) on the server. The printed output is: Beginning salary = 3000.0 Final Salary = 3300.0 employeeServer/EmployeeImpl.sqlj -------------------------------- Implements the Employee interface. This file implements the two methods specified in the IDL: getEmployee() and updateEmployee(), using SQLJ for ease of DML coding. EmployeeImpl.sqlj also implements a commit() method, that uses JDBC to issue a SQL COMMIT statement. Compiling and Running the Example ================================= UNIX ---- Enter the command 'make all' or simply 'make' in the shell to compile, load, and deploy the objects, and run the client program. Other targets are 'run' and 'clean'. Make sure that a shell environment variable ORACLE_HOME is set to point to the home location of the Oracle installation. This is operating system dependent, so see the Installation documentation that came with your system for the location. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. Windows NT ---------- On Windows NT, run the batch file makeit.bat from a DOS command prompt to compile, load, and deploy the objects. Run the batch file runit.bat to run the client program, and see the results. Make sure that the environment variables %ORACLE_HOME%, %CLASSPATH%, and %SERVICE% are set appropriately for the DOS command window. You can set these as either user or system environment variables from the Control Panel. Double click on System in the Control Panel then on the Environment tab to set these variables. Start a new DOS window after setting environment variable values. See the Installation documentation that came with your Oracle8i system for the values of these variables. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. You can also set an environment variable %JAVA_HOME% to point to the root of your Java JDK. For example, SET JAVA_HOME=C:\JDK1.1.6.
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in wstring name) raises (SQLError); void updateEmployee (in EmployeeInfo name) raises (SQLError); void commit () raises (SQLError); }; };
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 { if (args.length != 4) { System.out.println ("usage: Client serviceURL objectName user password"); System.exit (1); } String serviceURL = args [0]; String objectName = args [1]; String user = args [2]; String password = args [3]; // get the handle to the InitialContext Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); env.put (Context.SECURITY_PRINCIPAL, user); env.put (Context.SECURITY_CREDENTIALS, password); env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN); Context ic = new InitialContext (env); // This is using Server-side TX services, specifically, JDBC TX: // Now, get the handle to the object and it's info Employee employee = (Employee)ic.lookup (serviceURL + objectName); EmployeeInfo info = employee.getEmployee ("SCOTT"); System.out.println ("Beginning salary = " + info.salary); // do work on the object or it's info info.salary += (info.salary * 10) / 100; // call update on the server-side employee.updateEmployee (info); // call commit on the server-side employee.commit (); System.out.println ("Final Salary = " + info.salary); } }
package employeeServer; import employee.*; import java.sql.*; import oracle.aurora.jts.util.*; import org.omg.CosTransactions.*; public class EmployeeImpl extends _EmployeeImplBase { public EmployeeInfo getEmployee (String name) throws SQLError { try { int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void updateEmployee (EmployeeInfo employee) throws SQLError { try { #sql { update emp set ename = :(employee.name), sal = :(employee.salary) where empno = :(employee.number) }; } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void commit () throws SQLError { try { #sql { commit }; } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } }
Overview ======== The serversideJTS example shows how to do transaction management for CORBA server objects from the server object, using the XA JTS methods. Compare this example with the clientside example, in which all transaction management is done on the client. This example also shows a server object that uses SQLJ in its methods. Source files ============ employee.idl ------------ The CORBA IDL for the example. Defines: An EmployeeInfo struct A SQLError exception An Employee interface, with EmployeeInfo getEmployee(in wstring name) EmployeeInfo getEmployeeForUpdate(in wstring name) void updateEmployee(in EmployeeInfo name) The SQLError exception is used so that SQLException messages can be passed back to the client. Client.java ----------- You invoke the client program from a command prompt, and pass it four arguments, the - service URL (service ID, hostname, port, and SID if port is a listener) - name of the published server object to lookup and instantiate - username - password that authenticates the client to the Oracle8i database server For example: % java -classpath LIBs Client sess_iiop://localhost:2481:ORCL \ /test/myEmployee scott tiger where LIBs is the classpath that must include $ORACLE_HOME/lib/aurora_client.jar $ORACLE_HOME/jdbc/lib/classes111.zip $ORACLE_HOME/lib/vbjorb.jar $ORACLE_HOME/lib/vbjapp.jar $JAVA_HOME/lib/classes.zip The client code is almost exactly the same as the code in ../clientside/Client.java, but without the JTS transaction calls. The client code performs the following steps: - gets the arguments passed on the command line - creates a new JNDI Context (InitialContext()) - initializes the Aurora transaction service - looks up the myEmployee CORBA published object on the server (this step also authenticates the client using NON_SSL_LOGIN and activates the server object) - gets and prints information about the employee SCOTT - decreases SCOTT's salary by 10% - updates the EMP table with the new salary by calling the updateEmployee() method on the employee object - gets and prints the new information The printed output is: Beginning salary = 3000.0 Final Salary = 2700.0 employeeServer/EmployeeImpl.sqlj -------------------------------- Implements the Employee interface. This file implements the three methods specified in the IDL: getEmployee(), getEmployeeForUpdate(), and updateEmployee(), using SQLJ for ease of DML coding. EmployeeImpl also adds two private methods, commitTrans() and startTrans(), that perform XA JTS transaction management from the server. Note that on the server there is no need to call AuroraTransactionService.initialize() to initialize the transaction manager. This is done automatically by the server ORB. If the SQLJ code throws a SQLException, it is caught, and a CORBA-defined SQLError is thrown. This in turn would be propagated back to the client, where it is handled. Compiling and Running the Example ================================= UNIX ---- Enter the command 'make all' or simply 'make' in the shell to compile, load, and deploy the objects, and run the client program. Other targets are 'run' and 'clean'. Make sure that a shell environment variable ORACLE_HOME is set to point to the home location of the Oracle installation. This is operating system dependent, so see the Installation documentation that came with your system for the location. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. Windows NT ---------- On Windows NT, run the batch file makeit.bat from a DOS command prompt to compile, load, and deploy the objects. Run the batch file runit.bat to run the client program, and see the results. Make sure that the environment variables %ORACLE_HOME%, %CLASSPATH%, and %SERVICE% are set appropriately for the DOS command window. You can set these as either user or system environment variables from the Control Panel. Double click on System in the Control Panel then on the Environment tab to set these variables. Start a new DOS window after setting environment variable values. See the Installation documentation that came with your Oracle8i system for the values of these variables. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. You can also set an environment variable %JAVA_HOME% to point to the root of your Java JDK. For example, SET JAVA_HOME=C:\JDK1.1.6.
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in wstring name) raises (SQLError); EmployeeInfo getEmployeeForUpdate (in wstring name) raises (SQLError); void updateEmployee (in EmployeeInfo name) raises (SQLError); }; };
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 { if (args.length != 4) { System.out.println ("usage: Client serviceURL objectName user password"); System.exit (1); } String serviceURL = args [0]; String objectName = args [1]; String user = args [2]; String password = args [3]; // get the handle to the InitialContext Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); env.put (Context.SECURITY_PRINCIPAL, user); env.put (Context.SECURITY_CREDENTIALS, password); env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN); Context ic = new InitialContext (env); // This is using Server-side TX services, specifically, JTS/XA TX: // get handle to the object and it's info Employee employee = (Employee)ic.lookup (serviceURL + objectName); // get the info about a specific employee EmployeeInfo info = employee.getEmployee ("SCOTT"); System.out.println ("Beginning salary = " + info.salary); // do work on the object or it's info info.salary -= (info.salary * 10) / 100; // call update on the server-side employee.updateEmployee (info); System.out.println ("Final Salary = " + info.salary); } }
package employeeServer; import employee.*; import java.sql.*; import oracle.aurora.jts.util.*; import org.omg.CosTransactions.*; public class EmployeeImpl extends _EmployeeImplBase { private void startTrans () throws SQLError { try { TS.getTS ().getCurrent ().begin (); } catch (Exception e) { throw new SQLError ("begin failed:" + e); } } private void commitTrans () throws SQLError { try { TS.getTS ().getCurrent ().commit (true); } catch (Exception e) { throw new SQLError ("commit failed:" + e); } } public EmployeeInfo getEmployee (String name) throws SQLError { try { startTrans (); int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public EmployeeInfo getEmployeeForUpdate (String name) throws SQLError { try { startTrans (); int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name for update }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void updateEmployee (EmployeeInfo employee) throws SQLError { try { #sql { update emp set ename = :(employee.name), sal = :(employee.salary) where empno = :(employee.number) }; commitTrans (); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } }
Overview ======== The serversideLoggin example shows how to do transaction management for CORBA server objects both directly from the client application, as in the clientside example, but also adds a method in the server object that suspends the current transaction, starts a new transaction, and writes some data out to a table. The second transaction is then committed and the first transaction is resumed. Finally, in the original transaction context on the client the update that happened in a server object method is committed, to end the transaction. Source files ============ employee.idl ------------ The CORBA IDL for the example. Defines: An EmployeeInfo struct A SQLError exception An Employee interface, with EmployeeInfo getEmployee(in wstring name) EmployeeInfo getEmployeeForUpdate(in wstring name) void updateEmployee(in EmployeeInfo name) The SQLError exception is used so that SQLException messages can be passed back to the client. Client.java ----------- You invoke the client program from a command prompt, and pass it four arguments, the - service URL (service ID, hostname, port, and SID if port is a listener) - name of the published server object to lookup and instantiate - username - password that authenticates the client to the Oracle8i database server For example: % java -classpath LIBs Client sess_iiop://localhost:2481:ORCL \ /test/myEmployee scott tiger where LIBs is the classpath that must include $ORACLE_HOME/lib/aurora_client.jar $ORACLE_HOME/jdbc/lib/classes111.zip $ORACLE_HOME/lib/vbjorb.jar $ORACLE_HOME/lib/vbjapp.jar $JAVA_HOME/lib/classes.zip The client code performs the following steps: - gets the arguments passed on the command line - creates a new JNDI Context (InitialContext()) - initializes the Aurora transaction service - looks up the myEmployee CORBA published object on the server (this step also authenticates the client using NON_SSL_LOGIN and activates the server object) - starts a new transaction: TS.getTS().getCurrent().begin(); - gets and prints information about the employee SCOTT - increases SCOTT's salary by 10% - updates the EMP table with the new salary by calling the updateEmployee() method on the employee object - gets and prints the new information - commits the update: TS.getTS().getCurrent().commit(false); The client application prints: Beginning salary = 3000.0 End salary = 3300.0 log.sql ------- This SQL script creates the log_table table that is used by the EmployeeImpl class to log database updates. employeeServer/EmployeeImpl.sqlj -------------------------------- Implements the Employee interface. This file implements the three methods specified in the IDL: getEmployee(), getEmployeeForUpdate(), and updateEmployee() These methods use SQLJ for ease of DML coding. The class also implements a private method, log(), that is invoked by the getEmployee() and getEmployeeForUpdate() methods. The log() method suspends the current transaction, begins a new transaction, and updates the log_table with information on who did what. If the SQLJ code throws a SQLException, it is caught, and a CORBA-defined SQLError is thrown. This in turn is propagated back to the client, where it is handled. Compiling and Running the Example ================================= UNIX ---- Enter the command 'make all' or simply 'make' in the shell to compile, load, and deploy the objects, and run the client program. Other targets are 'run' and 'clean'. Make sure that a shell environment variable ORACLE_HOME is set to point to the home location of the Oracle installation. This is operating system dependent, so see the Installation documentation that came with your system for the location. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. Windows NT ---------- On Windows NT, run the batch file makeit.bat from a DOS command prompt to compile, load, and deploy the objects. Run the batch file runit.bat to run the client program, and see the results. Make sure that the environment variables %ORACLE_HOME%, %CLASSPATH%, and %SERVICE% are set appropriately for the DOS command window. You can set these as either user or system environment variables from the Control Panel. Double click on System in the Control Panel then on the Environment tab to set these variables. Start a new DOS window after setting environment variable values. See the Installation documentation that came with your Oracle8i system for the values of these variables. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. You can also set an environment variable %JAVA_HOME% to point to the root of your Java JDK. For example, SET JAVA_HOME=C:\JDK1.1.6.
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in wstring name) raises (SQLError); EmployeeInfo getEmployeeForUpdate (in wstring name) raises (SQLError); void updateEmployee (in EmployeeInfo name) raises (SQLError); }; };
import employee.*; import oracle.aurora.jndi.sess_iiop.ServiceCtx; import oracle.aurora.jts.client.AuroraTransactionService; import oracle.aurora.jts.util.TS; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; public class Client { public static void main (String[] args) throws Exception { if (args.length != 4) { System.out.println ("usage: Client serviceURL objectName user password"); System.exit (1); } String serviceURL = args [0]; String objectName = args [1]; String user = args [2]; String password = args [3]; // get an handle to the InitialContext Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); env.put (Context.SECURITY_PRINCIPAL, user); env.put (Context.SECURITY_CREDENTIALS, password); env.put (Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN); Context ic = new InitialContext (env); // get handle to the TX-Factory AuroraTransactionService.initialize (ic, serviceURL); // create an instance of an object to be modified in the TX Employee employee = (Employee)ic.lookup (serviceURL + objectName); EmployeeInfo info; // start the TX TS.getTS ().getCurrent ().begin (); // get employee-info filled up in the TX from the server info = employee.getEmployeeForUpdate ("SCOTT"); System.out.println ("Beginning salary = " + info.salary); // do work on the object in the TX; e.g. change the info info.salary += (info.salary * 10) / 100; // update the info in the TX employee.updateEmployee (info); // get and print the employee and it's info info = employee.getEmployee ("SCOTT"); System.out.println ("End salary = " + info.salary); // commit the TX TS.getTS ().getCurrent ().commit (true); } }
create table log_table (when date, which number, who number, what varchar2(2000)); exit
package employeeServer; import employee.*; import oracle.aurora.AuroraServices.ActivatableObject; import java.sql.*; import oracle.aurora.rdbms.DbmsJava; import oracle.aurora.rdbms.Schema; import oracle.aurora.jts.util.*; import org.omg.CosTransactions.*; public class EmployeeImpl extends _EmployeeImplBase implements ActivatableObject { public EmployeeInfo getEmployee (String name) throws SQLError { try { int empno = 0; double salary = 0.0; log ("getEmployee (" + name + ")"); #sql { select empno, sal into :empno, :salary from emp where ename = :name }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public EmployeeInfo getEmployeeForUpdate (String name) throws SQLError { try { int empno = 0; double salary = 0.0; log ("getEmployeeForUpdate (" + name + ")"); #sql { select empno, sal into :empno, :salary from emp where ename = :name for update }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void updateEmployee (EmployeeInfo employee) throws SQLError { log ("updateEmployee (" + employee + ")"); try { #sql { update emp set ename = :(employee.name), sal = :(employee.salary) where empno = :(employee.number) }; } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } private void log (String message) throws SQLError { try { // Get the current TX and suspendTxn it Control c = TS.getTS ().getCurrent ().suspend (); // Start a new transaction TS.getTS ().getCurrent ().begin (); // Get the current user name int ownerNumber = Schema.currentSchema ().ownerNumber (); // Get the session-id int sessID = DbmsJava.sessionID (DbmsJava.USER_SESSION); // Insert the information in the log table #sql { insert into log_table (who, which, when, what) values (:ownerNumber, :sessID, sysdate, :message) }; // Commit the TX started for logging the info TS.getTS ().getCurrent ().commit (true); // Resume the suspended TX TS.getTS ().getCurrent ().resume (c); } catch (Exception e) { throw new SQLError (e.toString ()); } } public org.omg.CORBA.Object _initializeAuroraObject () { return this; } }
Overview ======== Source files ============ employee.idl ------------ Client.java ----------- You invoke the client program from a command prompt, and pass it five arguments, the - service URL (service ID, hostname, port, and SID if port is a listener) - name of the published server object to lookup and instantiate - username - password that authenticates the client to the Oracle8i database server - number of new threads/sessions to create For example: % java -classpath LIBs Client sess_iiop://localhost:2481:ORCL \ /test/myEmployee scott tiger 3 where LIBs is the classpath that must include $ORACLE_HOME/lib/aurora_client.jar $ORACLE_HOME/jdbc/lib/classes111.zip $ORACLE_HOME/lib/vbjorb.jar $ORACLE_HOME/lib/vbjapp.jar $JAVA_HOME/lib/classes.zip The client code performs the following steps: - gets the arguments passed on the command line - creates a new JNDI Context (InitialContext()) - in a for-loop, creates different sessions using the ClientThread class, and prints out information about the session ID The printed output from Client should be something like this: Starting ClientThread (:session0) Starting ClientThread (:session1) Beginning salary = 3630.0 in :session0 10% Increase:session0 End salary = 3993.0 in :session0 Starting ClientThread (:session2) Beginning salary = 3993.0 in :session2 30% Decrease:session2 End salary = 2795.10009765625 in :session2 Beginning salary = 2795.10009765625 in :session1 20% Increase:session1 End salary = 3354.1201171875 in :session1 The actual output will differ depending on the state of the EMP table when the example is run. ClientThread.java ----------------- The ClientThread constructor creates a new named session in the server, and authenticates the client with NON_SSL_LOGIN, using the Context, service URL, published object name, username, and password passed as parameters. (NON_SSL_LOGIN is specified in the Context passed from Client.java.) The implementation of run() first yields to any other running threads. When run, it then initializes its transaction context, activates an Employee object in its session, and starts a new transaction. It then selects for update the SCOTT row in the EMP table, by calling a method on the employee object, and updates SCOTT's salary in a way dependent on the name of the session (this is a Dilbert world). Finally, it prints the new salary information, and commits the update (thus unlocking the EMP table row). employeeServer/EmployeeImpl.sqlj -------------------------------- Implements the Employee interface. This file implements the two methods specified in the IDL: getEmployee(), getEmployeeForUpdate(), and updateEmployee(), using SQLJ for ease of DML coding. See the description of this file in ../clientside/employeeServer for more information. Compiling and Running the Example ================================= UNIX ---- Enter the command 'make all' or simply 'make' in the shell to compile, load, and deploy the objects, and run the client program. Other targets are 'run' and 'clean'. Make sure that a shell environment variable ORACLE_HOME is set to point to the home location of the Oracle installation. This is operating system dependent, so see the Installation documentation that came with your system for the location. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. Windows NT ---------- On Windows NT, run the batch file makeit.bat from a DOS command prompt to compile, load, and deploy the objects. Run the batch file runit.bat to run the client program, and see the results. Make sure that the environment variables %ORACLE_HOME%, %CLASSPATH%, and %SERVICE% are set appropriately for the DOS command window. You can set these as either user or system environment variables from the Control Panel. Double click on System in the Control Panel then on the Environment tab to set these variables. Start a new DOS window after setting environment variable values. See the Installation documentation that came with your Oracle8i system for the values of these variables. Also, review the README file for the Oracle database, and the README file for the CORBA/EJB server (the Oracle8i ORB), for additional up-to-date information. You can also set an environment variable %JAVA_HOME% to point to the root of your Java JDK. For example, SET JAVA_HOME=C:\JDK1.1.6.
module employee { struct EmployeeInfo { wstring name; long number; double salary; }; exception SQLError { wstring message; }; interface Employee { EmployeeInfo getEmployee (in wstring name) raises (SQLError); EmployeeInfo getEmployeeForUpdate (in wstring name) raises (SQLError); void updateEmployee (in EmployeeInfo name) raises (SQLError); }; };
import employee.*; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; public class Client { public static void main (String[] args) throws Exception { if (args.length != 5) { System.out.println ("usage: Client serviceURL objectName user password " + "sessionsCount"); System.exit (1); } String serviceURL = args [0]; String objectName = args [1]; String user = args [2]; String password = args [3]; int sessionCount = Integer.parseInt (args[4]); // get the handle to InitialContext // Note: authentication is done per session in ClientThread Hashtable env = new Hashtable (); env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); Context ic = new InitialContext (env); // invoke different sessions using ClientThread for (int i = 0; i < sessionCount; i++) { String sessionName = new String (":session" + i); ClientThread ct = new ClientThread (ic, serviceURL, objectName, sessionName, user, password); System.out.println ("Starting ClientThread (" + sessionName + ")"); ct.start (); } } }
import employee.*; import oracle.aurora.jts.client.AuroraTransactionService; import oracle.aurora.jndi.sess_iiop.ServiceCtx; import oracle.aurora.jndi.sess_iiop.SessionCtx; import oracle.aurora.AuroraServices.LoginServer; import oracle.aurora.client.Login; import oracle.aurora.jts.util.TS; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Hashtable; public class ClientThread extends Thread { private Context ic = null; private String serviceURL = null; private String objectName = null; private String sessionName = null; private SessionCtx session = null; public ClientThread () {} public ClientThread (Context ic, String serviceURL, String objectName, String sessionName, String user, String password) { try { this.ic = ic; ServiceCtx service = (ServiceCtx)ic.lookup (serviceURL); this.session = (SessionCtx)service.createSubcontext (sessionName); LoginServer login_server = (LoginServer)session.activate ("etc/login"); Login login = new Login (login_server); login.authenticate (user, password, null); this.serviceURL = serviceURL; this.sessionName = sessionName; this.objectName = objectName; } catch (Exception e) { e.printStackTrace (); } } public void run () { try { this.yield (); // Get handle to the TX-Factory AuroraTransactionService.initialize (ic, serviceURL + "/" + sessionName); // create an instance of an employee object in the session Employee employee = (Employee)session.activate (objectName); EmployeeInfo info; // start the transaction TS.getTS ().getCurrent ().begin (); // Get the info about an employee // Note: lock is set on the row using 'for update' clause // while select operation info = employee.getEmployeeForUpdate ("SCOTT"); System.out.println ("Beginning salary = " + info.salary + " in " + sessionName); // arbitrarily change the value of the salary, // e.g. depending on sessionName if (sessionName.endsWith("0")) { System.out.println ("10% Increase" + sessionName); info.salary += (info.salary * 10) / 100; } else if (sessionName.endsWith("1")) { System.out.println ("20% Increase" + sessionName); info.salary += (info.salary * 20) / 100; } else { System.out.println ("30% Decrease" + sessionName); info.salary -= (info.salary * 30) / 100; } // Try sleeping this thread for a while before updating the info // Note: the other threads MUST wait // (since selected with 'for update' clause) this.sleep (2000); // update the infomation in the transaction employee.updateEmployee (info); // Get and print the info in the transaction // Note: do NOT use 'for update' here info = employee.getEmployee ("SCOTT"); System.out.println ("End salary = " + info.salary + " in " + sessionName); // commit the changes TS.getTS ().getCurrent ().commit (true); } catch (Exception e) { e.printStackTrace (); } } }
package employeeServer; import employee.*; import oracle.aurora.AuroraServices.ActivatableObject; import java.sql.*; import oracle.aurora.jts.util.*; import org.omg.CosTransactions.*; public class EmployeeImpl extends _EmployeeImplBase implements ActivatableObject { public EmployeeInfo getEmployee (String name) throws SQLError { try { int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public EmployeeInfo getEmployeeForUpdate (String name) throws SQLError { try { int empno = 0; double salary = 0.0; #sql { select empno, sal into :empno, :salary from emp where ename = :name for update }; return new EmployeeInfo (name, empno, (float)salary); } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public void updateEmployee (EmployeeInfo employee) throws SQLError { try { #sql { update emp set ename = :(employee.name), sal = :(employee.salary) where empno = :(employee.number) }; } catch (SQLException e) { throw new SQLError (e.getMessage ()); } } public org.omg.CORBA.Object _initializeAuroraObject () { return this; } }