Web Start & RMI (Stub Class not found)

S

swebb99

Hi,

I have a client application that uses RMI and works fine. However when
run as a WebStart application it throws a ClassNotFound exception when
it tries to get a handle on a remote stub from the server.

The code I use is

Registry registry = LocateRegistry.getRegistry("localhost", 1234);
// lookup the factory
universe = (IMyFactory) registry.lookup("rmi:///MyManagerFactory");

It throws the exception on the lookup. My jnlp file has all permisions
set and from debugging the input in the code above is the same if run
from an app or webstart.

Any ideas at all ?

Thanks

Steve
 
A

Andrew Thompson

I have a client application that uses RMI and works fine. However when
run as a WebStart application it throws a ClassNotFound exception when
it tries to get a handle on a remote stub from the server.

The code I use is

Registry registry = LocateRegistry.getRegistry("localhost", 1234);
// lookup the factory
universe = (IMyFactory) registry.lookup("rmi:///MyManagerFactory");

It throws the exception on the lookup.

The CNFE is occuring for the 'IMyFactory', I take it?
...My jnlp file has all permisions
set and from debugging the input in the code above is the same if run
from an app or webstart.

Any ideas at all ?

- State error output verbatim.
- Tell us what Jar the IMyFactory is supposed to reside in.
- Check it is in there.
- Show us your JNLP (or better still, link to it).

Andrew T.
 
S

swebb99

Andrew said:
The CNFE is occuring for the 'IMyFactory', I take it?


- State error output verbatim.
- Tell us what Jar the IMyFactory is supposed to reside in.
- Check it is in there.
- Show us your JNLP (or better still, link to it).

Andrew T.

Hi Andrew,

Sorry should have put extra details in the original email.

The last line of the code should have read :

niverse = (IMyFactory) registry.lookup("rmi:///MyFactory");

Tthe IMyFactory class is in a jar file know to the client via the jnlp
called IServer.jar however MyFactory and MyFactory_stub classes are in
a jar file called Server.jar and is not available to the client but is
to the server.

The jnlp is : (cut out some none relevant info)

<?xml version="1.0" encoding="UTF-8"?>

<jnlp href="xc.jnlp" spec="1.0+" codebase="http://localhost:8079/xc">
<information>
<title>my app</title>
<vendor>me</vendor>
<homepage href="index.html">
</homepage>
<description>My Application</description>
<description kind="short">My application</description>
<offline-allowed>
</offline-allowed>
</information>
<security>
<all-permissions>
</all-permissions>
</security>
<resources>
<j2se version="1.4" max-heap-size="256m" initial-heap-size="32m">
</j2se>
<jar href="MyApp.jar">
</jar>
<jar href="IServer.jar">
</jar>
</resources>
<application-desc main-class="com.b8.ic2.as.agentsupport">
</application-desc>


The exception trace is

java.rmi.UnmarshalException: error unmarshalling return; nested
exception is:
java.lang.ClassNotFoundException: com.me.MyFactory_Stub
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at com.me.getMyServer(agentsupport.java:3597)
......
......
......
at com.me.main(agentsupport.java:6825)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javaws.Launcher.executeApplication(Unknown Source)
at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
at com.sun.javaws.Launcher.continueLaunch(Unknown Source)
at com.sun.javaws.Launcher.handleApplicationDesc(Unknown Source)
at com.sun.javaws.Launcher.handleLaunchFile(Unknown Source)
at com.sun.javaws.Launcher.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.me.MyFactory_Stub
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 java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader$2.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader.loadClass(Unknown Source)
at sun.rmi.server.MarshalInputStream.resolveClass(Unknown Source)
at java.io_ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io_ObjectInputStream.readClassDesc(Unknown Source)
at java.io_ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io_ObjectInputStream.readObject0(Unknown Source)
at java.io_ObjectInputStream.readObject(Unknown Source)
... 21 more

I'm not sure if I need to setup a codebase or any other config for
webstart when using RMI that perhaps isn't required for a normal client
application.

Thanks

Steve
 
S

swebb99

Andrew said:
The CNFE is occuring for the 'IMyFactory', I take it?


- State error output verbatim.
- Tell us what Jar the IMyFactory is supposed to reside in.
- Check it is in there.
- Show us your JNLP (or better still, link to it).

Andrew T.

I should also mention that if I remove the third '/' out of the url in
the lookup the exception is thrown staight away however with the third
'/' the exception isn't thrown for a few second the app seems to hang
on the lookup call for a while.
 
A

Andrew Thompson

Caused by: java.lang.ClassNotFoundException: com.me.MyFactory_Stub
OK.

The last line of the code should have read :

niverse = (IMyFactory) registry.lookup("rmi:///MyFactory");

Tthe IMyFactory class is in a jar file know to the client via the jnlp
called IServer.jar however MyFactory and MyFactory_stub classes are in
a jar file called Server.jar and is not available to the client but is
to the server.

The only reason I can think that MyFactory_Stub
causes an excpetion at that line is if IMyFactory
inherits from it - does it?

