Lotus Go Webserver

JIE Developer's Guide

Internet InterORB Protocol Enabler for Java


Table of Contents

Introduction

Writing JIE applications

NCF features of JIE

Sample JIE applications

Tutorial: Modifying an application step-by-step

Using the BTool

Tips & Techniques

Appendix A. JIE Reference


Introduction

This Guide describes the development process behind writing client/server applications over the CORBA Internet Inter-ORB Protocol (IIOP). It shows how painless developing in Java for client/server is, and it covers some of the distribution configuration options for the client and server.

Please see the Readme file for system requirements and installation instructions.

About JIE. The Internet InterORB Protocol Enabler for Java (JIE) is part of the Lotus Go Webserver. JIE (pronounced "gee") is a great way for you to add distribution to your Java and Web-centric applications using OMG's (the Object Management Group) open, standard, Internet Inter-ORB Protocol (IIOP). JIE is not a full CORBA ORB in the sense that it provides all of the traditional CORBA ORB services. The goal of JIE is to provide a robust Java client and server IIOP enabler that can be used in the web environment. Here are just some of the features that make JIE such an outstanding addition to the Lotus Go product:

Works directly with Java. The JIE toolkit includes emitters (code generators) that work directly with your Java interface class files to automatically generate Stubs used by your applications on the client side and Skeletons that wrapper your object implementations on the server side. In this way, you can work in 100% Pure Java on both sides, and you don't have to learn CORBA IDL (Interface Definition Language) or maintain separate source files in order to get started. Existing business objects that were written without an interface and implementation may also be distributed by using the JIE interface and implementation Emitter to create a wrapper from the class file.

HTTP-based Server ORB Start-up. JIE also includes an ORBlet (a lightweight Java based Object Request Broker) that can be automatically started in an HTTP server by a Java enabled browser running an Applet. This feature not only eliminates the need to separately maintain special ORB servers in order to distribute your applications, but it also greatly simplifies the application start-up procedure.

URL-based Object Activation. The JIE package includes a class with URLToObject and objectToURL methods that you can use in your client Applet to locate an object with a human readable URL. This feature makes it easy to find objects from information taken directly from Web pages. It also makes transparent the steps involved in activating a remote object to your application.

HTTP Tunnelling of IIOP Messages. Once your Applet has a reference to a remote object from an easy to use URL name, JIE's ORBlet features the ability for IIOP messages to tunnel through a fire-wall by using the existing HTTP connection. This feature means that you can administer a single securable gateway, yet gain the performance benefits of direct connections between client Applets and remote objects on the server.

Pass by Value of Java Objects. We believe that distribution of objects to remote servers can be a great way to achieve scalability in large applications, especially where these objects are shared by many clients. However, we also believe there are cases where the objects should be local to avoid the network traffic and associated overhead. For this reason, JIE includes the ability to pass objects from the server to the client and vice versa, so that object interactions involving remote method invocations are reduced to a minimum.

Extensible Object Services Framework. JIE comes ready to use out of the box with classes that activate transient objects (those whose constructor method does all the work of making the object ready to use). This feature is provided in the form of a transient object resolver. JIE also includes an example of a simple file-based persistent object resolver that can be used to save objects to a file. The JIE Resolver Interfaces provide the ability to plug in your own implementations for robust object services like identity, persistence and transactions. This feature allows you to integrate JIE with your existing application object activation model (sometimes called Business Object Frameworks).

Contents


Writing JIE applications

There are three phases to developing an application for distributed objects. In the first stage, one designs the business logic, irrespective of anything CORBA does. Second, one develops and tests the client-side application/applet, and finally, one writes and tests the server-side.

Figure 1: The resulting application. 

Develop the business logic and application

The first step in this development process will take you through capturing the business logic of a domain in a Java object. Then we access those objects 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 later, it could be distributed with very few changes. The required changes relate only to the activation of JIE and the creation of the objects. The example 1 application in the CORBA/iiop/tutorial1/example1 directory is the implementation of this process. The Account interface and _AccountImplBase implementation class are the files created in this first process. It is not necessary to provide a Java interface and implementation for each class that you want to distribute. In the case of pre-existing business logic classes, the interface and implementation emitters can be used to generate the Java interface and implementation required by JIE to distribute an object.

Distribute the application

Finish with an Lotus Go Webserver IIOP servlet

To run the applet with the business objects under a fully distributed environment, the Lotus Go Webserver 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 an HTTP servlet load get command. The servlet will be loaded and executed by the Lotus Go Webserver allowing the socket to be captured by the servlet and passed into the ORB.

Lotus Go Webserver Server ORB Initialization using a servlet

In order to run under the Lotus Go Webserver, the JIE classes and the application classes must exist in the Lotus Go Webserver C:\WWW\HTML directory. The Servlet class file must exist in the C:\WWW\SERVLETS\PUBLIC directory. The example3 makefile, for instance, will copy the appropriate files to the correct directory when building the "install" target as follows:

The APPLETDIR and SERVLETDIR environment variables need to point to the correct directories for the makefile to work properly. The JIE installation will create a batch file called SetJIE.bat that can be used to set all of the necessary environmental variables.

