File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Distributed Java and the fly likes Java RMI and MyEclipse Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Distributed Java
Bookmark "Java RMI and MyEclipse" Watch "Java RMI and MyEclipse" New topic
Author

Java RMI and MyEclipse

Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
I hope that someone else has already done the suffering to learn how to do this.

I am starting to experiment with writing Java RMI client and server code. I started with the Oracle demo where the client makes a request for the value of pi to an arbitrary number of places, and the server computes it and passes it back to the client.

I was able to get this working using javac and jar from the command line (which involves bundling the class files into a JAR, copying it over to the tomcat webapps directory). My guess is that there is some way to set this up in MyEclipse so that it compiles and redeploys--but it is not exactly obvious how to set this up. Help!

I am using MyEclipse 9.1, Tomcat 5.0.28 (please don't laugh; we're working on moving into modern times, and getting rid of our papyrus and clay tablets).

To simplify figuring out what is broken, I have taken the Oracle tutorial code and put in a single project, divided into three packages: client, compute, and engine. I can start the server (engine) with the following DOS batch file:



I can run the client side from the command line with the following DOS batch file:



where %1% is the parameter passed to the batch file specifying the number of digits of pi to have the server side calculate and return.


Then I tried to get MyEclipse to start the server in pretty much the equivalent way using the Run Configurations...:

Main.class: engine.ComputeEngine
Classpath: default classpath and c:\tomcat5\webapps\rmi\compute.jar
Environment: java.rmi.server.codebase=file:/c:\tomcat5\webapps\rmi\compute.jar
java.security.policy=server.policy

Code:
ComputeEngine exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: compute.Compute
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
at sun.rmi.transport.Transport$1.run(Transport.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
at java.lang.Thread.run(Thread.java:595)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:343)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at engine.ComputeEngine.main(ComputeEngine.java:29)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: compute.Compute
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
at sun.rmi.transport.Transport$1.run(Transport.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: compute.Compute
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:242)
at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:707)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:651)
at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:588)
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:1494)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1457)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
... 9 more


As you can see, there is a ClassNotFoundException: compute.Compute

I'm hard pressed to see why. If I do a jar -tf c:\tomcat5\webapps\rmi\compute.jar I get:




Any suggestions?
Vijitha Kumara
Bartender

Joined: Mar 24, 2008
Posts: 3829

Why are you deploying this to Tomcat as this has no web content at all? Can't you just bring the RMI server up standalone?


SCJP 5 | SCWCD 5
[How to ask questions] [Twitter]
Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
I thought that the Java RMI required a server to be running. It doesn't? The server side of this example is sufficient by itself?

That's actually quite neat, but does not answer the question of why I can't get this work from MyEclipse.
Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
Thanks! Indeed, it does not require Tomcat to be running to work. This is very neat. It still doesn't answer the question of why I can't get this to start from MyEclipse, but any time that I can reduce the number of components required to make something do what it needs, that's a gain.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

Clayton Cramer wrote:I thought that the Java RMI required a server to be running. It doesn't? The server side of this example is sufficient by itself?

That's actually quite neat, but does not answer the question of why I can't get this work from MyEclipse.


Java RMI does require a server to be running. An RMI server. Tomcat is an HTTP server. It doesn't have any RMI support built into it.

To test RMI in eclipse, you have to launch an RMI server from Eclipse OR you have to attach the Eclipse debugger to the RMI server as a remote debugging session (this requires the RMI server to be launched with debugging enabled so that it will open a network port for Eclipse to debug through). Then you launch the client app in Eclipse, You can set breakpoints in both client code and server code, but Eclipse does have to have an up-to-date copy of the server's RMI service source code available so that it will know the proper line numbers.


Customer surveys are for companies who didn't pay proper attention to begin with.
Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
Okay, this helps. Let me ask you a more detailed questions:

"To test RMI in eclipse, you have to launch an RMI server from Eclipse OR you have to attach the Eclipse debugger to the RMI server as a remote debugging session (this requires the RMI server to be launched with debugging enabled so that it will open a network port for Eclipse to debug through)."

It appears that the magic incantation on the server command line arguments is:

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n -Djava.rmi.server.logCalls=true -Dsun.rmi.loader.loglLevel=5 -Dsun.rmi.server.exceptionTrace=true -Dsun.rmi.server.logLevel=5

I am guessing on the logLevel values.

I am still running into the problem with

java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)

This seems to be a security policy problem, which I still have not figured out. I am passing -Djava.security.policy=server.policy, where server.policy is the name of a file containing

grant codeBase "file:/C:/tomcat5/webapps/rmi/-" {
permission java.security.AllPermission;
};

Yes, I am not relying on Tomcat, but that's where the file is.

Should I specify a fully qualified path to where server.policy is located?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

Last time I had a webapp as an RMI client, I think I had a security policy for Tomcat, but not for the RMI Server. Since the RMI server is a stand-alone app, it can pretty much do anything it wants to anyway.

