Hi,
I am trying to run an RMI example from the book
Core Java(TM) 2, Volume II--Advanced Features (7th Edition) and I'm hitting a classpath issue that I cannot figure out. Would anyone know what the solution is here?
The example is a simple example where the class WarehouseClient.java simply makes a call via RMI to run a method on WarehouseServer.java that returns a value. The code for this example is listed below. A webserver called NanoHTTPD.java is used to dynamically deliver class files.
The file NanoHTTPD.java is an embeddable HTTP server which I got from here http://elonen.iki.fi/code/nanohttpd/ , so I have not listed the code for that. All the other relevant code to reproduce this is listed at the bottom.
Here is the directory structure that I have:
E:\RMI-EXAMPLE-1
+---core
+---java
+---book
+---chpt10
+---example
NanoHTTPD$1.class
NanoHTTPD$HTTPSession.class
NanoHTTPD$Response.class
NanoHTTPD.class
NanoHTTPD.java
Warehouse.class
Warehouse.java
WarehouseClient.class
WarehouseClient.java
WarehouseImpl.class
WarehouseImpl.java
WarehouseServer.class
WarehouseServer.java
Here are the commands I run:
* C:\rmiregistry
* E:\RMI-EXAMPLE-1\java -cp . core.java.book.chpt10.example.NanoHTTPD 8080
* E:\RMI-EXAMPLE-1\java -cp . -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer
* E:\RMI-EXAMPLE-1\java -cp .java -cp . core.java.book.chpt10.example.WarehouseClient
This works and the WarehouseClient gets the value back from the WarehouseServer.
Now, here is my problem. If I make a small change to the structure of my directories, as follows, it stops working. All I have done is put my core Java package into a directory called classes. So instead of E:\RMI-EXAMPLE-2 being the root of the package, the directory E:\RMI-EXAMPLE-2\classes is the root directory.
E:\RMI-EXAMPLE-2
+---classes
+---core
+---java
+---book
+---chpt10
+---example
NanoHTTPD$1.class
NanoHTTPD$HTTPSession.class
NanoHTTPD$Response.class
NanoHTTPD.class
NanoHTTPD.java
Warehouse.class
Warehouse.java
WarehouseClient.class
WarehouseClient.java
WarehouseImpl.class
WarehouseImpl.java
WarehouseServer.class
WarehouseServer.java
Here are the commands I run:
* C:\rmiregistry
* E:\RMI-EXAMPLE-2\java -cp classes core.java.book.chpt10.example.NanoHTTPD 8080
* E:\RMI-EXAMPLE-2\java -cp classes -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer
But the WarehouseServer throws an exception that it cannot find the Warehouse.class file - I've listed the exception below. Which is strange as I've included the classes directory on the classpath, so why can't it find the class?
Any ideas why this class cannot be found?
Thanks,
Sean.
Constructing server implementation...
Binding server implementaiton to registry...
Exception in thread "main" javax.naming.CommunicationException [Root exception is java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: core.java.book.chpt10.example.Warehouse]
at com.sun.jndi.rmi.registry.RegistryContext.bind(RegistryContext.java:126)
at com.sun.jndi.toolkit.url.GenericURLContext.bind(GenericURLContext.java:208)
at javax.naming.InitialContext.bind(InitialContext.java:400)
at core.java.book.chpt10.example.WarehouseServer.main(WarehouseServer.java:17)
Caused by: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: core.java.book.chpt10.example.Warehouse
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:396)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:250)
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
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.bind(Unknown Source)
at com.sun.jndi.rmi.registry.RegistryContext.bind(RegistryContext.java:120)
... 3 more
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: core.java.book.chpt10.example.Warehouse
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:386)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:250)
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: core.java.book.chpt10.example.Warehouse
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:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:711)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:655)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:592)
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:238)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
... 12 more
package core.java.book.chpt10.example;
import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class WarehouseServer {
public static void main(String[] args) throws RemoteException, NamingException {
System.out.println("Constructing server implementation...");
WarehouseImpl centralWarehouse = new WarehouseImpl();
System.out.println("Binding server implementaiton to registry...");
Context namingContext = new InitialContext();
namingContext.bind("rmi:central_warehouse", centralWarehouse);
System.out.println("Waiting for invocations from clients...");
}
}
package core.java.book.chpt10.example;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
public class WarehouseImpl extends UnicastRemoteObject implements Warehouse {
private HashMap<String, Double> prices;
protected WarehouseImpl() throws RemoteException {
prices = new HashMap<String, Double>();
prices.put("Blackwell Toaster", 24.95);
prices.put("ZapXpress Microwave Oven", 49.95);
}
@Override
public double getPrice(String description) throws RemoteException {
Double price = prices.get(description);
return price == null ? 0 : price;
}
}
package core.java.book.chpt10.example;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Warehouse extends Remote {
double getPrice(String description) throws RemoteException;
}
package core.java.book.chpt10.example;
import java.rmi.RemoteException;
import java.util.Enumeration;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingException;
public class WarehouseClient {
public static void main(String[] args) throws NamingException, RemoteException {
Context namingContext = new InitialContext();
System.out.print("RMI registry bindings: ");
Enumeration<NameClassPair> e = namingContext.list("rmi://localhost/");
while(e.hasMoreElements()){
System.out.println(e.nextElement().getName());
}
String url = "rmi://localhost/central_warehouse";
Warehouse centralWarehouse = (Warehouse) namingContext.lookup(url);
String descr = "Blackwell Toaster";
double price = centralWarehouse.getPrice(descr);
System.out.println(descr + ":" + price);
}
}
Edited by: 841344 on Mar 2, 2011 11:47 PM
Edited by: 841344 on Mar 2, 2011 11:48 PM
Edited by: 841344 on Mar 2, 2011 11:50 PM