In any case, if a class is referenced in any sense in a
client-side application, it needs to be *available* to the
client(1).
....
Sorry should have put extra details in the original email.

Cool. But note that a post to a usenet newsgroup is a
very different thing to email. Email is not public, not
publicly searchable - and would cost you a lot more. ;-)
The jnlp is : (cut out some none relevant info)

OK.. Normally I tell people to be wary of trimming
details, on the basis that "if you don't know what is
failing. it is hard to identify the relevant parts of the
problem" but your trimming of both the stack trace and
JNLP was a good call. I *think* I have enough details..

To cut to..
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<j2se version="1.4" max-heap-size="256m" initial-heap-size="32m">
</j2se>
<jar href="MyApp.jar">
</jar>
<jar href="IServer.jar">
</jar>
</resources>

...(1) so your <resources> section must include the Jar that
contains 'MyFactory_Stub'. 'Server.jar' must be included here.
...
I'm not sure if I need to setup a codebase or any other config for
webstart when using RMI that perhaps isn't required for a normal client
application.

No. WebStart works the same as native applications and
applets in that respect. I suspect the thing that is complicating
matters here, is that somehow the desktop application already
has access to the 'Server.jar'.

Andrew T.
 
S

swebb99

Andrew said:
The only reason I can think that MyFactory_Stub
causes an excpetion at that line is if IMyFactory
inherits from it - does it?

In any case, if a class is referenced in any sense in a
client-side application, it needs to be *available* to the
client(1).
...


Cool. But note that a post to a usenet newsgroup is a
very different thing to email. Email is not public, not
publicly searchable - and would cost you a lot more. ;-)


OK.. Normally I tell people to be wary of trimming
details, on the basis that "if you don't know what is
failing. it is hard to identify the relevant parts of the
problem" but your trimming of both the stack trace and
JNLP was a good call. I *think* I have enough details..

To cut to..



..(1) so your <resources> section must include the Jar that
contains 'MyFactory_Stub'. 'Server.jar' must be included here.
..

No the stub is in Server.jar but if I am understanding RMI correctly
the remote server should pass the interface object to the client and
the stub only needs to be in a jar that the server know about when the
system starts up ?

It works this way when running as an app ! I checked the class path for
the client application and it doesn't contain the server.jar.


Thanks Steve
 
A

Andrew Thompson

No the stub is in Server.jar but if I am understanding RMI correctly
the remote server should pass the interface object to the client and
the stub only needs to be in a jar that the server know about when the
system starts up ?

Umm... I might have been wrong. Truth is - I have no
direct experience with RMI. Perhaps one of the RMI
gurus will happen by, shortly.

Andrew T.
 
S

swebb99

The interesting thing is if I call list() on the registry it returns
one entry :

rmi://MyFactory

So why the hell doesn't the call to lookup() on this object work !. I
would expect it to return the IMyFactory object (which extents Remote)
and which MyFactory implements !

I've totally run out of idea's why web start won't let this work but it
runs fine as a normal app :(

Steve
 
M

Matt Humphrey

No the stub is in Server.jar but if I am understanding RMI correctly
the remote server should pass the interface object to the client and
the stub only needs to be in a jar that the server know about when the
system starts up ?

It works this way when running as an app ! I checked the class path for
the client application and it doesn't contain the server.jar.

Andrew's first guess that the client when run directly probably has
surreptitious access to the stub files is probably correct. However, RMI
also has a mode whereby an RMI classloaded loaded by the client will
automatically retrieve the stub files. This may or may not have been
correctly configured.

Presuming that you're not relying on the RMI classloader, check to see that
all of the classes supporting IMyFactory and MyFactory_Stub are present on
the client, including those reachable only by reference. An RMI
inconvenience is that it may report the wrong class being missing.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4250650 Perhaps the stub
refers to something that aren't even expecting to use--that class must still
be present (or accessible) to the client.

This thread may be helpful
http://forum.java.sun.com/thread.jspa?threadID=672210&messageID=3928354

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
S

swebb99

Matt said:
Andrew's first guess that the client when run directly probably has
surreptitious access to the stub files is probably correct. However, RMI
also has a mode whereby an RMI classloaded loaded by the client will
automatically retrieve the stub files. This may or may not have been
correctly configured.

Presuming that you're not relying on the RMI classloader, check to see that
all of the classes supporting IMyFactory and MyFactory_Stub are present on
the client, including those reachable only by reference. An RMI
inconvenience is that it may report the wrong class being missing.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4250650 Perhaps the stub
refers to something that aren't even expecting to use--that class must still
be present (or accessible) to the client.

This thread may be helpful
http://forum.java.sun.com/thread.jspa?threadID=672210&messageID=3928354

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/


Great thanks for the info Matt. I'll double check again the path that
the app is using when run standalone and I'll also doube check the
interface and make sure Im not missing any classes that are required.
Thats one hell of a bug not to be fixed !!!!


Cheers

Steve
 
S

swebb99

By the way I am right in thinking that the classpath of the client only
needs to have access to the interface class to be used for the remote
object. They classpath of the server however needs to have the proper
rmi class and the associated stub as well as the interface class. ?

Thanks

Steve
 
M

Matt Humphrey

By the way I am right in thinking that the classpath of the client only
needs to have access to the interface class to be used for the remote
object. They classpath of the server however needs to have the proper
rmi class and the associated stub as well as the interface class. ?

If you're not using the RMI Classloader, the client needs the interface
classes, the stub classes and all other shared classes. The server needs the
interface classes, all shared classes and the implementation classes. I
don't think it needs the stubs, but I often give the server everything
except the GUI. I usually set out an architecture that makes it clear which
projects fall into which of the categories so its clear where they go.

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
E

EJP

By the way I am right in thinking that the classpath of the client only
needs to have access to the interface class to be used for the remote
object. They classpath of the server however needs to have the proper
rmi class and the associated stub as well as the interface class. ?

No. The stub *and* the remote interface *and* anything it depends on,
and the closure of that, need to be available to both the client and the
registry, either via their classpaths or the codebase feature.

Another thing: when you are using Registry as opposed to Naming, you
don't need to specify URLs, just binding names. It will work (because
anything will work as a name to Registry) but it's not necessary. The
URLs are specified to Naming so it knows where to look.
 
