Lotus Go Webserver
Tutorial: Modifying an application step-by-step
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).
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.
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.
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 called a Stub, and the proxy for the server is called a Skeleton. Both the Stub and the Skeleton can be created from the Account.class. IIOPStub and IIOPSkeleton are emitter tools that are provided as part of the JIE toolkit to create the Stub and Skeleton. The IIOPInterface and IIOPImplBase are emitter tools that are provided as a way to create a Java interface and implementation for an existing Java class, without re-writing the Java class. Refer to the Java to Java code emitter section for more information on all of the emitters provided in the JIE toolkit.
Figure 2: The design process. 
The following code generates the AccountStub.java and the AccountSkeleton.java, which must be compiled with 'javac.'
java COM.ibm.CORBA.iiop.emit.IIOPStub \. COM.ibm.CORBA.iiop.tutorial1.example2 COM.ibm.CORBA.iiop.tutorial1.example2.Account
java COM.ibm.CORBA.iiop.emit.IIOPSkeleton \. COM.ibm.CORBA.iiop.tutorial1.example2 COM.ibm.CORBA.iiop.tutorial1.example2.Account
The example 2 in the CORBA/iiop/tutorial1/example2 directory is the implementation of this process.
After creating the stub and skeleton the application needs to be modified to activate JIE and create the Account object through JIE. In example 2, the Transfer application uses distributed objects through an activated JIE. The JIE is activated by executing the static method ORB.init(Applet, Properties) . Now each Account object will be created using the URLToObject method on the JIE. 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 _AccountImplBase object on the server using the instanceId to re-access it as long as the server JIE is running. The server JIE will create only transient objects which can be reaccessed with the same instanceId as long as an instance of JIE is running. A persistence service is required to reaccess the same AccountImpl object after the server JIE is restarted. When the application has completed its work, it should always close the JIE, which will close the socket and disconnect from the server JIE.
public static void transferFunds(String account, float amount)
{
String hostURL = new String("IIOP:/"+serverName+":"+serverPort);
Properties initProperties =
new Properties();
initProperties.put("server",
serverName);
initProperties.put("port",
String.valueOf(serverPort));
ORB client = (COM.ibm.jorb.ORB)ORB.init((java.applet.Applet)null,
initProperties);
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.disconnect(null);
}
}
The JIE provides a daemon listener server which will accept IIOP requests
from a client application. This listener server does not handle class loading
to the client, therefore the client application must have all required
classes available locally. This listener server does provide a good environment
to test applications and allow the user to see what is happening in the
server JIE. The listener server can be run using the command line below.
It will wait for a request and activate the server JIE when the client
application executes the URLToObject method. The listener server uses the
current machine name and port 3333 as default. This listener will activate
the TransientResolver and pass it to the ORB for object resolution.
java COM.ibm.CORBA.iiop.iiop.IIOPServer
Client applets may also connect to the listener 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 parameters serverName and serverPort are used by the applet as initial properties to the client ORB and in the URLToObject method request.
<applet name="Accounts" code="COM.ibm.CORBA.iiop.tutorial1.example2.AccountsUI" codebase="/" width=500 height=300> <param name=URLToObjectContext value = "http://randyfox:3333"> <param name=serverName value="randyfox"> <param name=serverPort value="3333"> </applet>
The applet code for activation is the same for the Transfer application. The static method ORB.init((Applet)null, (Properties)initProperties) is used to activate the JIE, passing in the parameters from the html. The applet uses the getParameter() method to retrieve serverName and serverPort; these could be hard-coded in the applet but would require recompiling it for each system that the server JIE is run on. The AccountsUI.java file in example 2 contains Java GUI methods to display the applet. Refer to the Java APIs on the Javasoft web site. for details of the available Java GUI applet methods.
{
Properties initProperties =
new Properties();
initProperties.put("server",
serverName);
initProperties.put("port",
String.valueOf(serverPort));
initProperties.put("servlet",
"");
orb = (COM.ibm.CORBA.iiop.ORB)ORB.init((java.applet.Applet)null,
initProperties);
// 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 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
// Servlet for Lotus Go Webserver
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import COM.ibm.CORBA.iiop.LotusGoServlet;
import COM.ibm.jiesamples.transientResolver.TransientResolver;
public class AccountServlet extends COM.lotus.go.internal.GoServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse
resp)
{
try {
Properties
initProperties = new Properties();
/*
An object resolver can be created and initialized to be used */
/* by
the ORB with the code below */
TransientResolver
resolver = new TransientResolver();
initProperties.put("resolverObject",
resolver);
/*
The LotusGoServlet creates a new thread and */
/* calls
ORB.init((String[])null, initProperties) */
LotusGoServlet
gs = new LotusGoServlet(req, resp, initProperties);
} catch (Throwable e) {
e.printStackTrace();
throw
new Error(e.getMessage());
}
}
}
package COM.ibm.CORBA.iiop;
import java.io.*;
import java.lang.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import COM.lotus.go.internal.*;
import COM.lotus.go.external.IcsRawSocket;
import COM.ibm.CORBA.iiop.ORB;
public class LotusGoServlet
{
public LotusGoServlet(HttpServletRequest req, HttpServletResponse
resp, Properties props)
{
try {
IcsRawSocket
sock = new IcsRawSocket(req,resp);
//Use
a thread to test that it is OK to steal the socket and let the servlet
finish.
//Then
we can guarantee that we have the ability to write to the client even though
//the
original request thread that the webserver gave us is dead.
SocketThread
st = new SocketThread(sock, props);
//Start
the thread that we want to write to the socket with.
Thread
th = new Thread(st);
th.start();
//let
us know when the servlet is considered finished by the webserver
System.out.println("IIOP
Enabler for Java started for "+th.getName());
} catch (Throwable e) {
e.printStackTrace();
}
}
}
class SocketThread implements Runnable
{
IcsRawSocket rawSocket = null;
Properties initProperties = null;
public SocketThread(IcsRawSocket raw_, Properties
props)
{
rawSocket = raw_;
initProperties = props;
}
public void run()
{
try {
initProperties.put("inputStream",
rawSocket.getInputStream());
initProperties.put("outputStream",
rawSocket.getOutputStream());
ORB
orb = (COM.ibm.CORBA.iiop.ORB)ORB.init((String[])null, initProperties);
System.out.println("IIOP
Enabler for Java ending for "+Thread.currentThread().getName());
rawSocket.close();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
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:
nmake install
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"
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.
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.
The interface emitter will create the code for the name specified as an interface. Additional methods can be added before emitting the ImplBase. If the object will be an Object by Value, instead of Object by Reference, then see Objects By Value for the correct modifications before compiling.
java COM.ibm.CORBA.iiop.emit.IIOPInterface
p1 p2 p3 p4
p1 - base directory of package
p2 - full name of class of the business logic
p3 - full name of interface to be created
p4 - optional flag for Object by Value = ByValue
java COM.ibm.CORBA.iiop.emit.IIOPInterface MyAppDir java.util.Hashtable COM.ibm.jiesamples.hashtest.java.Hashtable ByValue
The implementation base code (ImplBase) will be emitted into the name specified using the original class of the business logic and the interface class. Only the new methods introduced in the interface will appear in the ImplBase. The logic for these methods should be added before compiling. For Object by Value the _read and _write methods will also be created.
java COM.ibm.CORBA.iiop.emit.IIOPInterface
p1 p2 p3 p4 p5
p1 - base directory of package
p2 - full name of class of the business logic
p3 - full name of the class of the interface
p4 - full name of ImplBase to be created
p5 - optional flag for Object by Value = ByValue
java COM.ibm.CORBA.iiop.emit.IIOPImplBase MyAppDir java.util.Hashtable COM.ibm.jiesamples.hashtest.java.Hashtable COM.ibm.jiesamples.hashtest.java._HashtableImplBase ByValue
The stub code will be emitted from the interface class into the name specified with 'Stub' appened. The stub is the client side proxy representaion of the object on the server.
java COM.ibm.CORBA.iiop.emit.IIOPInterface
p1 p2 p3
p1 - base directory of package
p2 - full name of class
p3 - full name of Stub to be created
java COM.ibm.CORBA.iiop.emit..IIOPStub MyAppDir COM.ibm.jiesamples.hashtest.java COM.ibm.jiesamples.hashtest.java.Hashtable
The skeleton code will be emitted from the interface class into the name specified with 'Skeleton' appened. The skeleton is the server side proxy representaion of the object on the server.
java COM.ibm.CORBA.iiop.emit.IIOPInterface
p1 p2 p3
p1 - base directory of package
p2 - full name of class
p3 - full name of Skeleton to be created
java COM.ibm.CORBA.iiop.emit.IIOPSkeleton MyAppDir COM.ibm.jiesamples.hashtest.java COM.ibm.jiesamples.hashtest.java.Hashtable
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.
<param name=URLToObjectContext value="/Servlet/AccountServlet">
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.
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");
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.
COM.ibm.jiesamples.hashtest.java.Hashtable
hash = new _HashtableImplBase();
hashtest2.putHashtable(hash);
// registers hash with the hashtest2 object in the server.
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();
}
}
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.
public interface Vector extends COM.ibm.CORBA.iiop.obv.ByValue {
}
public class _VectorImplBase
extends COM.omg.CORBA.portable.ObjectImpl
implements COM.ibm.jiesamples.dictionary.java.Vector
{
public void _read(COM.omg.CORBA.portable.InputStream
parm1)
{
// This
method must be implemented for Pass By Value to work correctly.
// Refer
to the COM.omg.CORBA.portable.Streamable class for more information.
int
size = parm1.read_long();
for
(int i = 0; i < size; i++) {
String s = parm1.read_string();
value.addElement(s);
}
}
public void _write(COM.omg.CORBA.portable.OutputStream
parm1)
{
// This
method must be implemented for Pass By Value to work correctly.
// Refer
to the COM.omg.CORBA.portable.Streamable class for more information.
if (!value.isEmpty())
{
int size = value.size();
parm1.write_long(size);
for (int i = 0; i < size; i++) {
parm1.write_string((String)value.elementAt(i));
}
}
}
public COM.omg.CORBA.TypeCode
_type()
{
return
null;
// This
method must be implemented for Pass By Value to work correctly.
// Refer
to the COM.omg.CORBA.portable.Streamable class for more information.
}
}
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.
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.
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.
This is a browser to browser checkers game between two players registered under the same game name.
Dictionary provides a simple register and lookup application using a persistent data store.
This is a sample application demonstrating how to distribute existing java classes.
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.
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.
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.
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.
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.
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.
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
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
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
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:
> javac Account.java
> javac _AccountImplBase.java
> java COM.ibm.CORBA.iiop.emit.IIOPStub ..\..\..\..\..\.. COM.ibm.CORBA.iiop.tutorial2.example2 Account
> java COM.ibm.CORBA.iiop.emit.IIOPSkeleton ..\..\..\..\..\.. COM.ibm.CORBA.iiop.tutorial2.example2 Account
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.
> javac *.java
> copy *.class C:\www\html\COM\ibm\CORBA\iiop\tutorial2\example2
> copy account.html C:\www\html\COM\ibm\CORBA\iiop\tutorial2\example2
If you use the Makefile, the following is equivalent to everything above:
> nmake all
> nmake install
Now, start the IIOP server:
> java COM.ibm.CORBA.iiop.iiop.IIOPServer
After starting the IIOP server, run Account.html by pointing your browser to:
http://servername/COM/ibm/CORBA/iiop/tutorial2/example2/account.html
Compare your output to the output obtained from tutorial 1. Make sure the reset function is working properly.
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
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:
> javac Account.java
> javac _AccountImplBase.java
> java COM.ibm.CORBA.iiop.emit.IIOPStub ..\..\..\..\..\.. COM.ibm.CORBA.iiop.tutorial2.example3 Account
> java COM.ibm.CORBA.iiop.emit.IIOPSkeleton ..\..\..\..\..\.. COM.ibm.CORBA.iiop.tutorial2.example3 Account
Compile, then copy Account.html and AccountServlet.class:
> javac *.java
> copy account.html C:\www\html
> copy AccountServlet.class C:\www\servlets\public
If you use the Makefile, the following is equivalent to everything above:
> nmake all
> nmake install
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:
http://servername/account.html
The example should now have a new reset button. Try it!
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.
Add the following method declaration:
public void reset();
Add the following variable declaration:
protected float original_balance = 0;
Add this to _AccountImplBase() constructor method:
this.original_balance = balance;
Add this method definition:
public void
reset()
{
balance = this.original_balance;
}
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);
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();
}
}
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>
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.
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.
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.
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.
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.
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.
To illustrate this process of making a new project file, below are steps for creating the Build Tool Project file for Example 1.
If you encounter problems, here are a few helpful troubleshooting tips:
> 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.
Select Class files for file type to import. Select your project name.
Click "Next".
Browse to and select JIE_Toolkit\COM directory. Select "Include
files from subdirectories". Click "Finish".
This is due from pulling in a couple more files than are needed to run
inside VA.
You may safely ignore these problems, or if you chose, delete these files
from the repository.
In future versions of Visual Age you may be able to debug servlets, but no support now exists. At such time, you will need to pull in the Class files distributed with your server by unzipping the icsclass.zip for Lotus Go. Then import the classes from those zip files. You also will need to ensure that you have the correct servlets imported for your server; VA for Java only allows one copy of a class with the same name and hierarchy. The correct servlet lies in the for LotusGo subdirectories for checkers, dictionary, and example3.
choose Java files from
JIE_Toolkit\COM\ibm\CORBA\iiop\tutorial1
and JIE_Toolkit\COM\ibm\CORBA\iiop.tutorial2fin
and JIE_Toolkit\COM\ibm\jiesamples.
Run with two parameters initial_checking_balance and initial_savings_balance
(e.g. 100 200).
If example 1 is the only thing running, there should only be one
thread to chose from.
In the debugger window goto Threads->Terminate. The AccountsUI window
should close.
Run without any arguments.
Change Height = 400, Width=500, and set and save parameters as follows:
<param name=URLToObjectContext value="http://YourServerNameHere:3333">
<param name=serverName value="">
<param name=serverPort value=3333>
If you experience problems running this, try <param name=serverName value="YourServerNameHere">.
Change Height=400, Width=500, and set and save parameters as follows:
If you are running Lotus Go web server use
<param name=URLToObjectContext value="/Servlet/AccountServlet">
Following the same steps of Example 3, run COM.ibm.jiesamples.dictionary
with the appropriate
URLToObjectContext for your server: "/Servlet/DictionaryServlet"
for LotusGo.
To get example3/AccountsUI, checkers, and dictionary to run with a web
server that is running on
another port you must change the ORB.init() in each of the files to this:
Properties initProperties
= new Properties();
initProperties.put("server","");
//or 'put("server","YourServerNameHere")' if you have
problems
initProperties.put("port","YourPort");
initProperties.put("servlet",getParameter("URLToObjectContext"));
orb = (COM.ibm.CORBA.iiop.ORB)
ORB.init((java.applet.Applet)null, initProperties);
For example3/AccountsUI, this is in the resolveAndActivateAccounts()
method. In CheckersApp, this is in the
init() method. And in DictionaryUI, this is in the resolveAndActivateDictionary()
method.
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.
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
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...
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.
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".
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.
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">
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.
There are three forms of client ORB initialization methods as shown and described below:
If the properties list is non-null, then "server", "port", "servlet", and optionally "debug" properties are expected. Please see the Java Developers Kit for a description of the Properties class.
server
String Internet host name of
a server ORB
port
int port
of the server ORB
servlet
String name of the servlet (a Java
class file)
debug
boolean true/false
If the properties list above is null, then the args array is expected to contain the following elements:
args[0]
Internet host name of a server ORB
args[1]
port number of the server ORB
args[3]
name of the servlet (a Java class file)
AppInitSample1.java and AppInitSample2.java (found in COM/ibm/CORBA/iiop/tutorial1/example2) are examples of how to initialize the ORB from a Java application. The former uses the command line arguments version of init; the latter uses the properties list.
This form may be called from either an applet or an application. When called from an applet, the Applet parameter must contain a reference to the calling applet, and the Properties argument should be null. A parameter "URLToObjectContext" should be supplied the HTML file that loads the applet. This parameter is a string that specifies the servlet name. See account.html and AccountsUI.java for an example.
When called from an application, the Applet parameter should be null, but cast to (java.applet.Applet), and the property list should contain the same data as described in the application init above. Transfer.java of example2 shows how to initialize the ORB from a java Application.
This purpose of this initialization form is to meet the Java IDL Mapping specification. This will create a static instance of the ORB. Please see the specification for further information.
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.
Properties props)
Name
Description
--------------------------------------------------------
server server name
port
port number
servlet servlet name to
be loaded by HTTP
debug set to
true enables debug
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
package COM.ibm.CORBA.iiop;
import java.io.*;
import java.lang.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import COM.lotus.go.internal.*;
import COM.lotus.go.external.IcsRawSocket;
import COM.ibm.CORBA.iiop.ORB;
public class LotusGoServlet
{
public LotusGoServlet(HttpServletRequest req, HttpServletResponse
resp, Properties props)
{
try {
IcsRawSocket
sock = new IcsRawSocket(req,resp);
//Use
a thread to test that it is OK to steal the socket and let the servlet
finish.
//Then
we can guarantee that we have the ability to write to the client even though
//the
original request thread that the webserver gave us is dead.
SocketThread
st = new SocketThread(sock, props);
//Start
the thread that we want to write to the socket with.
Thread
th = new Thread(st);
th.start();
//let
us know when the servlet is considered finished by the webserver
System.out.println("IIOP
Enabler for Java started for "+th.getName());
} catch (Throwable e) {
e.printStackTrace();
}
}
}
class SocketThread implements Runnable
{
IcsRawSocket rawSocket = null;
Properties initProperties = null;
public SocketThread(IcsRawSocket raw_, Properties
props)
{
rawSocket = raw_;
initProperties = props;
}
public void run()
{
try {
initProperties.put("inputStream",
rawSocket.getInputStream());
initProperties.put("outputStream",
rawSocket.getOutputStream());
ORB
orb = (COM.ibm.CORBA.iiop.ORB)ORB.init((String[])null, initProperties);
System.out.println("IIOP
Enabler for Java ending for "+Thread.currentThread().getName());
rawSocket.close();
} catch (Throwable e) {
e.printStackTrace();
}
}
}