RMISocketFactory
to use
at runtime, based on:
java.rmi.server.SocketType,
passed
to the constructor of UnicastRemoteObject
(see the tutorial on
Creating a Custom RMISocketFactory)java.rmi.factory.pkgs
Before this feature was added, it was possible to use different types
of sockets for different connections within the same JVM, but you had to
write an RMISocketFactory
that supported all of the socket types
used by your application, as described by the tutorial on Creating
a Custom RMISocketFactory. You also had to set that particular
RMISocketFactory
as the default socket factory at the beginning
of your RMI programs (for more information, see the tutorial on Creating
a Custom Socket Type). Unfortunately, applets are not allowed to call
the setSocketFactory
method because it would apply to all applets
executing in that JVM, so this new feature allows a different socket factory
to be used on a per-object basis.
This tutorial will use another version of the "Hello World" example,
modified to use a custom RMISocketFactory
. The main difference
between this example and the example used in the tutorial on creating a
custom RMISocketFactory
is that in this example, the RMISocketFactory
is not set at the beginning of HelloImpl
or HelloClient
.
The steps to take to enable the flexible lookup mechanism are:
java.rmi.server.RMISocketFactory
that produces
the types of sockets used by your application, named "RMISocketFactory
".RMISocketFactory
,
will use for communication. Use this name as:RMISocketFactory
SocketType
object passed
to the UnicastRemoteObject
constructorjava.rmi.server.RMISocketFactory
into a package.
Specifically, there should be a file called RMISocketFactory.java
in the package chosen in the previous step, so the fully package-qualified
name of your class will be in the format: <yourpackage>.<yourprotocol>.RMISocketFactory
RMISocketFactory
The name of your custom RMISocketFactory
must be RMISocketFactory
so that the RMI runtime will be able to lookup the correct RMI socket
factory by the package name. Since Creating
a Custom RMISocketFactory is the focus of another RMI tutorial, we
will modify the CompressionRMISocketFactory
written for that tutorial,
to become examples.rmisocfac.compression.RMISocketFactory.
Step 2:
Decide on a name for the protocol the sockets produced
by your RMISocketFactory
will use for communication.
Since CompressionRMISocketFactory
produces sockets that compress
and uncompress data, the protocol name will be "compression". Notice that
the SocketType
object is constructed with String
argument
with the package name of your RMISocketFactory
subclass.
As a result, the constructor for the class HelloImpl
looks like:
public HelloImpl(String s) throws RemoteException
{
super(0, new SocketType("examples.rmisocfac.compression",
null, null));
name = s;
}
Step 3:
Put your subclass of java.rmi.server.RMISocketFactory
into a package: <yourpackage>.<yourprotocol>.RMISocketFactory
The custom RMISocketFactory
's protocol name and containing
package will be "compression"
. In this example, the fully-qualified
package is examples.rmisocfac.compression
.
Please note: Because the subclass of java.rmi.server.RMISocketFactory
has the same name as its superclass, it is necessary to refer to the superclass
by its fully qualified package name.
Below is the code for the new custom RMISocketFactory
.
/* Notice the package name */
package examples.rmisocfac.compression;
import examples.rmisocfac.*;
import java.io.*;
import java.net.*;
import java.rmi.server.*;
/* Notice the name of the class */
public class RMISocketFactory extends java.rmi.server.RMISocketFactory
{
public Socket createSocket(String host, int port)
throws IOException
{
CompressionSocket socket
=
new CompressionSocket(host, port);
return socket;
}
public Socket createSocket(String host, int port,
SocketType type)
throws IOException
{
CompressionSocket socket
= new CompressionSocket(host, port);
return socket;
}
public ServerSocket createServerSocket(int port)
throws IOException
{
CompressionServerSocket server =
new CompressionServerSocket(port);
return server;
}
public ServerSocket createServerSocket(int port, SocketType type)
throws IOException
{
CompressionServerSocket server = new CompressionServerSocket(port);
return server;
}
}
Step 4:
RMISocketFactory
used by your remote application
Once your custom RMISocketFactory
has been compiled, make sure
the CLASSPATH is set so that that the client and the server can find the
RMISocketFactory
used in the application.
Step 5:
Run the Server and the Client
Running the server is the same as in the other tutorials; start the
rmiregistry
, if it's not already running, and then:
java -Djava.rmi.server.codebase=file:/mydirectory/ examples.rmisocfac.HelloImpl
&
The client may be an applet or an application, so both are provided.
HelloClient.java
is an application and HelloApplet.java
is an applet referenced by test.html
. The file test.html
looks like this:
<applet code=examples.rmisocfac.HelloApplet height=50 width=100>
</applet>
So to run the client, you can:
java examples.rmisocfac.HelloClient
or
appletviewer test.html
For the complete souce code, click here.
Set the java.rmi.factory.pkgs
property
Note: This property may be used, but is not necessary, if (1)
you will only need a single RMISocketFactory
, and (2) you
specify the exact package name of your socket factory, as we did, in the
implementation class's constructor.
The property java.rmi.factory.pkgs
can contains a vertiacal
bar (e.g. '|') separated list of the package names for each RMISocketFactory
that you want to make available for use by your application. In this example,
the protocol is called "compression" so you would set the property java.rmi.factory.pkgs
to "examples.rmisocfac"
.
If you have more than one custom RMISocketFactory
that you
want to use in a remote application, you would need to set the property
java.rmi.factory.pkgs
for the server and the client:
java -Djava.rmi.factory.pkgs="examples.rmisocfac|other.rmifactories"
-Djava.rmi.server.codebase=file:/mydirectory/
examples.rmisocfac.HelloImpl
&
java -Djava.rmi.factory.pkgs="examples.rmisocfac|other.rmifactories"
examples.rmisocfac.HelloClient
Please note: The quotation marks are necessary because the vertical bar `|` is a special character and will be treated as such unless used inside quotation marks.