Search code examples
javarmirpc

Java RMI client tries to load implementation instead of interface


I have a problem with a RMI clients class loading behaviour:

My RMI Server side application exports a ISessionFactory object with a single method:

ISessionToken createSession(String username, String password) throw RemoteException;

The ISessionFactory extends Remote, ISessionToken is Serializeable.

I have three projects: Client, Server (contains *Impl) and Facade (contains ISession*).

The server starts up fine and I can lookup the ISessionFactory. For test purposes I added a doSomething method which prints out a string via System.out at the server side, this also works fine. A call to createSession() however does not, but gives the exception:

Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.lang.ClassNotFoundException: rmiserver.SessionTokenImpl (no security manager: RMI class loader disabled)
   at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:198)
   at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
   at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
   at com.sun.proxy.$Proxy0.createSession(Unknown Source)
   at rmiclient.Client.main(Client.java:14)
 Caused by: java.lang.ClassNotFoundException: 
   rmiserver.SessionTokenImpl (no security manager: RMI class loader disabled)
   at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:396)
   at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:186)
   at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:637)
   at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:264)
   at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:214)
   at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
   at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
   at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
   at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
   at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
   at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:326)
   at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:175)
   ... 4 more

I understand that without export of ISessionToken it will be serialized and passed to the client, so I have to validate every session token passed to the server.

What I don't understand is that the client feels the need to load the Impl class of the token. As far as I am concerned it should be doing fine by knowing the interface? What am I missing?


Solution

  • I understand that without export of ISessionToken it will be serialized and passed to the client.

    Correct.

    What I don't understand is that the client feels the need to load the Impl class of the token.

    Because you didn't export it, so it will be serialized and passed to the client. You just said so yourself.

    As far as I am concerned it should be doing fine by knowing the interface?

    Only if you export it. Even then, the client actually receives a stub which implements the interface. You can't just send around an interface without something that implements it.

    What am I missing?

    You didn't export it.