RMI callback with JAVA1.5
Since the version 1.5 we have no need to distribute the stub to all the clients.
It's a great feature, but I need to perform a callback from the server to the client, in this case I need to perform a call to UnicastRemoteObject.exportObject()
client-side before calling the registration method exposed by the server, and the stub of the class implementing the callback interface must be placed in the classpath of the server, is it true? Is there any other methos to perform an RMI-callback?
To be clear as much as possible I have this interface exposed by the server
publicinterface Servicesextends Remote
{
public Map<String, ApplicationStatus> applicationsList ()throws RemoteException;
public ApplicationStatus startApplication (String identifier)throws RemoteException;
public ApplicationStatus stopApplication (String identifier)throws RemoteException;
publicint exitCode (String identifier)throws RemoteException;
/**
* This method, as the name says, is used by the client to register the listener to some server-side event.
* @param callback
* @throws RemoteException
*/
publicvoid registerForNotification (ExitCodeCallback callback)throws RemoteException;
}
and the interface of the callback is
publicinterface ExitCodeCallbackextends Remote
{
publicvoid notifyExitCode (ExitCodeEvent event)throws RemoteException;
}
On the server side I export the services in the registry
Services servicesServerSide =new MyServices();
Services services = (Services) UnicastRemoteObject.exportObject(servicesServerSide , 0);
and on the client I perform a lookup of the services
Registry registry = LocateRegistry.getRegistry("192.168.0.1", 1099);
Services services = (Services) registry.lookup("SERVICES");
I export my implementation of the interface
publicclass ClientExitCodeCallbackimplements ExitCodeCallback
{
publicvoid notifyExitCode (ExitCodeEvent event)
{
System.out.println(event.asString());
}
}
through the code
services.registerForNotification(remoteCallback);
but on the calling of this method I obtain a ServerSideException
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: it.sogei.jscheduler.rmi.client.ClientExitCodeCallback_Stub
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:325)
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:466)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
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:126)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:179)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.registerForNotification(Unknown Source)
at it.sogei.jscheduler.rmi.client.StartClient.main(StartClient.java:45)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: it.sogei.jscheduler.rmi.client.ClientExitCodeCallback_Stub
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:285)
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:466)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: it.sogei.jscheduler.rmi.client.ClientExitCodeCallback_Stub
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:246)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:430)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1544)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:290)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:279)
... 6 more
Is it true all of the above?

