aspose file tools*
The moose likes Distributed Java and the fly likes Classpath Issue Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Distributed Java
Bookmark "Classpath Issue" Watch "Classpath Issue" New topic
Author

Classpath Issue

Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

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 WarehouseClient 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:


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


The 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.




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.














SCJP (1.4 | 5.0), OCJP (6.0), OCMJD
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5597
    
  15

It's all about the directory structure in my opinion. So you have to execute from the correct current directory. If the directory "classes" is a child of directory "RMI-EXAMPLE-2" and you execute the java command from E, then the correct statement to start the server would be:

java -cp RMI-EXAMPLE-2/classes -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer

Anyhow when I try to start the WarehouseServer with correct classpath settings (with regard to the current directory) the program runs without exception.


SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
http://www.javaroe.be/
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Ah, darn, I made a mistake in my initial post with regards to the location the Java.exe is run from. I have updated. It should have read:

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


Running the server from "E:\RMI-EXAMPLE-2\" and setting the classpath to "classes" fails to work and I get the exception originally mentioned.
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Roel De Nijs wrote:It's all about the directory structure in my opinion. So you have to execute from the correct current directory. If the directory "classes" is a child of directory "RMI-EXAMPLE-2" and you execute the java command from E, then the correct statement to start the server would be:

java -cp RMI-EXAMPLE-2/classes -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer

Anyhow when I try to start the WarehouseServer with correct classpath settings (with regard to the current directory) the program runs without exception.


Hmmm...this is strange. Even when I try as you suggested Roel I get the exception. So I ran the following command from the directory "E:\"

java -cp RMI-EXAMPLE-2/classes -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer

I'm running on Windows XP using this version of Java:

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode)
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5597
    
  15

I ran your example again and had no problems.

In my current directory (C:\java\workspace) I have a "RMI" folder and inside this directory I have a "bin" folder containing the class files.

C:\java\workspace>java -cp bin -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer
Exception in thread "main" java.lang.NoClassDefFoundError: core/java/book/chpt10/example/WarehouseServer
Caused by: java.lang.ClassNotFoundException: core.java.book.chpt10.example.WarehouseServer
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: core.java.book.chpt10.example.WarehouseServer. Program will exit.

C:\java\workspace>java -cp RMI/bin -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer
Constructing server implementation...
Binding server implementaiton to registry...
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Hmmm. Thanks for testing that Roel. I replicated your setup and I still get the same exception thrown (see below).

What command are you using to running to start the RMI registry and webserver?

I am using:

* C:\java\workspace>java -cp RMI/bin core.java.book.chpt10.example.NanoHTTPD 8080
* C:\rmiregistry

I wonder is there some networking issue at play on my side?



C:\java\workspace>java -cp RMI/bin -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer

Constructing server implementation...
Binding server implementaiton to registry...
Exception in thread "main" javax.naming.CommunicationException [Root exception is java.rmi.ServerException: RemoteException occurr
ed 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
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

I disconnected myself from my network\internet, rebooted, and ran all the commands again. Same problem, the same exception is getting thrown.

This is very strange, I'm not sure what to try now.

The webserver is providing the class file. I can see this from the command prompt for the webserver after I start WarehouseServer.

Any ideas of what to try?


C:\java\workspace>java -cp RMI/bin core.java.book.chpt10.example.NanoHTTPD 8080
NanoHTTPD 1.21 (C) 2001,2005-2011 Jarno Elonen and (C) 2010 Konstantinos Togias
(Command line options: [port] [--licence])

Now serving files in port 8080 from "C:\java\workspace"
Hit Enter to stop.

GET '/core/java/book/chpt10/example/Warehouse.class'
HDR: 'connection' = 'keep-alive'
HDR: 'accept' = 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2'
HDR: 'host' = 'localhost:8080'
HDR: 'user-agent' = 'Java/1.6.0_22'
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

This is crazy! Just to confirm I am not going mad. I tried the commands from my first example using your setup Roel, as follows

C:\>rmiregistry
C:\java\workspace\RMI\bin>java -cp . core.java.book.chpt10.example.NanoHTTPD 8080
C:\java\workspace\RMI\bin>java -cp . -Djava.rmi.server.codebase=http://localhost:8080/ core.java.book.chpt10.example.WarehouseServer


The WarehouseServer starts fine and throws no exception.

The two main things I see mentioned when RMI is not working is

1) Security issues
2) Classpath issues

