6 How to Implement WebLogic RMI
java.rmi.Remote
interface which is the basic building block for all remote objects even though it 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, where a client or server can look up the object and use it remotely. 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 applications, look up the object by name in the registry. WebLogic RMI exceptions are identical to and extend java.rmi
exceptions so that existing interfaces and implementations do not have to change exception handling.
This chapter includes the following sections:
Creating Classes That Can Be Invoked Remotely
You can write the RMI classes and drop them in WebLogic RMI and change the import statement on a remote interface and the classes that extend the remote interface. WebLogic RMI generates code that has flexible runtime, and creates dynamic bytecode that is independent of the class that implements the interface.
You can write your own WebLogic RMI classes in just a few steps.
Step 1. Write a Remote Interface
Every class that can be remotely invoked implements a remote interface. Write the remote interface in adherence with the following guidelines.
-
A remote interface must extend the interface java.rmi.Remote, which contains no method signatures. Include method signatures that will be implemented in every remote class that implements the interface.
-
The remote interface must be public. Otherwise a client gets an error when attempting to load a remote object that implements it.
-
It is not necessary for each method in the interface to declare
java.rmi.RemoteException
in its throws block. The exceptions that your application throws can be specific to your application, and can extendRuntimeExceptio
n. WebLogic RMI subclassesjava.rmi.RemoteException
, so if you already have existing RMI classes, you will not have to change your exception handling. -
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 with the method signature
sayHello()
.WebLogic RMI supports more flexible runtime code generation; WebLogic RMI supports dynamic proxies and dynamically created bytecode that are type-correct but are otherwise independent of the class that implements the interface. If a class implements a single remote interface, the proxy and bytecode that is generated by the compiler will have the same name as the remote interface. If a class implements more than one remote interface, the name of the proxy and bytecode that result from the compilation depend on the name mangling used by the compiler.
Example 6-1 Hello.java Remote Interface
package examples.rmi.hello; import java.rmi.RemoteException; /** * This interface is the remote interface. * * Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved. */ public interface Hello extends java.rmi.Remote { String sayHello() throws RemoteException; }
Step 2. Implement the Remote Interface
Write the class 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. All the code generation that takes place in WebLogic RMI is dependent on this class file.
-
Your class can implement more than one remote interface. Your class can also define methods that are not in the remote interface, but you cannot invoke those methods remotely.
-
Example 6-2 implements a class that creates a
HelloImpl
and binds it to the unique name,HelloServer
, in the registry. The methodsayHello()
provides a greeting. -
The
main()
method creates an instance of the remote object and registers it in the WebLogic JNDI tree, by binding it to a name (a URL that points to the implementation of the object). A client that needs to obtain a proxy to use the object remotely will be able to look up the object by name.
WebLogic RMI does not require that you set a Security Manager in order to integrate security into your application. Security is handled by WebLogic Server support for SSL and ACLs.
Example 6-2 HelloImpl.java Remote Interface Implementation
package examples.rmi.hello; import javax.naming.*; import java.rmi.RemoteException; /** * Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved. */ public class HelloImpl implements Hello{ private String name; /** * Constructs a HelloImpl with the specified string. * * @param s String message */ public HelloImpl(String s) throws RemoteException { super(); name = s; } /** * Returns a string. * * @return String message * @exception java.rmi.RemoteException */ public String sayHello() throws java.rmi.RemoteException { return "Hello World!"; } /** * Allows the WebLogic Server to instantiate this implementation * and bind it in the registry. */ public static void main(String args[]) throws Exception { try { HelloImpl obj = new HelloImpl("HelloServer"); Context ctx = new InitialContext(); ctx.bind("HelloServer", obj); System.out.println("HelloImpl created and bound in the registry " + "to the name HelloServer"); } catch (Exception e) { System.err.println("HelloImpl.main: an exception occurred:"); System.err.println(e.getMessage()); throw e; } } }
Step 3: Create a Client that Invokes Remote Methods
In general, once you create an initial context, it takes just a single line of code to get a reference to the remote object. Do this with the Naming.lookup()
method. The following sections provide additional information on creating clients:
Setting Client Timeouts
You can set client side timeouts while configuring your initial context:
-
To set the amount of time a request waits for a connection response, use the
weblogic.jndi.connectTimeout
. -
To set the amount of time a request waits for a response from the remote server after a connection has been established, use the
weblogic.jndi.responseReadTimeout
. -
See Request Timeouts.
For example:
. . . // Get an InitialContext Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL, url); env.put("weblogic.jndi.connectTimeout", new Long(15000)); env.put("weblogic.jndi.responseReadTimeout", new Long(15000)); return new InitialContext(env); . . .
Example HelloClient.java Client
Here is a short WebLogic client application that uses an object created in Example 6-2.
Example 6-3 Example HelloClient.java Client
package examples.rmi.hello;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* This client uses the remote HelloServer methods.
*
* @author Copyright (c) 1999,2012, Oracle and/or its affiliates. All Rights Reserved.
*/
public class HelloClient
{
// Defines the JNDI context factory.
public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
int port;
String host;
private static void usage() {
System.err.println("Usage: java examples.rmi.hello.HelloClient " +
"<hostname> <port number>");
}
public HelloClient() {}
public static void main(String[] argv) throws Exception {
if (argv.length < 2) {
usage();
return;
}
String host = argv[0];
int port = 0;
try {
port = Integer.parseInt(argv[1]);
}
catch (NumberFormatException nfe) {
usage();
throw nfe;
}
try {
InitialContext ic = getInitialContext("t3://" + host + ":" + port);
Hello obj = (Hello) ic.lookup("HelloServer");
System.out.println("Successfully connected to HelloServer on " +
host + " at port " +
port + ": " + obj.sayHello() );
}
catch (Exception ex) {
System.err.println("An exception occurred: "+ex.getMessage());
throw ex;
}
}
private static InitialContext getInitialContext(String url)
throws NamingException
{
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
return new InitialContext(env);
}
}
Step 4. Compile the Java Classes
Use javac
or some other Java compiler to compile the .java
files to produce .class
files for the remote interface and the class that implements it.
Example 6-4 provides an Ant script that can be used in the WebLogic Server examples environment to compile the .java
files and install the .class
files into the serverclasses
and clientclasses
directories configured for the WebLogic Server examplesServer.
Example 6-4 Example build.xml file to Compile Java Classes
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="rmi.hello" default="all" basedir="."> <property environment="env"/> <property file="../../../examples.properties"/> <property name="build.compiler" value="${compiler}"/> <!-- set global properties for this build --> <property name="source" value="${basedir}"/> <target name="all" depends="build"/> <target name="build" depends="compile.server, compile.client"/> <!-- Compile server classes into the serverclasses directory --> <target name="compile.server"> <javac srcdir="${source}" destdir="${server.classes.dir}" includes="Hello.java, HelloImpl.java" classpath="${ex.classpath};${server.classes.dir}" deprecation="${deprecation}" debug="${debug}" debugLevel="${debugLevel}" /> </target> <!-- Compile client classes into the clientclasses directory --> <target name="compile.client"> <javac srcdir="${source}" destdir="${client.classes.dir}" includes="HelloClient.java" classpath="${ex.classpath};${server.classes.dir}" deprecation="${deprecation}" debug="${debug}" debugLevel="${debugLevel}" /> </target> </project>
Run the RMI Hello Code Sample
Use the following instructions to run the WebLogic RMI Hello example:
Prerequisites
Install WebLogic server, including the examples. It is assumed that you know how to start the examplesServer and how to set an environment in a shell to run examples.
Configure a Startup Class
Start an instance of the examplesServer. Create a startup class with the following information:
-
Name:
MyHello
-
Class Name:
examples.rmi.hello.HelloImpl
-
Targets: examplesServer
See Configure Startup Classes in Oracle WebLogic Remote Console Online Help.
Note:
In this example, the build script makes sure that the startup class is in a location on the server's classpath.
Restart the examplesServer
Restart the examplesServer. As the server boots, you should see the following in the server log:
HelloImpl created and bound in the registry to the name HelloServer
Once the server is running, you can verify that HelloServer
is registered by viewing the JNDI tree.