Using WebLogic RMI
I. IntroductionOverview of RMI in the WebLogic frameworkWebLogic RMI, WebLogic's implementation of JavaSoft's Remote Method Invocation (RMI) specification, provides standards-based distributed object computing within WebLogic. WebLogic's implementation of RMI is a drop-in replacement for JavaSoft's RMI that provides scalability and performance, as well as access to all of WebLogic's integrated services, like JDBC, Events, etc. In addition, with release 3.0, WebLogic RMI is fully integrated with WebLogic JNDI. Applications can be partitioned into meaningful name spaces by using either the JNDI API or the Registry interfaces in WebLogic RMI. The WebLogic RMI compiler generates stubs and skeletons that completely replace the stubs and skeletons produced by RMIC, the RMI compiler. Like RMIC, the WebLogic RMI compiler produces enough compile-time information to support runtime resolution of classes, methods, and instances, to override Object methods, and to deliver Exceptions raised in the server to the invoking clients. For comparative information on JavaSoft's RMI and WebLogic RMI, read the the WebLogic whitepaper, Overview of WebLogic RMI. If you are new to the RMI specificationYou may want to go through the RMI training on the JavaSoft site before you continue through the implementation section of this document. This document contains information about using WebLogic's RMI, but it is not a beginner's tutorial on remote objects or writing distributed applications.WebLogic RMI architectureWebLogic's RMI code generatorYou run the WebLogic RMI code generator (rmic) by executing the weblogic.rmic class on the Java class file you want to execute via RMI. The code generator produces a stub and skeleton. The stub class is the serializable class that is passed to the client. The skeleton is a server-side class that processes requests from the stub on the client. The implementation for the class is bound to a name in the RMI registry in the WebLogic Server. A client acquires the stub for the class by looking up the class in the registry. WebLogic Server serializes the stub and sends it to the client. The client calls methods on the stub just as if it were a local class and the stub serializes the requests and sends them to the skeleton on the WebLogic Server. The skeleton deserializes client requests and executes them against the implementation classes, serializing results and sending them back to the stub on the client. With the WebLogic RMI compiler, you can specify that more platform-specific compilers should be used. By default, weblogic.rmic invokes the compiler from the JDK distribution, javac, but you may call any compiler with the -compiler option to weblogic.rmic, as shown in this example which calls the Symantec Java compiler: $ java weblogic.rmic -compiler \Cafe\bin\sj.exe The WebLogic RMI compiler accepts any option supported by the Java compiler; for example, you could add -d \classes examples.hello.HelloImpl to the command above. All other options supported by the compiler can be used, and are passed directly to the Java compiler. The WebLogic RMI compiler also accepts the option -nomanglednames, which suppresses the generation of the default proxy types and causes the WebLogic RMI compiler to produce proxies specific to the remote class. Proxies are described in more detail in the following section. Other features of the WebLogic RMI compiler address some of the limitations of the JavaSoft RMI compiler:
Note: If you are upgrading from an earlier version of WebLogic, you need to re-run rmic on any existing code to regenerate the wrapper classes so that they're compatible with the WebLogic Server version. Proxies in WebLogic RMIA proxy is a class used by the clients of a remote object, in the case of RMI, a skeleton and a stub. The stub class is the instance that is invoked upon in the client's Java Virtual Machine (JVM); the stub marshals the invoked method name and its arguments, forwards these to the remote JVM, and -- after the remote invocation is completed and returns -- unmarshals the results on the client. The skeleton class, which exists in the remote JVM, unmarshals the invoked method and arguments on the remote JVM, invokes the method on the instance of the remote object, and then marshals the results for return to the client.In JavaSoft's RMI reference implementation, there is invariably a one-to-one correspondence between the proxy classes and the remote objects. For example, running the JavaSoft RMI compiler against example.hello.HelloImpl -- which implements the remote class example.hello.Hello -- will produce two classes, example.hello.HelloImpl_Skel and example.hello.HelloImpl_Stub. If another class -- for example, counter.example.CiaoImpl also implements the same remote interface (example.hello.Hello), a virtually identical pair of proxy classes will be produced with the JavaSoft RMI compiler (counter.example.CiaoImpl_Skel and counter.example.CiaoImpl_Stub). The WebLogic RMI compiler works differently for increased efficiency. The default behavior of WebLogic's RMI compiler is to produce proxies for the remote interface, and for the remote classes to share the proxies. For example, with WebLogic's RMI compiler, example.hello.HelloImpl and counter.example.CiaoImpl are represented by a single stub and skeleton, the proxy that matches the remote interface(s) implemented by the remote object -- in this case, example.hello.Hello. When a remote object implements more than one interface, the proxy names and packages are determined by encoding the set of interfaces. You can override this default behavior with the WebLogic RMI compiler option -nomanglednames, which will cause the compiler to produce proxies specific to the remote class. When a class-specific proxy is found, it takes precedence over the interface-specific proxy. In addition, with WebLogic RMI proxy classes, the stubs are not final. References to colocated remote objects are references to the objects themselves, not to the stubs. How the RMI Registry and Server work in WebLogicOne of the great strengths of WebLogic's implementation of RMI is that it depends upon and benefits from the infrastructure provided by WebLogic. The WebLogic Server hosts the RMI registry and provides server infrastructure for RMI clients. With WebLogic's high-performance, efficient client-to-server and server-to-network communications, the overhead for RMI registry and server communications is minimal, since registry traffic is multiplexed over the same connection as JDBC, Event, and other kinds of traffic. WebLogic's sophisticated communications model means that clients use a single socket for RMI; scaling for RMI clients is linear in the WebLogic environment, unlike with JavaSoft's RMI reference implementation. WebLogic's RMI registry is created when the WebLogic Server starts up, and calls to create new registries simply locate the existing registry. Objects that have been bound in the registry can be accessed with a variety of client protocols, including the standard rmi://, as well as t3://, t3s://, http://, or https://. In fact, all of the Naming services use JNDI (Java Naming and Directory Interface).
Breadth and depth of WebLogic's implementationIn general, functional equivalents of all methods in the java.rmi package are provided in Release 3.0 of WebLogic RMI, except for those methods in the RMIClassLoader and the method java.rmi.server.RemoteServer.getClientHost().A functional equivalent for the RMI classloader will be available in a release subsequent to version 3.0, and at that point classloading from the WebLogic Server will be automatic. Because the RemoteServer.getClientHost() method is related to enabling information used for security, which WebLogic implements at the server level in a more sophisticated fashion, WebLogic may not choose to implement this method in a future release. All other interfaces, exceptions, and classes are supported in WebLogic RMI. Here are notes on particular implementations that may be of interest to developers:
The setSecurityManager() method is provided in WebLogic RMI for compilation compatibility only. No security is associated with it, since WebLogic RMI depends on the more general security model within WebLogic. If, however, you do set a SecurityManager, keep in mind that you can set only one. Before setting a SecurityManager, you should test to see if one has already been set; if you try to set another, your program will throw an exception. Here is an example: if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); The following classes are implemented but unused in WebLogic RMI:
II. The WebLogic RMI APIWebLogic RMI API referenceThere are several packages shipped as part of WebLogic RMI. The public API includes WebLogic's implementation of the RMI base classes, the registry, and the server packages. WebLogic's implementation also includes the WebLogic RMI code generator and supporting classes that are not part of the public API.
Class java.lang.Object Interface weblogic.rmi.server.LoaderHandler Class weblogic.rmi.registry.LocateRegistry (implements weblogic.rmi.registry.Registry) Class weblogic.rmi.Naming Class weblogic.rmi.server.ObjID (implements java.io.Serializable) Class weblogic.rmi.server.Operation Class java.io.OutputStream Class java.io.FilterOutputStream Class java.io.PrintStream Class weblogic.rmi.server.LogStream Class weblogic.rmi.server.RMIClassLoader Interface weblogic.rmi.server.RMIFailureHandler Class weblogic.rmi.server.RMISocketFactory Interface weblogic.rmi.registry.Registry (extends weblogic.rmi.Remote) Interface weblogic.rmi.registry.RegistryHandler Interface weblogic.rmi.Remote Interface weblogic.rmi.server.RemoteCall Class weblogic.rmi.server.RemoteObject (implements weblogic.rmi.Remote) Class weblogic.rmi.server.RemoteServer Class weblogic.rmi.server.UnicastRemoteObject (implements java.lang.Cloneable) Class weblogic.rmi.server.RemoteStub Interface weblogic.rmi.server.RemoteRef (extends java.io.E ternalizable) Class java.lang.SecurityManager Class weblogic.rmi.RMISecurityManager Interface weblogic.rmi.server.ServerRef (extends weblogic.rmi.server.RemoteRef) Interface weblogic.rmi.server.Skeleton Class java.lang.Throwable (implements java.io.Serializable) Class java.lang.Exception Class weblogic.rmi.AlreadyBoundException Class java.lang.CloneNotSupportedException Class weblogic.rmi.server.ServerCloneException Class weblogic.rmi.NotBoundException Class weblogic.rmi.RemoteException (implements weblogic.common.WLSerializable, java.io.Serializable) Class weblogic.rmi.AccessException Class weblogic.rmi.ConnectException Class weblogic.rmi.ConnectIOException Class weblogic.rmi.server.ExportException Class weblogic.rmi.server.SocketSecurityException Class weblogic.rmi.MarshalException Class weblogic.rmi.NoSuchObjectException Class weblogic.rmi.ServerError Class weblogic.rmi.ServerException Class weblogic.rmi.ServerRuntimeException Class weblogic.rmi.server.SkeletonMismatchException Class weblogic.rmi.server.SkeletonNotFoundException Class weblogic.rmi.StubNotFoundException Class weblogic.rmi.UnexpectedException Class weblogic.rmi.UnknownHostException Class weblogic.rmi.UnmarshalException Class java.lang.RuntimeException Class java.lang.SecurityException Class weblogic.rmi.RMISecurityException Class weblogic.rmi.server.ServerNotActiveException Class weblogic.rmi.server.UID (implements java.io.Serializable) Interface weblogic.rmi.server.Unreferenced Overview of the WebLogic RMI API
If you have written RMI classes, you can drop them in WebLogic RMI by changing the import statement on a remote interface and the classes that extend it. To add remote invocation to your client apps, look up the object by name in WebLogic's built-in registry. The basic building block for all Remote objects is the interface weblogic.rmi.Remote, which contains no methods. You extend this "tagging" interface -- that is, it functions as a tag to identify remote classes -- to create your own remote interface, with method stubs that create a structure for your remote object. Then you implement your own remote interface with a remote class. This implementation is bound to a name in the registry, from whence a client or server may look up the object and use it remotely. As in JavaSoft's reference implementation of RMI, the weblogic.rmi.Naming class is an important one. It includes methods for binding, unbinding, and rebinding names to remote objects in the registry. It also includes a lookup() method to give a client access to a named remote object in the registry. In addition, with release 3.0, WebLogic JNDI, WebLogic's implementation of the JavaSoft Java Naming and Directory Interface, is used throughout WebLogic to provide naming and lookup services. WebLogic RMI also supports naming and lookup in JNDI. WebLogic RMI Exceptions are identical to and extend java.rmi Exceptions so that existing interfaces and implementations do not have to change Exception handling.
There are two parts to using WebLogic RMI. First you create the interfaces and classes that you will invoke remotely. Then you add code to your client application that carries out the remote invocations. Each part of the implementation guide is divided into two step-by-step sections that detail these implementation phases. Following the implementation examples are instructions on how to set up and run the WebLogic Server to host your WebLogic RMI apps.
Converting an existing RMI class to use WebLogic RMIIt's easy to use WebLogic's RMI with classes written for JavaSoft's reference implementation of RMI. Here we use a simple example to demonstrate the four steps for conversion. For this example we use the HelloWorld example from JavaSoft documentation distribution.Step 1. Change the package importsIf you have a class written to use JavaSoft's reference implementation of RMI, only one change is needed in your class to start using WebLogic RMI. Change the import packages to point to weblogic.rmi instead of java.rmi. If you use any explicit full package names for java.rmi. classes, you need to change those class names as well to use weblogic.rmi. WebLogic supplies a PERL script in the examples/rmi directory of the distribution that you may use for this purpose -- called sub.pl. This script is provided purely as a convenience, and comes with no warranty. Step 2. CompileCompile the implementation class and the remote interface that it extends, and any other associated Java files -- perhaps an applet file that you use to invoke. You need to specify the destination of the output with the -d flag when you compile so that the classes are compiled into your weblogic/classes directory, which should already be in your CLASSPATH. On Windows NT, if you are compiling from the directory where the Hello example Java files are located, the command looks like this:$ javac -classpath %CLASSPATH% -d c:\weblogic\classes *.java Then run the WebLogic RMI code generator on the implementation class. Again, you specify the destination with the -d flag. On a UNIX system, the code generation command looks like the following example. Note that the command should be typed on a single command-line: $ java weblogic.rmic -d /weblogic/classes examples.rmi.hello.HelloImpl If you have compiled classes as we illustrated into the WebLogic classes directory, you will see these files in the directory weblogic/classes/examples/rmi/hello: Hello.class HelloApplet.class HelloClient.class HelloImpl.class Hello_WLSkel.class Hello_WLStub.class Step 3. Set up the WebLogic Server for RMIIdentify the remote classes that you want to be bound when the WebLogic Server starts up by registering these classes in the WebLogic weblogic.properties file. (For more information on the properties file, see Setting WebLogic properties.)
The weblogic.properties file is located in root directory of the distribution, parallel with the myserver/ directory. Both the properties file and the myserver/ directory must exist in order to run the WebLogic Server. To register each remote class for startup:
Note that the startup args for a main() method in RMI startup classes is a space-delimited list of arguments (unlike the comma-delimited name=value pairs used for system startup class arguments). Start the WebLogic Server. If WebLogic Server is set up to write log messages to the console (the default), you will see the messages: Wed Jul 23 14:13:44 PDT 1997:<I> <RMI> Registry started Wed Jul 23 14:13:45 PDT 1997:<I> <WebLogic> Invoke rmi startup class hello: examples.rmi.hello.HelloImpl HelloImpl created and bound in the registry to the name HelloServerscroll by as the WebLogic starts up. Note that the name you assign to the remote class in the call to Naming.bind() in the main() is the name under which the remote class will be available. The virtual name you assign to the class when you register it has nothing to do with the way you access the class in the Registry. Step 4. Run the client appletIf you are using a webserver other than WebLogic:
Then call the applet with your browser. Creating classes that can be invoked remotelyYou can write your own WebLogic RMI classes in just a few steps. Here we demonstrate another simple example to show how you start from scratch. Using WebLogic's RMI is simpler than using JavaSoft's RMI, since you do not need to extend UnicastRemoteObject and you do not need to set a SecurityManager.Step 1. Write a Remote interfaceEvery class that can be remotely invoked implements a remote interface. A remote interface must extend the interface weblogic.rmi.Remote, which contains no method signatures.
The interface that you write should include method signatures that will be implemented in every remote class that implements it. Interfaces in Java are a powerful concept, and allow great flexibility at both design time and runtime. If you need more information on how to write an interface, check out the JavaSoft tutorial An Overview of RMI. Your Remote interface should follow guidelines similar to those followed if you are using JavaSoft's RMI:
With JavaSoft's RMI, every class that implements a remote interface must have accompanying, precompiled stubs and skeletons. WebLogic RMI supports more flexible runtime code generation; WebLogic RMI supports stubs and skeletons that are type-correct but are otherwise independent of the class that implements the interface. If a class implements a single remote interface, the stub and skeleton that is generated by the code generator will have the same name as the remote interface. If a class implements more than one remote interface, the name of the stub and skeleton that result from code generation will depend on the name mangling used by the code generator. Your Remote interface may not contain much code. All you need are the method signatures for methods you want to implement in Remote classes. Here is an example of a Remote interface. It has only one method signature. package examples.rmi.multihello; import weblogic.rmi.*; public interface Hello extends weblogic.rmi.Remote { String sayHello() throws RemoteException; } Step 2. Implement the Remote interfaceNow write the class that will be invoked remotely. The class should implement the Remote interface that you wrote in Step 1, which means that you implement the method signatures that are contained in the interface. Currently, all the code generation that takes place in WebLogic RMI is dependent on this class file, but this will change in future releases.With WebLogic's RMI, there is no need for your class to extend UnicastRemoteObject, which is required by JavaSoft's RMI. (If you extend UnicastRemoteObject, WebLogic RMI will not care, but it isn't necessary.) This allows you to retain a class hierarchy that makes sense for your application. Your class may implement more than one Remote interface. Your class may also define methods that are not in the Remote interface, but you will not be able to invoke those methods remotely. You should also define at least a default constructor. In this example, we implement a class that creates multiple HelloImpls and binds each to a unique name in the Registry. The method sayHello() greets the user and identifies the object which was remotely invoked.
package examples.rmi.multihello; import weblogic.rmi.*; public class HelloImpl implements Hello { private String name; public HelloImpl(String s) throws RemoteException { name = s; } public String sayHello() throws RemoteException { return "Hello! From " + name; } Finally, write a main that creates an instance of the remote object and registers it in WebLogic RMI's registry, by binding it to a name (a URL that points to the implementation of the object). A client that wants to obtain a stub to use the object remotely will be able to look up the object by name. Here is an example of a main() for the HelloImpl class. This registers the HelloImpl object under the name HelloRemoteWorld in a WebLogic Server's Registry. public static void main(String[] argv) { // Not needed with WebLogic RMI // System.setSecurityManager(new RmiSecurityManager()); // But if you include this line of code, you should make // it conditional, as shown here: // if (System.getSecurityManager() == null) // System.setSecurityManager(new RmiSecurityManager()); int i = 0; try { for (i = 0; i < 10; i++) { HelloImpl obj = new HelloImpl("MultiHelloServer" + i); Naming.rebind("//localhost/MultiHelloServer" + i, obj); System.out.println("MultiHelloServer" + i + " created."); } System.out.println("Created and registered " + i + " MultiHelloImpls."); } catch (Exception e) { System.out.println("HelloImpl error: " + e.getMessage()); e.printStackTrace(); } } Note that, unlike JavaSoft's RMI reference implementation, WebLogic RMI doesn't require that you set a SecurityManager in order to integrate security into your application. Security is handled in a more general, server-wide way within WebLogic, with WebLogic Secure (support for SSL and ACLs). If you must, you may use your own security manager, but do not install it in the WebLogic Server. Step 3. Compile the java classFirst compile the .java files with javac or some other Java compiler to produce .class files for the Remote interface and the class that implements it.Step 4. Compile the implementation class with RMI compilerRun the WebLogic RMI compiler against the remote class to generate the stub and skeleton. A stub is the client-side proxy for a remote object that forwards each WebLogic RMI call to its matching serverside skeleton, which in turn forwards the call to the actual remote object implementation. To run WebLogic RMI's compiler, use the command pattern: $ java weblogic.rmic nameOfRemoteClasswhere nameOfRemoteClass is the full package name of the class that implements your Remote interface. With the examples we have used previously, the command would be: $ java weblogic.rmic examples.rmi.hello.HelloImplThe following options for java weblogic.rmic are available for you to use, and should be entered in one line, after java weblogic.rmic and before the name of the remote class.
You should set the flag -keepgenerated when you run the WebLogic RMI compiler if you want to keep the generated stub and skeleton files. Running the WebLogic RMI compiler creates two new classes, a stub and a skeleton. These appear as nameOfInterface_Stub.class and nameOfInterface_Skel.class. The four files created -- the remote interface, the class that implements it, and the stub and skeleton created by the WebLogic RMI compiler -- should be placed in the appropriate directory in the CLASSPATH of the WebLogic Server whose URL you used in the naming scheme of the object's main(). Step 5. Invoking methods on remote objects in your client codeOnce you compile and install the remote class, the interface it implements, and its stub and skeleton on the WebLogic Server, you can add code to a T3Client application to invoke methods in the remote class.In general, it takes just a single line of code: you need to get a reference to the remote object. Do this with the Naming.lookup() method. Here is a short T3Client application that uses the object we created in the first part of this guide. package mypackage.myclient; import weblogic.rmi.*; import weblogic.common.*; public class HelloWorld throws Exception { // Look up the remote object in the // WebLogic's registry HelloImpl hi = (HelloImpl)Naming.lookup("HelloRemoteWorld"); // Invoke a method remotely String message = hi.sayHello(); System.out.println(message); }This example demonstrates using a Java application rather than an applet as the client. Full code examplesHere is the full code for the Hello interface.package examples.rmi.hello; import weblogic.rmi.*; public interface Hello extends weblogic.rmi.Remote { String sayHello() throws RemoteException; }Here is the full code for the HelloImpl class that implements it. package examples.rmi.hello; import weblogic.rmi.*; public class HelloImpl // Don't need this in WebLogic RMI: // extends UnicastRemoteObject implements Hello { public HelloImpl() throws RemoteException { super(); } public String sayHello() throws RemoteException { return "Hello Remote World!!"; } public static void main(String[] argv) { try { HelloImpl obj = new HelloImpl(); Naming.bind("HelloRemoteWorld", obj); } catch (Exception e) { System.out.println("HelloImpl error: " + e.getMessage()); e.printStackTrace(); } } } Using client-side callbacks with RMIWith Release 3.0, WebLogic RMI supports client-to-server, client-to-client, and server-to-client invocations, with callbacks from server-side objects into applets. With WebLogic RMI, there is no need to export a client-side object as a remote object, as there is with JavaSoft's reference implementation. (The reason you must export an object with JavaSoft's RMI is that Remote objects are required to extend UnicastRemoteObject, which prevents the class from extending any other superclass -- in this case, Applet. JavaSoft's implementation must provide a way for classes that do not extend UnicastRemoteObject to be treated as Remote objects, which is done by exporting. WebLogic RMI does not require that Remote objects extend UnicastRemoteObject.) In an application that uses client-side callbacks to a remote client, you partition the application logic between tasks carried out on the server, and those that are exclusive to the client -- a common scenario with any distributed application. In this case, however, you write your remote interfaces for the server-side classes with methods that take the remote client object as a parameter or return it, when appropriate. For example, a server-side task that watches stock quotes will take as an argument the remote object that is interested in changes in stock prices. It can then operate on the remote object, for example, to make changes to the tables that the remote object keeps of stock prices. In practical use, being able to use a remote object as a parameter or a return value for a remotely invoked method is convenient for such things as updating the display of an applet in response to server-side events. Here, for example, you would merely export the applet itself as a remote object that registers an interest in server-side events, and whose display changes in response to those events. We illustrate how to make callbacks to a remote client in this section with the Stock example included in the distribution. There are two parts to this application: the first is the StockWatch, which acts as an event manager for this application and allows the StockApplet to register an interest in the stock events it will receive. The second part is the StockApplet, which displays realtime stock information, according to the events it receives from the StockServer. You can find the code for this application in your WebLogic distribution, in weblogic/examples/rmi/stock.
Step 1. Write the Remote interfaces for both client and serverYou will write two remote interfaces for this application: the StockWatch (the server-side logic that accepts incoming stock price events and allows clients to register an interest in them) and the StockNotify (the client-side logic that registers an interest in stock prices). Both, of course, extend weblogic.rmi.Remote. The StockWatch interface has 4 methods:
The StockNotify interface has just one method:
There are other classes that make up this application:
Step 2. Implement the Remote interfacesYou will need to write an implementation for your server-side logic -- the Remote interface StockWatch in this example -- and your client-side logic -- in this example, the Remote interface StockNotify. The implementation classes for this example are, respectively, StockServer and StockApplet.The StockServer class supplies information about stocks to its clients. In summary, the StockServer keeps a notifyTable, which is a Hashtable of the remote objects that have registered an interest in stocks, and a stockTable, a Hashtable of the stocks the server is watching. The real work of the StockServer is carried out in its run() method. It first calls a private method to get new stock prices, and then it enumerates through all of the remote objects (these are StockApplet object -- they implement the remote StockNotify interface -- kept in the StockServer's notifyTable) that have registered an interest in stock prices and updates each remote object where appropriate, by calling the remote object's update() method. Here is a code snippet:
// Get the date and time Date date = new Date(); // Enumerate through all the stock watchers Enumeration enum = notifyTable.keys(); while (enum.hasMoreElement()) { StockNotify clientapplet = (StockNotify)enum.nextElement(); Stock[] stockList = list(clientapplet); if (stockList != null) { // Update the remote object try { clientapplet.update(date, stockList); } catch (RemoteException re) { // Watcher is unavailable or unreachable // Cancel the notification e.printStackTrace(); cancelAll(clientapplet); } } } The StockApplet class has several interesting features: it manages the AWT display, which we will not describe in detail here; it keeps a Hashtable of those stocks in which it has registered an interest; and it sets up some boundaries for how often it will update its display, and for how long. Most importantly, it exports itself as the callback destination for its remotely invoked update() method, which receives notification of changing stock prices. The init() method in the applet is where the real work takes place. Note that there is no need in WebLogic RMI for this particular method call -- although it will not break your code to make the method call. We show it here as commented out:
// Export the applet as a remote object // UnicastRemoteObject.exportObject(this); The real initial action is to look up the StockWatch server, in order to call its methods for registering interest in stocks, as shown here. We use the document base of the applet as part of the URL; the applet must load all of its classes from the same host. Note that in our example, we use getCodeBase() instead of getDocumentBase(), which doesn't always properly load the applet, depending upon the browser.
// Look up the base URL URL base = getCodeBase(); String port = getParameter("registryPort"); if (port == null) { int p = base.getPort(); if (p == -1) p = 80; port = String.valueOf(p); } String serverName = "//" + base.getHost() + ":" + port + "/example.stock.StockServer"; stockWatch = (StockWatch)Naming.lookup(serverName); Now we remotely invoke methods on the StockServer object (it implements the StockWatch remote interface) to register an interest in stocks, as shown here. Note that one of the parameters passed to the watch() method is the client object itself. // Register an interest in stock updates for (int i = 0; i < name.length; i++) { stockWatch.watch(name[i], this); stockTable.put(name[i], new StockData(name[i], color[i])); } The StockApplet class also has inner classes -- like StockData used in the previous code snippet -- that take the stock information and display it in the applet. Step 3. Compile and install the classesAfter you write the implementation classes, compile them with the WebLogic RMI compiler, as shown in this example. Note that the symbol $(CLASSES) stands for your WebLogic classes directory, or the destination of your compiled class files. Each of these commands should be typed on a single command-line (although the last is displayed on multiple lines for clarity):
$ javac -d $(CLASSES) *.java $ cd $(CLASSES) $ java weblogic.rmic -d $(CLASSES) examples.rmi.stock.StockApplet examples.rmi.stock.StockServer Then you will need to register the StockServer as an RMI startup class in your weblogic.properties file. The StockServer will be bound in the registry when the WebLogic Server is started. Here is the correct property entry:
weblogic.system.startupClass.stock=examples.rmi.stock.StockServer Finally, you will also want to place the HTML file that calls the StockApplet in a registered document root. Then start the WebLogic Server with the URL of the applet. Setting up the WebLogic Server for RMIThe WebLogic Server hosts the RMI registry and the RMI server. In order to start the appropriate processes in WebLogic, you need to set one or two properties in your WebLogic properties file -- that's the weblogic.properties file that exists in the root directory of the WebLogic distribution.Properties to be set:
Start the WebLogic Server and call the main of your client application. IV. Change history
|
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|