I'm ruling out security, as the example above works, so it couldn't be security issues?

That leaves me with a classpath issue, but I can't see what the issue is? Any ideas folks?

Roel, I'm presuming when you are running the commands, that the CLASSPATH variable does not contain a path to your class files for this example?
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5597
    
  15

Hi Sean,

To be honest I ran the code without using this NanoHTTPD server. Shame on me As a side note you are making things more complex than needed: using a http server to serve your class files. I guess it just makes part of your learning part

I tried it now completely with the NanoHTTPD and I got it to work. I think you have to make sure that this http server is serving the files from the correct directory. So again with my setup:

1. start rmiregistry
2. start the http server
C:\java\workspace\RMI\bin>java -cp . core.java.book.chpt10.example.NanoHTTPD 8081 (it's really important that you serve files from the correct directory: not "workspace", not "workspace/RMI", but "workspace/RMI/bin" is the correct directory for serving your class files)
Now serving files in port 8081 from "C:\java\workspace\RMI\bin"
Hit Enter to stop.

3. run the WarehouseServer
C:\java\workspace\RMI\bin>java -cp . -Djava.rmi.server.codebase=http://localhost:8081/ core.java.book.chpt10.example.WarehouseServer
Constructing server implementation...
Binding server implementaiton to registry...
Waiting for invocations from clients...

4. run the WarehouseClient
C:\java\workspace\aclvb\RMI\bin>java -cp . core.java.book.chpt10.example.WarehouseClient
RMI registry bindings: central_warehouse
Blackwell Toaster:24.95


Hope it helps!
Good luck!
Kind regards,
Roel
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5597
    
  15

Sean Keane wrote:This is crazy! Just to confirm I am not going mad.

No, you are not going mad You just made sure the http server is serving files from the correct directory, namely C:\java\workspace\RMI\bin. If you start the server from any other directory, the WarehouseServer class will not be found. So it's a hidden classpath issue, because you want to use a http server to serve the files you need to start the WarehouseServer
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Ah, legend! Thanks Roel. I guess it required a bit more playing around on my behalf.

The problem seems to be as you reported - you need to start the webserver in the root directory of Java package containing the classes to be served, otherwise the webserver cannot find them when requested for them.

In more concrete terms:
- I was starting my webserver in the directory E:\RMI-Example-2
- The path to the class being requested was E:\RMI-Example-2\classes\core\java\book\chpt10\example\Warehouse.class
- The webserver got a request for '/core/java/book/chpt10/example/Warehouse.class'
- The webserver was looking at the following location 'E:/RMI-Example-2/core/java/book/chpt10/example/Warehouse.class' as the webserver is set up to start looking from the root of the directory from it was launched from i.e. E:\RMI-Example-2

- Now, start the webserver in the directory E:\RMI-Example-2\classes
- The webserver once again gets a request for '/core/java/book/chpt10/example/Warehouse.class'
- But this time it is looking at the following location 'E:/RMI-Example-2/classes/core/java/book/chpt10/example/Warehouse.class' , and it successfully finds the file

Just for my own curiosity, I actually ran the WarehouseServer from the directory E:\RMI-Example-2 to rule out the problem being a classpath issue with the WarehouseServer class, and to see if it was just a problem with the webserver.

I ran the following and all commands ran successfully without any exception being thrown:

* C:\>rmiregistry
* E:\RMI-Example-2\classes>java -cp . 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
* E:\RMI-Example-2>java -cp classes core.java.book.chpt10.example.WarehouseClient


So, I conclude the problem is just with the webserver - it needs to be started from the root directory containing the Java package.

Problem solved! Thanks again Roel, appreciate the help.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Classpath Issue