Note that the whole "COM" directory tree must be copied. Once this setup is complete, any client system with a java 1.02 or later enabled web browser can run the applet using this URL: http:/COM/ibm/CORBA/tutorial1/example3/account.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 = "Servlet/AccountServlet"


Using the NCF features of JIE

The JIE ORB provides specific Network Computing Framework (NCF) requirements that allow the use of CORBA and IIOP to be easily used and implemented. The features described below are unique to NCF and the NCF environment and specifically of great value to the Java developer that does not need to work directly with IDL or existing CORBA ORBs.

Java to Java code emitters

The JIE toolkit includes emitters (code generators) that create Interfaces, Implementations (ImplBases), Stubs, and Skeletons. In the case where a class already exists (i.e. Vector or Hashtable), the proper interface can be created by using the IIOPInterface emitter. The other emitters can then be used to create the proper ImplBase, Stub and Skeleton that are required by JIE to distribute this class. In the case of a new class, the class can be implemented as an interface/implementation pair. These can then be used by the IIOPStub and IIOPSkeleton emitters to create the other Stub and Skeleton required by JIE. In either case, when developing the business logic for the application, write it as you would for any Java application and then use the appropriate emitters when required. The following sections will describe the proper usage of the four emitters that are provided as part of the JIE toolkit.

Emitting the Interface: IIOPInterface

Emitting the Implementation: IIOPImplBase

Emitting the Stub: IIOPStub

 

Emitting the Skeleton: IIOPSkeleton

 

HTTP-based server ORB start-up

By a providing parameter in the HTML page that contains the applet initialization, the server side ORB can be activated under a HTTP browser. This will activate the servlet specified and give control of the socket to the ORB. Once the ORB controls the socket only IIOP communication protocol will be used on this socket. This also enables the connection to tunnel inside of the HTTP request/response protocol.

An application can also start an ORB using a servlet under a HTTP server by specifying the correct parameters as properties on the ORB.init method.

URL-based object activation

Two methods are provided on the ORB which are unique to the NCF environment. They are URL based resolution of an object, URLToObject, and an URL representation of an object, objectToURL. This methods work in much the same way as the CORBA methods string_to_object and object_to_string. The formant of the NCF URL follows the standard URL specification. Once the ORB has been initialized URLToObject can be used to obtain a reference to a specific object. During this resolution only the proxy 'stub' on the client is created. The server side skeleton and object are not created until the first method invocation is executed on the stub. This eliminates one or more trips accross the internet to activate the object.
 

        test = (IIOPTest)clientORB.URLToObject("IIOPID://server.ibm.com:3333;IIOPTest/2?COM.ibm.CORBA.iiop.test.types.IIOPTest" );
        objectURL = client.objectToURL((COM.omg.CORBA.Object)test, "IIOPID");

 

Using server-to-client callbacks

Very often the client would like to be notified of an event that occurs in the server. With JIE this is very easily done by emitting the distribution classes and passing the ImplBase object as a parameter for registration in the server. The client will new the object and pass it to the application specific control object on the server. The server will create the stub proxy and which allows the callback control object to call the method requested on the event.
 

    Client side code:

        COM.ibm.jiesamples.hashtest.java.Hashtable  hash   = new _HashtableImplBase();
        hashtest2.putHashtable(hash);  // registers hash with the hashtest2 object in the server.

    Server side code:

        class HashTest {  // application control object
            COM.ibm.jiesamples.hashtest.java.Hashtable  hash = null;
            public void putHashtable(Hashtable _hash) {
                hash = _hash;
            }
            public void notifyUsers {  // callback to registered client
                hash.eventOccured();
            }
        }

Using pass by value for Java objects

CORBA objects in Java are normally passed by reference having a proxy stub and skeleton representations that the ORB will use to execute methods. An object, in JIE, can also be accessed directly by the client as an object that was passed from the server as a Pass by Value object. This implies that the object was instanciated on the server and a copy of the object's state was sent to the client where a new instance of the class will be created and the state streamed into it. Any change of state in the client side object will not be reflected in  the server side object unless the application writes specific code for updates.

The JIE ORB recognizes the object as Object by Value if it implements the ByValue interface. This interface extends the Streamable class providing the _read, _write, and _type methods. The JIE ORB requires that these methods be implemented to stream the object state as primitive types. The interface of the object will extend ByValue and the ImplBase will implement the methods as shown below. Note that the IIOPInterface and IIOPImplBase emitters can be used to generate the proper ByValue interface and implementation. In the case of the IIOPImplBase emitter, the ImplBase created will have empty _read, _write methods that will need to be hand-coded with class specific logic that can not be generated by the emitter.

The JIE ORB also supports passing Java objects by value that do not implement the ByValue interface if Java version 1.1 or higher are supported in both the client and the server. If a parameter or return value of a method does not have a proxy avialable and it does not implement the ByValue interface then the ORB will attempt to use Java Serialization to pass the object by value. This means that the object must implement java.io.Serializable.

Using the Resolver Interfaces