S

swebb99

Matt said:
If you're not using the RMI Classloader, the client needs the interface
classes, the stub classes and all other shared classes. The server needs the
interface classes, all shared classes and the implementation classes. I
don't think it needs the stubs, but I often give the server everything
except the GUI. I usually set out an architecture that makes it clear which
projects fall into which of the categories so its clear where they go.

Matt Humphrey (e-mail address removed) http://www.iviz.com/

Hi,

Thanks for the replies.

I've gone through the code and setting trying to find the problem but
come up with nothing so far. Things I've ticked off the list are :

1) Webstart is using Java 1.4 which I want it to.
2) The jnlp for the client specifies a resource for the jar file
containing the interface class but not the actual class or stub class
3) The application when run standalone only has the same jars in its
classpath as specified in the jnlp file.
3) The server class path contains referenced to all the jars so the
interface, real object and stub
4) The interface class doesn't contain any params or return types that
the client doesn't have any interfaces for. Infact there are no params
on the methods just return types and they are all rmi interface classes
that the client has access to in the interface jar file.
5) I tried playing around with the rmi server codebase setting in the
jnlp file but didn't get anywhere with it other than if I gave it some
duff setting the ClassNotFound exception was thrown straight away
rather than after a little while.
6) I tried using Naming.lookup instead of lookup off the registry. This
just gave me a Not bound exception !!!

I suppose I better have a look at the server code and see how that
works. I was told some interesting info and that is that a web server
isn't used as such and the rmiregistry isn't started manually. The
server is one class that starts the registry programatically and also
sets itself up as a server. I need to have a look and figure it out.
Checking the command line that starts it it doesn't set up any codebase
settings that seems a bit strange ?? However it communicated with the
app if run standalone !

All very odd what the hell is the difference when running jnlp :(

Thanks

Steve
 
S

swebb99

Hi,

Thanks for the replies.

I've gone through the code and setting trying to find the problem but
come up with nothing so far. Things I've ticked off the list are :

1) Webstart is using Java 1.4 which I want it to.
2) The jnlp for the client specifies a resource for the jar file
containing the interface class but not the actual class or stub class
3) The application when run standalone only has the same jars in its
classpath as specified in the jnlp file.
3) The server class path contains referenced to all the jars so the
interface, real object and stub
4) The interface class doesn't contain any params or return types that
the client doesn't have any interfaces for. Infact there are no params
on the methods just return types and they are all rmi interface classes
that the client has access to in the interface jar file.
5) I tried playing around with the rmi server codebase setting in the
jnlp file but didn't get anywhere with it other than if I gave it some
duff setting the ClassNotFound exception was thrown straight away
rather than after a little while.
6) I tried using Naming.lookup instead of lookup off the registry. This
just gave me a Not bound exception !!!

I suppose I better have a look at the server code and see how that
works. I was told some interesting info and that is that a web server
isn't used as such and the rmiregistry isn't started manually. The
server is one class that starts the registry programatically and also
sets itself up as a server. I need to have a look and figure it out.
Checking the command line that starts it it doesn't set up any codebase
settings that seems a bit strange ?? However it communicated with the
app if run standalone !

All very odd what the hell is the difference when running jnlp :(

Thanks

Steve

Right I finally got it working but only by putting the stub files in a
jar that is referenced via the jnlp. It just wouldn't work without
this. I looked at everything mentioned I could find on the web and it
all looked correct. Strange !!! I'm now thinking that there is some bug
in the api's somewhere ?

Thanks for all replies.
 

tlc

Joined
Aug 29, 2008
Messages
1
Reaction score
0
I had the same problem. The RMI client works as a standalone app, yet failed when deployed in a webapp. It did turn out to be the case of missing necessary jars in the webapp lib. As a standalone app, an exception was thrown to indicate what it was looking for. In the webapp, however, the call to Naming.lookup just hangs.

Thanks for the tip that helped me dig further and uncover this problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,786
Latest member
EmilioGuru

Latest Threads

Top