This tutorial concentrates on development of a simple application to quickly take you through the entire development process for client/server applications over the CORBA Internet Inter-ORB Protocol (IIOP). In it you will learn how simple it is to use Java, along with client and servlet development. It will also go into details of distribution configuration options for the client and server. The standalone Java Object Request Broker (JORB) does not currently pass an Object by Value without JBOF in Bojangles.
The first step in this tutorial will take you through capturing some business logic of a domain into a Java object and then accessing that logic through an application or applet in a distributed environment. Creation of the business logic should be done without regard to whether it will be distributed or not. The application that uses the business logic can be developed as a standalone application first and then later be distributed with very few changes. The required changes relate only to the activation of the JORB and the creation of the objects. The example 1 application in the corba/tutorial1/example1 directory is the implementation of this process. The Account interface and AccountImpl class are the files created in this first process.
The first requirement for distribution is to create proxy representations of the Account interface that exist on the server. The proxy for the client side is a Stub and for the server is a Skeleton. Both of these are emitted from the Account interface that describes the methods for the business logic of the AccountImpl object. These methods are implemented in the stub and skeleton to delegate the method request on to the actual AccountImpl object on the server and then return any required return value back to the client. For more information on stubs and skeleton responsibilities refer to the General Distribution description document. Below are the command lines used to emit the stub and skeleton using tools provided in Bojangles. Once the stub and skeleton are emitted they must also be compiled with 'javac'. The example 2 in the corba/tutorial1/example2 directory is the implementation of this process.
java COM.ibm.jaws.tools.emit.RunStubEmitter COM.ibm.corba.tutorial1.example2.Account
java COM.ibm.jaws.tools.emit.RunSkeletonEmitter COM.ibm.corba.tutorial1.example2.Account
After creating the stub and skeleton the application needs to be modified to activate the JORB and create the Account object through the JORB. In example 2 the Transfer application uses distributed objects through an activated JORB. The JORB is activated by executing the static method CORBA.ORB_init(null). Now each Account object will be created using the URLToObject method on the JORB. This method requires an IIOP URL that complies with standard URL format with some extensions. As seen below, the URL format is "IIOP:/serverName:serverPort;instanceId?className". This will instanciate a stub proxy on the client, a skeleton proxy on the server and the AccountImpl object on the server using the instanceId to reaccess it as long as the server JORB is running. The server JORB will create only transient objects that can be reaccess with the same instanceId as long as the JORB is running. A persistence service, such as what Bojangles provides, is required to reaccess the same AccountImpl object after the server JORB is restarted. When the application has completed its work, it should always close the JORB, which will close the socket and disconnect from the server JORB.
public static void transferFunds(String account, float amount) { String hostURL = new String("IIOP:/"+serverName+":"+serverPort); ORB client = CORBA.ORB_init(null); checking = (Account)client.URLToObject(hostURL+ ";/Checking" + "?COM.ibm.corba.tutorial1.example2.Account" ); savings = (Account)client.URLToObject(hostURL+ ";/Savings" + "?COM.ibm.corba.tutorial1.example2.Account" );
client.close(); } }
The Bojangles JORB provides a daemon server which will accept IIOP requests from a client application. This daemon server does not handle class loading to the client, therefore the client application must have all required classes available locally. This daemon server does provide a good environment to test applications and allow the user to see what happening in the server JORB. The daemon server can be run using the command line below. It will wait for a request and activate the server JORB when the client application executes the URLToObject method. The daemon server uses the current machine name and port 3333 as default.
java COM.ibm.corba.IIOP.IIOPServer
Client applets may also connect to the daemon server, but must have all required classes available locally. The applet is loaded through an html file using the parameters below. The name specifies the instance name of the applet and the code specifies which class to load and execute. The URLToObjectContext is used in the applet to specify the serverName and portName to be used in the URLToObject method request.
<applet name="Accounts" code="COM.ibm.corba.tutorial1.example2.AccountsUI" codebase="/" width=500 height=300> <param name=URLToObjectContext value="http:/randyfox:3333"> </applet>
The applet code for activation is the same as the application. The static method CORBA.ORB_init(this) is used to activate the JORB, passing the applet as a parameter. The URLToObject method call uses the getParameter method to retrieve the URLToObjectContext from the html file for the server and port. This could be hard coded in the applet but would require recompiling it for each system that the server JORB is run on. The AccountUI.java file in example 2 contains Java GUI methods to display the applet. Details of the available Java GUI appet methods can be found in the Sun API javadoc.
{ orb = CORBA.ORB_init(this); // Activate the accounts using "resolve" checkingAccount = (Account) orb.URLToObject(getParameter("URLToObjectContext") + ";/Checking" + "?COM.ibm.corba.tutorial1.example2.Account"); savingsAccount = (Account) orb.URLToObject(getParameter("URLToObjectContext") + ";/Savings" + "?COM.ibm.corba.tutorial1.example2.Account"); }
To run the applet with the business objects under a fully distributed environment, the Netscape server is used in place of the IIOP daemon server. This allows the classes required for the client to be downloaded and the IIOP request to be tunneled through a http servlet load put command. The servlet will be loaded and executed by the Netscape server allowing the socket to be captured by the server JORB. The JORB is activated using the static method CORBA.ORB_init with and a string array and the JORB instance name. The string array for the standalone JORB is empty. Each of these elements when used are explained in the Bojangles tutorial. Once the JORB is initialized, it is passed the socket in the run method and maintains control until the client closes the socket with the close method on the client JORB.
public class AccountsServlet extends netscape.server.applet.ServerApplet { public void run() throws Exception { try { // Create the server orb and run it. String args[] = new String[3]; args[0] = ""; args[1] = ""; args[2] = null; ORB orb = CORBA.ORB_init(args, "AccountServletORB"); orb.run(getClientSocket()); } catch (Throwable e) { e.printStackTrace(); throw new Error(e.getMessage()); } } }
In order to run under the Netscape server, the JORB and the business objects must exist under the /Netscape/server/docs and /Netscape/server/plugins/java/applets directories. This can be done by using the xcopy commands below. The application and business objects should be copied to the appropriate directory also if they are not under corba. Once this is done a browser from any system may run the applet using this URL: http:/COM/ibm/corba/tutorial1/example3/index.html. The html file in example 3 has one required change in it that allows the servlet name to be specified. This is seen on the URLToObjectContext parameter as value = "server-java/AccountServlet"
xcopy \com\ibm\corba \netscape\server\docs\COM\ibm\corba /s
xcopy \com\ibm\corba \netscape\server\plugins\java\applets\COM\ibm\corba /s
The JORB has dependencies on a naming convention that allows the base interface name to be determined from the class instance. These conventions use the interface name, i.e. Account, and append Stub, Skeleton, or Impl. If these conventions can not be followed then the JORB depends on the class instance name to be entered in the Implementation Reposistory. This can be done using the command line below or by editing the ImplRepository.data file. All names in the repository should include the package name. The required parameters are the class name that will be instanciated on the server JORB and the base interface name. If the stub and skeleton were not emitted off the base interface name, then the 3rd and 4th parameters will be the stub and skeleton class names that were emitted. If the file is changed by editing, each entry of the 4 names will be on one line with each name separated by a semicolon.
java COM.ibm.corba.porting.RegisterImpl className interfaceName stubName skeletonName
example 1 >java COM.ibm.corba.porting.RegisterImpl COM.ibm.corba.test.TestBaseImpl COM.ibm.corba.test.Test
example 2 >java COM.ibm.corba.porting.RegisterImpl COM.ibm.corba.test.TestBaseImpl COM.ibm.corba.test.Test COM.ibm.corba.test.TestStub COM.ibm.corba.test.TestSkeleton