The JIE ORB allows the application developer or a service developer to provide the object resolution for the ORB. This is a plugable interface which is implemented and passed into the server ORB at initialization time as a property. The ObjectResolver interface provides only three methods, keyToObject(), objectToKey(), and finalize(). The key is always generalized in byte array format for the ORB and objects are always java.lang.Object. The finalize method allows the ORB to notify the implemented ObjectResolver that the state of its objects should be preserved.

It is up to the implemented ObjectResolver to determine where and how the objects are created and where the state is preserved. The JIE samples provide a TransientResolver and a FileResolver as simple examples. In both of these additional methods are implemented that are not used by the JIE ORB. This methods are provided for the application writer to have better control over the state and activation of its objects. Any database and any type of object indentification can be used inside the implementation as long as the methods on the ObjectResolver are met.

The ObjectResolver should be set during the initialization for the server side ORB but may also be set or changed using the setObjectResolver method. The currently activated ObjectResolver for the ORB may be obtained by using the getObjectResovler method or providing it from the servlet which activated the ORB.
 


Sample JIE applications

The following examples ship as part of the JIE toolkit. All of these examples are in the JIE_Toolkit\COM\ibm\jiesamples directory with the exception of the tutorial example 4. All of the tutorial examples are in the JIE_Toolkit\COM\ibm\CORBA\iiop\tutorial1 directory.

To build these examples, a batch file is created during the JIE installation to set all of the environmental variables required to build and install these examples to the server directories. Refer to the SetJIE.bat for more information.

Checkers

This is a browser to browser checkers game between two players registered under the same game name.

Features:

Dictionary

Dictionary provides a simple register and lookup application using a persistent data store.

Features:

Hashtest

This is a sample application demonstrating how to distribute existing java classes.

Features:

TransientResolver

This is an example of an object resolver that can be registered with the JIE ORB. This resolver will register transient objects using a provided ID or an ID assigned by the ORB. While the ORB is active the ID may be used to return the same object originally instanciated.

Features:

FileResolver

This resolver works much like the TransientResolver but also provides persistence for each object in a file. The objects can be resolved to the same state with the ID even after the ORB has been recreated.

Features:

DaemonServer

The DaemonServer will allow the JIE ORB to be activated on the specified port of the current system. The listener allows multiple ORBs to be acctivated. Each connection to the listener will activate a new ORB.

Features:

Tutorial Example 4

The example 4 in the tutorial extends the AccountUI applet in example 3 to allow multiple users to access the same account and provide callbacks to all users when one user makes a change. When run in multiple instances of the browser on the same machine the browser started last will maintain control of the applet.

Features:


Tutorial: Modifying an application step-by-step

Overview of tutorial

The motivation behind writing this tutorial is that there are a lot of people out there who are interested in IIOP technology who are new to the idea, but would like a quick way to get their feet wet. In addition to providing a concrete example, this tutorial can also be used as a handy guide to help you make code modifications. Users with experience in modifying these types of programs will find this tutorial to be overly simplistic. This tutorial is mainly for new users.

In this tutorial, we add a simple reset button to the code presented in COM\ibm\CORBA\iiop\tutorial1. If a very large number is deposited or withdrawn, the balance may go out of bounds. In this case, the user should be able to click on a reset button to return the balance to the initial balance. This provides a way to correct the out of bounds situation. (Although this is not necessarily the optimal way to correct this problem, it makes a good example.)

Finally, although this tutorial gives all command lines in detail, much of the tedium (and a great deal of typing) can be automated by using the included Makefiles, the Build Tool and associated .proj files, or by creating your own custom batch files.

Before making changes

