Reputation: 1568
I have followed several tutorials on running an RMI application. However, I can't seem to make it work, as I keep getting stuck on the same exception.
I am, at this point only running a server, so no client communication is involved.
I have a simple RMI program that consists of:
SortServer
ISortFactory<T>
QuickSortFactory<T>
RMIUtils
classallpermissions.policy
Policy file contents
grant {
permission java.security.AllPermission;
};
RMIUtils
static {
// Set policy
setPolicy();
// Set Security manager if not present
if(System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
setHost("127.0.0.1");
}
public static void addCodeBaseFor(Class<?> clazz) {
System.setProperty("java.rmi.server.codebase", clazz.getProtectionDomain().getCodeSource().getLocation().toString());
}
public static void setPolicy() {
System.setProperty("java.security.policy", PolicyFileLocator.getLocationOfPolicyFile());
}
public static void setHost(String hostAddress) {
System.setProperty("java.rmi.server.hostname", hostAddress);
}
public static String getHost() {
return System.getProperty("java.rmi.server.hostname");
}
SortServer
public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {
RMIUtils.addCodeBaseFor(ISortFactory.class);
ISortFactory<String> strQSFactory = new QuickSortFactory<String>();
// Same error: Naming.bind("rmi://"+RMIUtils.getHost()+"/quicksortfactory", strQSFactory);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("quicksortfactory-string", strQSFactory);
}
ISortFactory
public interface ISortFactory<T> extends Remote {
public ISorter<T> createSorter() throws RemoteException;
}
Implementing QuickSortFactory
public class QuickSortFactory<T> extends UnicastRemoteObject implements ISortFactory<T> {
private static final long serialVersionUID = -4856366323843718656L;
public QuickSortFactory() throws RemoteException {
super();
}
@Override
public ISorter<T> createSorter() throws RemoteException {
return new QuickSort<T>();
}
}
ISorter, QuickSorter and referenced objects
ISorter
extends Remote
and its methods throw RemoteException
s.
QuickSort
extends SortLogic
and implements ISorter
. Its methods throw RemoteException
s.
SortLogic
extends UnicastRemoteObject
. Its methods throw RemoteException
s.
Since I use JDK 1.5+, I shouldn't need to worry about stubs. The rmiregistry is running fine, or I would have different errors.
Literal console output
2013-11-20 00:57:00 DEBUG RMIUtils:33 - Policy file path changed to 'C:\Users\Mark\AppData\Local\Temp\rmi-sorter5248481413010560777.policy'
2013-11-20 00:57:00 DEBUG RMIUtils:38 - RMI hostname set to 127.0.0.1
2013-11-20 00:57:00 DEBUG RMIUtils:27 - Codebase path added: file:/F:/Development/Git/Personal/parallel-sorter/bin/
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:359)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at nl.marktielemans.rmisorter.server.SortServer.main(SortServer.java:42)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:249)
at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:709)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:653)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:590)
at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:242)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1535)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1491)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1748)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
... 12 more
Without codebase parameter
I've tried without codebase parameter, but am not sure how to include the classes in the RMI classpath as I read I should.
I've tried starting the registry from the code in SortServer
using RegistryLocator.getRegistry()
as above, as well as starting it from a command line opened in my bin
directory. Still, I would get the same error.
Upvotes: 3
Views: 9369
Reputation: 310850
java.lang.ClassNotFoundException: nl.marktielemans.rmisorter.server.factory.ISortFactory
...
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
The Registry doesn't have that class available in its CLASSPATH.
If you're using the java.rmi.server.codebase
property you need to set it before exporting any remote objects, and the codebase needs to be something the Registry and the clients can use.
public static void addCodeBaseFor(Class<?> clazz) {
System.setProperty("java.rmi.server.codebase", clazz.getProtectionDomain().getCodeSource().getLocation().toString());
}
This isn't going to work. The location on the server of the containing JAR file can't be seen from the client. Generally it is an http: or ftp: URL.
Upvotes: 2