The one thing I can see that I'm not sure of is your URL. The proper syntax, I believe is: "file://C:/tomcat5/webapps/rmi/-". That extra slash after the protocol ID is critical, I believe.

Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
It is unfortunate that the error messages are not a bit more helpful. I have now tried my server.policy file with one, two, and three slashes after file:, and the results are:

One slash:

C:\Documents and Settings\ccramer\Workspaces\MyEclipse 9\rmi-server\src>java -Xd
ebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n -Dj
ava.rmi.server.logCalls=true -Dsun.rmi.loader.loglLevel=5 -Dsun.rmi.server.excep
tionTrace=true -Dsun.rmi.server.logLevel=5 -cp .;c:\tomcat5\webapps\rmi\compute.
jar -Djava.security.manager -Djava.rmi.server.codebase=file:/c:\tomcat5\webapps\
rmi\compute.jar -Djava.security.policy=file:/c:/tomcat5/webapps/rmi/server.polic
y engine.ComputeEngine
Listening for transport dt_socket at address: 8000
Oct 17, 2012 10:21:16 AM sun.rmi.server.UnicastRef newCall
FINE: main: get connection
ComputeEngine exception:
java.security.AccessControlException: access denied (java.net.SocketPermission 1
27.0.0.1:1099 connect,resolve)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkConnect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown S
ource)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown S
ource)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
at sun.rmi.server.UnicastRef.newCall(Unknown Source)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at engine.ComputeEngine.main(ComputeEngine.java:36)

Two slashes:

identical

Three slashes:

identical

One would almost get the impression that it is not even seeing the server.policy file. Perhaps the problem is the -Djava.security.policy= parameter? I suppose that I can try changing the number of slashes there next. And I did, with one, two, and three slashes after file: on the command line arguments, without any change in behavior.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

I found that to start my RMI server, the java.security.policy property needed quotes around its value. And apparently it isn't a URL so you don't need the file: prefix. So not this:



but this:


Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
This is very useful information! Thank you! What about in the server.policy file itself? Currently I have:

grant codeBase "file:///C:/tomcat5/webapps/rmi/-" {
permission java.security.AllPermission;
};

My suspicion is that since the server.policy file is referenced directly (not by a URL) that perhaps the codeBase parameter should also be just a file name. But that does not seem to work any better.
Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
Tim Holloway wrote:he one thing I can see that I'm not sure of is your URL. The proper syntax, I believe is: "file://C:/tomcat5/webapps/rmi/-". That extra slash after the protocol ID is critical, I believe.


It appears from reading http://docs.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html that file:/// (three slashes) is required.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

The file:// protocol was badly described at the beginning, or so I understand, so the required number of slashes is always a questionable item.

The way I look at it, here's how it works.

(1) The protocol part of the URL is "file://" -- with two slashes, just like other protocols you'll be familiar with.

(2) Assuming the file part of the URL is meant to be an absolute path and not a relative path -- the case I've always been dealing with -- then:

(2a) If you're in a Windows environment the file part should start with a drive letter and carry on in the normal way, only with / instead of \ as the separator.

(2b) If you're in a UNIX-like environment the file part should start with a / to denote an absolute path, and carry on in the normal way.

So that's why you'll see people say "use three slashes". The people who wrote the tutorial you linked to were from Sun, a UNIX-oriented company, and quite possibly they didn't want to get into UNIX vs Windows in that level of tutorial. Perhaps they hadn't even tried their examples on a Windows machine.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

Now you know why I was a bit hesitant.

In DOS/Windows, the indication that the path is absolute is a backslash FOLLOWING the drive selector. In most other OS's, the absolute-path marker is the very first character of the path. The double-slashes, as Paul noted, are part of the protocol identification sequence.

So a well-formed absolute path in Windows using the URL notation is "file:///C:/mydir/subdir/file.ext". I have also seen it as "file:///C|/mydir/subdir/file.ext", which is presumably to avoid possible ambiguities using the ":".
Clayton Cramer
Ranch Hand

Joined: Aug 26, 2010
Posts: 41
I found the answer over at http://patriot.net/~tvalesky/easyrmi.html. Here's an example that worked for me:

-Djava.security.policy=c:\rmi\hello\server.policy

Wow! Surprisingly simple!
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

Tim Holloway wrote:So a well-formed absolute path in Windows using the URL notation is "file:///C:/mydir/subdir/file.ext". I have also seen it as "file:///C|/mydir/subdir/file.ext", which is presumably to avoid possible ambiguities using the ":".


And in a completely unrelated situation yesterday evening (using the document() function in XSLT), I found that "file:///C:/..." gets the file I asked for whereas "file://C:/..." gives me error messages that C is an unknown protocol. So: three slashes good, two slashes bad.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Java RMI and MyEclipse