Although files are given in their final state in the tutorial2fin directory, it is recommended that new users start a fresh directory named tutorial2 and manually modify the code. Please make a copy of tutorial1 and rename it tutorial2. This directory should be in the COM\ibm\CORBA\iiop\tutorial2 path and should contain the three example subdirectories that we will be working with:

  • Example1
  • Example2
  • Example3
  • Feel free to refer to the final state tutorial2fin files if you get into trouble. Be aware that the references to server name in account.html must be changed to your server name before the tutorial2fin files will run. This is done by modifying account.html.

    Phase 1: Developing business logic

    In Example1, we test and debug our Java code to make sure it is working properly. At this time, you will be changing the files in the COM\ibm\CORBA\iiop\tutorial2\example1 path.

    Follow each of the following links in turn, then return here to test the modifications.

  • Modify Account.java
  • Modify _AccountImplBase.java
  • Modify AccountsTest.java
  • Modify AccountsUI.java
  • Modify Example1 Directory References
  • Testing Example1 Modifications

    After all the above modifications are made, compile the Java files in the directory and test your code as shown below. Compare your output to the output obtained from tutorial 1. Make sure the reset function is working properly.

    > javac *.java

    > java AccountsTest 100 200 25

    > java AccountsUI 100 200

    If you use the Makefile, the following is equivalent to everything above:

    > nmake test

    > nmake testui

    Phase 2: Developing the client side

    Now that we know the Java code is working, we can move on to the IIOP portion of the servlet tutorial. At this time, you will be changing the files in the COM\ibm\CORBA\iiop\tutorial2\example2 path.

    Just as you did for Phase 1, again follow each of the following links in turn, then return here to test the modifications. Note that some of the files are slightly different from Phase 1, and the example will not work if you merely copy Phase 1's files over to Phase2.

  • Modify Account.html
  • Modify Account.java
  • Modify _AccountImplBase.java
  • Modify AccountsUI.java
  • Modify Example2 Directory References
  • Testing Example2 Modifications

    After all the above modifications are made, compile the Java files in the directory and test your code as shown below. Note the use of emitters to create stubs and skeletons. Compare your output to the output obtained from tutorial 1. Make sure the reset function is working properly.

    Compile Account.java and _AccountImplBase.java, then use the Stub/Skeleton emitter:

    If there is not an existing directory path (for tutorial2/example2), you may need to create one. If your system variable settings are not completely correct, be aware the files may end up in an unexpected place.

    Recompile everything, then copy Account.html and the class files to your webserver document directory. The following example is for a Lotus Go Webserver directory.

    If you use the Makefile, the following is equivalent to everything above:

    Now, start the IIOP server:

    After starting the IIOP server, run Account.html by pointing your browser to:

    Compare your output to the output obtained from tutorial 1. Make sure the reset function is working properly.

    Phase 3: Developing the server side

    Our final step is to run our code on the Lotus Go Webserver. At this time, you will be changing the files in the COM\ibm\CORBA\iiop\tutorial2\example3 path.

    Just as you did for Phases 1 and 2, again follow each of the following links in turn, then return here to test the modifications. Note that some of the files are slightly different from Phases 1 and 2, and the example will not work if you merely copy Phase 2's files over to Phase 3.

  • Modify Account.html
  • Modify Account.java
  • Modify _AccountImplBase.java
  • Modify AccountsUI.java
  • Modify Example3 Directory References
  • Testing Example3 Modifications

    After all the above modifications are made, compile the Java files in the directory and test your code as shown below. Compare your output to the output obtained from tutorial 1. Make sure the reset function is working properly.

    Compile Account.java and _AccountImplBase.java, then use the Stub/Skeleton emitter:

    Compile, then copy Account.html and AccountServlet.class:

    If you use the Makefile, the following is equivalent to everything above:

    Make sure your Applet Directory and Servlet Directory paths are correct. (More details under #3 of the troubleshooting tips section). Also, if you are running a server other than Lotus Go Webserver, need to be careful in your use of Makefiles. For example, running "nmake all" defaults to LotusGo settings

    To use the Build Tool, read the Build Tool section, then load up the correct Example3.proj project file in the COM\ibm\btool directory. Be sure to change all tutorial1 references to tutorial2.

    Restart Lotus Go Webserver (refer to the troubleshooting tips section), then run Account.html by pointing your browser to:

    The example should now have a new reset button. Try it!

    File modification instructions

    The following instructions tell you how to make modifications to files in the tutorial2 directory. Open up the file in your favorite text editor, making sure you are in the correct example directory. If your directory path is different, change your package accordingly.

    Modifying Account.java

    Add the following method declaration:

    public void reset();

    Modifying _AccountImplBase.java

    Add the following variable declaration:

    protected float original_balance = 0;

    Add this to _AccountImplBase() constructor method:

    this.original_balance = balance;

    Add this method definition:

    Modifying AccountsTest.java

    Modify the test sequence to utilize our new reset function by replacing the existing test sequence with the following sequence. Compare this new sequence with the old and be sure you understand how it works, as it will show up in the output later on.

            // Test account methods.
            showAccount(checkingAccount);
            checkingAccount.deposit(changeAmount);
            showAccount(checkingAccount);
            checkingAccount.reset();
            showAccount(checkingAccount);
            checkingAccount.withdrawal(changeAmount);
            showAccount(checkingAccount);
    
            showAccount(savingsAccount);
            savingsAccount.deposit(changeAmount);
            showAccount(savingsAccount);
            savingsAccount.reset();
            showAccount(savingsAccount);
            savingsAccount.withdrawal(changeAmount);
            showAccount(savingsAccount);

    Modifying AccountsUI.java

    We will now modify the AccountsUI.java file. The reset button is closely modeled on the update button. Therefore, an easy way to find where to put the new code is to look for the update button code.

    Add these UI field declarations:

        protected final String kResetLabel = "Perform reset";
        protected final String kResetRequested =
        "Reset requested.  Resetting all accounts (this may take a moment)...";
        protected Button resetButton = null;

    Add this to the end of the buildUserInterface() method:

            // Create the panel for the reset button.
            Panel resetPanel = new Panel();
            add(resetPanel);
    
            // Create the reset button.
            resetButton = new Button(kResetLabel);
            resetButton.setFont(new Font("TimesRoman", Font.BOLD, 14));
            resetPanel.add(resetButton);

    Add this to the action() method:

            // Execute reset if the reset button was pressed.
            if (event.target instanceof Button &&
                ((String) object).equals(kResetLabel)) {
                resetButtonCallback();
            }

    Add the new resetButtonCallback() definition right after the existing updateButtonCallback() definition:

        protected void
        resetButtonCallback()
        {
            try {
                // Tell the user via the UI that we are working on the update.
                statusTextArea.replaceText(kResetRequested, 0, 1000);
    
    
                float adjustedBalance = 0;
    
    
                // Do the reset on all accounts, then
                // get the new account balances.
                    checkingAccount.reset();
    
                    // Get the new balance.
                    adjustedBalance = checkingAccount.getBalance();
    
                    // Update the user interface.
                    statusTextArea.replaceText("Newly reset checking account balance: " +
                                           adjustedBalance, 0, 1000);
    
                    savingsAccount.reset();
    
                    // Get the new balance.
                    adjustedBalance = savingsAccount.getBalance();
    
                    // Update the user interface.
                    statusTextArea.appendText("\nNewly reset savings account balance: " +
                                           adjustedBalance);
    
                // Update the user interface.
                statusTextArea.appendText("\n" + kUpdateInstructions);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    Modifying Account.html

    Modify the following portion by changing tutorial1 to tutorial2 (1 reference) and substituting the name of your IIOP server for servername (2 references):

    <applet
    name="Accounts"
    code="COM.ibm.CORBA.iiop.tutorial2.example2.AccountsUI"
    codebase="/"
    width=500
    height=300>
    <param name=URLToObjectContext value = "http://servername:3333">
    <param name=serverName value="servername">
    <param name=serverPort value="3333">
    </applet>

    Modify Example1 Directory References

    Each reference to tutorial1 must be changed to tutorial2 in the following files:

  • Account.java (1 reference)
  • _AccountImplBase.java (1 reference)
  • AccountsTest.java (1 reference)
  • AccountsUI.java (1 reference)
  • Makefile (2 references)
  • If you are using a different directory path, modify accordingly.

    Modifying Example2 Directory References

    Each reference to tutorial1 must be changed to tutorial2 in the following files:

  • Double-check Account.html (1 reference)
  • Account.java (1 reference)
  • _AccountImplBase.java (1 reference)
  • AccountsUI.java (3 references)
  • Makefile (4 references)
  • Transfer.bat (1 reference)
  • Transfer.java (3 references)
  • If you are using a different directory path, modify accordingly.

    Modifying Example3 Directory References

    Each reference to tutorial1 must be changed to tutorial2 in the following files:

  • Double-check Account.html (1 reference)
  • Account.java (1 reference)
  • _AccountImplBase.java (1 reference)
  • AccountsUI.java (3 references)
  • Makefile (3 references)
  • Transfer.bat (1 reference)
  • Transfer.java (3 references)
  • If you are using a different directory path, modify accordingly.


    Using the BTool

    Starting the Build Tool

    As part of the JIE installation, BTool should have been added to the start menu. You may start BTool by clicking StartMenu->Programs->JIE_Toolkit->JIE_Build_Tool

    Alternatively, you can run the following:

    > java COM.ibm.btool.BTool

    Make sure that the SetJIE.bat has been executed to set the environmental variables before running BTool. Refer to the BTool.bat file for more information.

    If you don't see the screen come up, try closing some windows (sometimes it appears underneath a window). If it still fails to come up after some time, read the Build Tool documentation.

    Loading an existing project file

    Click the Open Project icon or run Menu->File->Open...

    This should bring up a file selection window. Open the Example3 for LotusGo.proj project file.

    Building an example

    Click the Run Tools icon/button or run Menu->Action->Run Tools. After the build (which make take several minutes), everything should ready to run. Restart the Lotus Go Webserver and look for your modifications by running Account.html.

    Creating a new project file

    To illustrate this process of making a new project file, below are steps for creating the Build Tool Project file for Example 1.

    1. Launch BTool as described above
    2. Click the New Project icon or run Menu->File->New
    3. Click the Add... button or run Menu->Action->Add
    4. Type the following into the directory field: C:\JIE_Toolkit\COM\ibm\CORBA\iiop\tutorial2\example1\*.java
    5. Click (select) the following four files or click the Select All button)
    6. Click the Add button to add those four files into your project
    7. You should be back in the Build Tool window, which now has those four files under Project Files:
    8. Click (select) the first file Account.java
    9. Click (select) the Compile tool (in the right-hand window). No other tools should be selected.
    10. Repeat steps 8 and 9 with the remaining three files
    11. Save your project file by clicking the Save Project icon or run Menu->File->Save as...
    12. Click the Run Tools button to compile the four files


    Tips & Techniques

    Troubleshooting

    If you encounter problems, here are a few helpful troubleshooting tips:

    1. Check the CLASSPATH system variable to make sure that it is set up correctly. Lotus Go Webserver maintains a private JAVACLASSPATH in the servlet.cnf file within the Windows directory. Typically, this JAVACLASSPATH will already contain references to the JDK, server classes, and the HTML directory under the main server directory. The JIE installation on Windows NT will add a reference to the HTML directory if it is not there.
    2. When using the JIE toolkit to build, it will be necessary to have the JDK, server classes, and the JIE_Toolkit directory in your external CLASSPATH. The JIE installation will create a batch file called SetJIE.bat thats sets up all necessary environmental variables for building the JIE toolkit examples. The SetJIE.bat is created in the JIE_Toolkit directory.
    3. Double check your package. Did you change the tutorial and example numbers? Did you change all directory references?
    4. Try restarting the IIOP server if you have newly modified code. In example2, this is done by stopping and restarting this command:
    5. > java COM.ibm.CORBA.iiop.iiop.IIOPServer

      In example3, this is done in the Windows NT Services control panel, by selecting the Lotus Go Webserver line and clicking on Stop then Start.

    6. Make sure filenames (case sensitive) are identical to those found in tutorial1.
    7. Set the browser caches to 0 and clear existing caches. This is a good idea when testing applications built using the JIE toolkit, but is not recommended for normal browser usage since it will slow down performance and may cause problems with some applets when re-loading.
    8. Make sure your URLs are pointing to the correct places.
    9. Show the browser Java console (it's in the menu). If there is a Java error, try starting over fresh and making a superficial change (such as depositing twice the amount) and seeing if this change appears in the applet. If it does, debug your code or redo the modifications one change at a time. Be sure to restart the IIOP server between compiles.
    10. You may wish to activate the built-in JIE debug logging. See Logging JIE debug information below for details.
    11. If all else fails, try rebooting your machine. This has been found to correct a number of problems, especially if your changes don't appear to be updating.
    12. It may be wise to display a version number so you can be sure your changes are getting all the way to your browser. If your version number changes don't show up, check to make sure you are compiling the correct files and that they are copied to the correct places. If they still don't update, try rebooting.
    13. Contents

    Using JIE with Visual Age for Java

    Logging JIE debug information

    The JIE has a mechanism for logging debug information from a running client or server-side JIE. This RAS capability can be useful when debugging a problem or when a problem with the JIE is suppected. The debug logging can be turned on using the methods below for client and server running as an application or applet in a browser. Typically for the client, the debug output will appear in the java console window of the browser. In the case of the server side, the output must be directed to a file if running in a HTTP server. If running in the daemon listener the output can be seen in the DOS window running the listener.
     

    Typical Debug Output for Server

    Thread-3 ORB: inStream = COM.lotus.go.external.IcsRawInputStream@1eb4e0
    Thread-3 ORB: outStream = COM.lotus.go.external.IcsRawOutputStream@1eb4e5
    Thread-3 ORB: Created new Delegate for COM.ibm.CORBA.iiop.ServerORBlet@1eb566
    Thread-13 ServerORBlet: serverName rfox
    Thread-3 ORB: Created new Delegate for COM.ibm.CORBA.iiop.ServerORBlet@1eb566
    Thread-13 CallStream: CallStream in server started
    Thread-13 ServerORBlet: Object resolver = COM.ibm.jiesamples.transientResolver.TransientResolver@1eb295
    Thread-13 ServerORBlet: new connection for ORB COM.ibm.CORBA.iiop.ServerORBlet@1eb566
    Thread-13 ServerORBlet: running ORB
    Thread-13 ServerORBlet: Server Sync Message Sent.
    Thread-13 CallStream: Thread-14 Running replies thread false
    Thread-13 CallStream: Thread-14 Begin processMessages()
    Thread-14 GIOPMessageFactory: Blocking waiting for new message...
    Thread-14 GIOPMessageFactory: GIOP magic = 71 73 79 80 - GIOP
    Thread-14 GIOPMessageFactory: read...size=92, off=0, len=92, left=92
    Thread-13 CallStream: Thread-14 End processMessages()
    Thread-13 CallStream: Thread-14 Begin processMessages()
    Thread-14 GIOPMessageFactory: Blocking waiting for new message...
    Thread-13 MarshalInputStream: method name = deposit for request #1
    Thread-13 StreamController: ===New Request======================================
    Thread-3 ORB: getImpl keyToObject /Checking1?COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-3 ORB: getSkeletonFromKey Creating skeleton = COM.ibm.CORBA.iiop.tutorial1.example3.AccountSkeleton
    Thread-3 ORB: getSkeletonFromKey skeleton = COM.ibm.CORBA.iiop.tutorial1.example3.AccountSkeleton@1eb7f1
    Thread-13 StreamController: calling deposit on request #1
    Thread-13 StreamController: object    = COM.ibm.CORBA.iiop.tutorial1.example3._AccountImplBase@1eb7cd
    Thread-13 StreamController: skeleton  = COM.ibm.CORBA.iiop.tutorial1.example3.AccountSkeleton@1eb7f1
    Thread-13 StreamController: skeleton processed request
    Thread-13 MarshalOutputStream: sendReply for ID 1
    Thread-13 StreamController: sent reply
    Thread-14 GIOPMessageFactory: GIOP magic = 71 73 79 80 - GIOP
    Thread-14 GIOPMessageFactory: read...size=92, off=0, len=92, left=92
    Thread-13 CallStream: Thread-14 End processMessages()
    Thread-13 CallStream: Thread-14 Begin processMessages()
    Thread-14 GIOPMessageFactory: Blocking waiting for new message...
    Thread-13 MarshalInputStream: method name = getBalance for request #2
    Thread-13 StreamController: ===New Request======================================
    Thread-3 ORB: getImpl keyToObject /Checking1?COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-3 ORB: getSkeletonFromKey skeleton = COM.ibm.CORBA.iiop.tutorial1.example3.AccountSkeleton@1eb7f1
    Thread-13 StreamController: calling getBalance on request #2
    Thread-13 StreamController: object    = COM.ibm.CORBA.iiop.tutorial1.example3._AccountImplBase@1eb7cd
    Thread-13 StreamController: skeleton  = COM.ibm.CORBA.iiop.tutorial1.example3.AccountSkeleton@1eb7f1
    Thread-13 StreamController: skeleton processed request
    Thread-13 MarshalOutputStream: sendReply for ID 2
    Thread-13 StreamController: sent reply
     

    Typical Debug Output for Client

    Thread-1 ORB: creating ClientORBlet for rfox on port 80 IIOPPort 0
    Thread-1 ORB: Created new Delegate for COM.ibm.CORBA.iiop.ClientORBlet@4003ec58
    Thread-1 ORB: Created new Delegate for COM.ibm.CORBA.iiop.ClientORBlet@4003ec58
    Thread-1 ClientORBlet: new delegate = COM.ibm.CORBA.iiop.iiop.Delegate@4004ca98
    Thread-1 ClientORBlet: Creating a socket to rfox/80
    Thread-1 ClientORBlet: Servlet name is: (/Servlet/AccountServlet)
    Thread-1 ClientORBlet: Starting servletName: /Servlet/AccountServlet
    Thread-1 ClientORBlet: Server Type ICS
    Thread-1 ClientORBlet: GET /Servlet/AccountServlet?port=0 HTTP/1.0
    Waiting for Sync Message from Server, #bytes = 0
    Thread-1 ClientORBlet: Received Sync Message from Server. Server is now up!
    Thread-1 ClientORBlet: getStubFromKey objectList = null
    Thread-1 ClientORBlet: getStubFromKey stubList = null
    Thread-1 ClientORBlet: object = null
    Thread-1 ClientORBlet: Stub name = COM.ibm.CORBA.iiop.porting.BOAStub
    Thread-1 ClientORBlet: Class.forName(COM.ibm.CORBA.iiop.porting.BOAStub) = class COM.ibm.CORBA.iiop.porting.BOAStub
    Thread-1 Stub: instanceName = [COM.ibm.CORBA.iiop.porting.BOA;]
    Thread-1 Stub: className = COM.ibm.CORBA.iiop.porting.BOA
    Thread-1 Stub: port = 80
    Thread-1 Stub: serverName = rfox
    Thread-1 Stub: IOR:010000002600000049444c3a434f4d2f69626d2f434f5242412f69696f702f706f7274696e672f424f413a312e300000010000000000000052000000010000000400000072666f78500000003e000000434f4d2e69626d2e434f5242412e69696f702e706f7274696e672e424f413b3f434f4d2e69626d2e434f5242412e69696f702e706f7274696e672e424f4100
    Thread-1 ClientORBlet: resolving /Checking1 for class COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-1 ClientORBlet: getStubFromKey objectList = null
    Thread-1 ClientORBlet: getStubFromKey stubList = null
    Thread-1 ClientORBlet: object = null
    Thread-1 ClientORBlet: Stub name = COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub
    Thread-1 CallStream: Thread-2 Running replies thread false
    Thread-1 ClientORBlet: Class.forName(COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub) = class COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub
    Thread-1 Stub: instanceName = [/Checking1]
    Thread-1 Stub: className = COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-1 Stub: port = 80
    Thread-1 CallStream: Thread-2 Begin processMessages()
    Thread-1 Stub: serverName = rfox
    Thread-2 GIOPMessageFactory: Blocking waiting for new message...
    Thread-1 Stub: IOR:010000003500000049444c3a434f4d2f69626d2f434f5242412f69696f702f7475746f7269616c312f6578616d706c65332f4163636f756e743a312e3000000001000000000000004c000000010000000400000072666f7850000000380000002f436865636b696e67313f434f4d2e69626d2e434f5242412e69696f702e7475746f7269616c312e6578616d706c65332e4163636f756e7400
    Thread-1 ClientORBlet: resolved object COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub@40011e88
    Thread-1 ClientORBlet: resolving /Savings1 for class COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-1 ClientORBlet: getStubFromKey objectList = null
    Thread-1 ClientORBlet: getStubFromKey stubList = null
    Thread-1 ClientORBlet: object = null
    Thread-1 ClientORBlet: Stub name = COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub
    Thread-1 ClientORBlet: Class.forName(COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub) = class COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub
    Thread-1 Stub: instanceName = [/Savings1]
    Thread-1 Stub: className = COM.ibm.CORBA.iiop.tutorial1.example3.Account
    Thread-1 Stub: port = 80
    Thread-1 Stub: serverName = rfox
    Thread-1 Stub: IOR:010000003500000049444c3a434f4d2f69626d2f434f5242412f69696f702f7475746f7269616c312f6578616d706c65332f4163636f756e743a312e3000000001000000000000004b000000010000000400000072666f7850000000370000002f536176696e6773313f434f4d2e69626d2e434f5242412e69696f702e7475746f7269616c312e6578616d706c65332e4163636f756e7400
    Thread-1 ClientORBlet: resolved object COM.ibm.CORBA.iiop.tutorial1.example3.AccountStub@4007f7b8
    Thread-1 MarshalOutputStream: writeMethodName method name = deposit IOR COM.ibm.CORBA.iiop.iiop.IOR@225
    Thread-1 MarshalOutputStream: Size 100 IOR = COM.ibm.CORBA.iiop.iiop.IOR@225
    Thread-1 Stub: sentRequest
    Thread-1 StreamController: sendRequest COM.ibm.CORBA.iiop.iiop.Request@40075748
    Thread-1 MarshalOutputStream: send Request
    Thread-1 CallStream: AWT-Callback flushing request #1
    Thread-2 GIOPMessageFactory: GIOP magic = 71 73 79 80 - GIOP
    Thread-2 GIOPMessageFactory: read...size=12, off=0, len=12, left=12
    Thread-1 CallStream: AWT-Callback Received reply for #1
    Thread-1 CallStream: Thread-2 End processMessages()
    Thread-1 StreamController: waiting on reply
    Thread-1 CallStream: Thread-2 Begin processMessages()
    Thread-1 MarshalOutputStream: writeMethodName method name = getBalance IOR COM.ibm.CORBA.iiop.iiop.IOR@225
    Thread-2 GIOPMessageFactory: Blocking waiting for new message...
    Thread-1 MarshalOutputStream: Size 104 IOR = COM.ibm.CORBA.iiop.iiop.IOR@225
    Thread-1 Stub: sentRequest
    Thread-1 StreamController: sendRequest COM.ibm.CORBA.iiop.iiop.Request@40037d08
    Thread-1 MarshalOutputStream: send Request
    Thread-1 CallStream: AWT-Callback flushing request #2
    Thread-2 GIOPMessageFactory: GIOP magic = 71 73 79 80 - GIOP
    Thread-2 GIOPMessageFactory: read...size=16, off=0, len=16, left=16
    Thread-1 CallStream: Thread-2 End processMessages()
    Thread-1 CallStream: AWT-Callback Received reply for #2
    Thread-1 CallStream: Thread-2 Begin processMessages()
    Thread-1 StreamController: waiting on reply
    Thread-2 GIOPMessageFactory: Blocking waiting for new message...
     

    Activating the Debug Tool for the daemon listener server

    When running the daemon listener (java COM.ibm.CORBA.iiop.iiop.IIOPServer) the debug output can be seen in the DOS window by creating this file, c:\debug.jie, as an empty file. The debug statements will be printed in the window the server is running in.

    Activating the Debug Tool for a HTTP server

    The debug output under a HTTP server must be redirected to a file since most servers do not have Java consoles to display information about the application. By creating the file (c:\debug.jie) with a file name i.e. "c:\test" the output will be redirected into the file for the server side. The file name will be "c:\test.server". 

    Activating the Debug Tool for the Client Application

    The client application will be activated using the ORB.init((java.applet.Applet)null, initProperties) method which allows a "debug" property set to "true". This will enable the debug to appear in the application window.
     

    Activating the Debug Tool for the Client Applet in a browser

    The html file that loads the applet must on contain a parameter for debug thats value is true as below. This will enable the debug output to be displayed in the browser Java console.

    <param name=debug value="true">

    Directing Debug through method calls

    Any application on the client or server can activate the debug directly through method calls on the ORB as specified below. These are static methods on the COM.ibm.CORBA.iiop.ORB that allow activation of debug any time during execution of the application.

            debugOn();                         Turns on debug to the current window the application, client or server, is running in.
            debugOff();                        Turns off debug.
            openDebugFile(name);        Turns on debug redirecting the output to the file name specified.
     

    Contents


    Appendix A. JIE Reference

    ORB initialization methods

    Client ORB Initialization

    There are three forms of client ORB initialization methods as shown and described below:

     

    Server ORB Initialization

    There are several methods available to initialize a server ORB.  Only the most commonly used forms, namely those that are used to initialize the ORB on Lotus Go Webserver and the IIOPServer (debug server), are described here. The Lotus Go Webserver is initialized when the server side applet (servlet) is loaded. Each of these server side ORB initializations can be used with a server side applet (servlet) or the daemon listener. The differences between each are the use of a socket or streams and the ORB creating the object resolver or the resolver being created by the servlet.
     

    Application init allows an application to create and initialize an ORB.
    Parameters:
    args - ORB specific arguments from the main
    props - ORB specific properties
    Client activation properties


                      Name            Description
                      --------------------------------------------------------
                      server          server name
                      port            port number
                      servlet         servlet name to be loaded by HTTP
                      debug           set to true enables debug
     

    Server activation properties


                      Name            Description
                      --------------------------------------------------------
                      inputStream       input stream connected to client
                      outputStream    output stream connected to client
                      resolverObject  Object resolver specified by application
                      socket              socket connected to the client

    Lotus Go Webserver Server ORB Initialization using a servlet