Non-blocking notification mechanism via RMI

K

kittyhawk

Hi folks,

I want to trigger a method on some remote object via RMI to process
some data. But the client invoking the method should not block while
the remote object is processing. Instead, I would like the remote
object to notify the client as soon as the job is done.

Of course, one could hand over the client's reference so that the
remote object could invoke a client's method. But, first, the server
will block as long as the client is doing something in its called
method, and second, the client has to be accessible via RMI, too. The
latter fact even causes that the method is actually processed on the
server instead of on the client side. So, any System.out.println() will
show up on the server, not on the client.
I cann't span separate threads to do the callbacks. That's set. I have
also looked into some design patterns, but didn't find anything
suitable for RMI problems at first glance.

All I want is a simple notification mechanism. Non-blocking on the
client, non-blocking on the server. Just a ping from the server to the
client, like "Hey, job is done. Fetch your result."

Thanks in advance for any help!

Thomas
 
A

Alex Molochnikov

kittyhawk said:
Hi folks,

I want to trigger a method on some remote object via RMI to process
some data. But the client invoking the method should not block while
the remote object is processing. Instead, I would like the remote
object to notify the client as soon as the job is done.

Launch a new thread on the server from the method called by the client, and
return immediately. Any processing to be done by the request from the client
should be done in that new thread.
Of course, one could hand over the client's reference so that the
remote object could invoke a client's method. But, first, the server
will block as long as the client is doing something in its called
method,

Same deal on the client: start a new thread and return.
...and second, the client has to be accessible via RMI, too. The
latter fact even causes that the method is actually processed on the
server instead of on the client side. So, any System.out.println() will
show up on the server, not on the client.

Any method called on the client's objects (i.e. those that exist in the
client's address space) will be executed on the client. What makes you think
that you are seeing the client's System.out stream on the server?
I cann't span separate threads to do the callbacks. That's set.

And the reason is?

If you want the server to send a message to the client not as a response to
the client's call, but originating from the server, and want to use RMI for
this, the callback is your only choice. Essentially, you want to turn your
client into an improvised server, that will listen to the "real" server's
call - this is exactly what the callback mechanism does.
I have also looked into some design patterns, but didn't
find anything suitable for RMI problems at first glance.

All I want is a simple notification mechanism. Non-blocking on the
client, non-blocking on the server. Just a ping from the server to the
client, like "Hey, job is done. Fetch your result."

If you want to stay out of J2EE, the RMI can do this, but only if you are
willing/can use threads. Otherwise, you could try JMS - its asynchronous
messaging is suited perfectly for your task.

AM
 
E

EJP

kittyhawk said:
I want to trigger a method on some remote object via RMI to process
some data. But the client invoking the method should not block while
the remote object is processing. Instead, I would like the remote
object to notify the client as soon as the job is done.

Of course, one could hand over the client's reference so that the
remote object could invoke a client's method. But, first, the server
will block as long as the client is doing something in its called
method, and second, the client has to be accessible via RMI, too. The
latter fact even causes that the method is actually processed on the
server instead of on the client side. So, any System.out.println() will
show up on the server, not on the client.

That would only happen if you supplied a Serializable client callback so
its code executed at the server. You should be supplying an *exported
remote object* as the callback (e.g. extends UnicastRemoteObject), just
like the server.
I cann't span separate threads to do the callbacks. That's set.

You don't have to do that to execute the callback, but you do have to
start a new thread at the server to handle the actual *task* so that the
remote method implementation can return immediately to the client. That
thread will also execute the server side of the callback when it is done.

However I would question why you (a) must use RMI *and* (b) must have
this fully asynchronous model. The requirements are clearly in conflict.
You can do it but it's not a great fit.
 
C

Chris Uppal

kittyhawk said:
All I want is a simple notification mechanism. Non-blocking on the
client, non-blocking on the server. Just a ping from the server to the
client, like "Hey, job is done. Fetch your result."

If you don't want remote METHOD CALL semantics, why are you using RMI at all ?

-- chris
 
K

kittyhawk

Alex said:
Launch a new thread on the server from the method called by the client, and
return immediately. Any processing to be done by the request from the client
should be done in that new thread.


Same deal on the client: start a new thread and return.


Any method called on the client's objects (i.e. those that exist in the
client's address space) will be executed on the client. What makes you think
that you are seeing the client's System.out stream on the server?


And the reason is?

If you want the server to send a message to the client not as a response to
the client's call, but originating from the server, and want to use RMI for
this, the callback is your only choice. Essentially, you want to turn your
client into an improvised server, that will listen to the "real" server's
call - this is exactly what the callback mechanism does.


If you want to stay out of J2EE, the RMI can do this, but only if you are
willing/can use threads. Otherwise, you could try JMS - its asynchronous
messaging is suited perfectly for your task.

AM
I simply can't use a separate thread for each client task because my
component must also work on devices with limited memory and weak
processing power. Even the reduced overhead by using a thread pool is
way too much. All I can use is one thread within the remote object,
i.e. the server.
But I will look into JMS. Probably it will solve my headache...
 
L

Leon Lambert

You don't need one thread per client. You just need 1 worker thread.
Have it pull requests from a synchronized queue. Have the RMI calls post
to the queue in a synchronized fashion. This is a pretty common way of
handling problems like this whether they are local or remote.

Hope this helps
Leon Lambert
 
K

kittyhawk

That makes sense. But how do I notify the client when the job is done?
My first idea:
Let the client call stub.someMethod(xzy, this) where xyz is the actual
argument needed for the computation, and this is the refrenze to the
client object.
As soon as the job is done, the remote object could then call
((MyClientClass).processingJob.getReferenzeToClientObj()).notiy()

This callback has to go through RMI back to the client. So, the client
has to implement the Remote interface. Am I right? When I did this, it
worked, but any System.out.println() showed up on the remote side
instead of on the client side. Additionally, the remote object blocks
until the notify() method returns. Since I cann't assume a "frindly"
client, the notify method coul never return. Even if a use a separat
for each callback, the thread will wait as long as notify() is
executed. If notify() calculates a while(true){}, a bunch of waiting
threads will eat up my resources.

Probably I should say it more clearly: The problem is that I cannot
assume any time bound. Neither on the server side, nor on the client.
The server object has to be accessible via RMI, the client don't. A
worker thread on the server side fetching job for a queue is okay. But
I still don't see how the remote object notifies the client without
blocking until notify() returns.
 
P

Patrick May

kittyhawk said:
I want to trigger a method on some remote object via RMI to process
some data. But the client invoking the method should not block while
the remote object is processing. Instead, I would like the remote
object to notify the client as soon as the job is done. [ . . . ]
All I want is a simple notification mechanism. Non-blocking on the
client, non-blocking on the server. Just a ping from the server to
the client, like "Hey, job is done. Fetch your result."

A couple of people have mentioned JMS elsethread; that may be a
good fit for your requirements. Another Java technology to consider
is Jini (http://www.jini.org). What you seem to want to do could be
done with a simple master-worker pattern via a JavaSpace.

Regards,

Patrick
 
L

Leon Lambert

Its fairly easy to create a callback mechanism. Doing a google search
should find lots of examples. I'll paste in some snippits of somthing i
did that hopefully points you in the right direction. The remote
software would provide the callback object to the server. If you are
saying that you don't want to use a remote callback mechanism then there
really isn't much you can do but block. Another approach is to have the
server post answers to a client specific queue and have the client
periodically remotely dequeue answers. This is not as clean as callbacks
but is a bit simpler to implement.

Following is the interface to me callback object
interface EventCallbackInterface extends Remote
{
/**
This will tell the client that the server is still alive
* @throws RemoteException will be thrown if a network error occurs
*/
public void deadManCheck() throws RemoteException;
/**
An object has changes has occured
* @param index is an unique event identifier
* @param reason is the reason for the change
* @param record is which record changed
* @throws RemoteException will be thrown if a networking error occurs
*/
public void handleChange(int index,int reason,RtdrRecordData
record) throws RemoteException;
}


Following is the class the implements it.
/**
* This class provides a callback mechanism from an rtdr server to the client
* @author Leon Lambert
* @version 1.00, 08/01/98
* @since JDK1.2
*/
class EventCallbackImpl extends UnicastRemoteObject implements
EventCallbackInterface
{
/**
* Rtdr that is managing this connection
*/
RemoteRtdr remoteRtdr;

/**
* Allocate an instance to manage callbacks to this client
* @param remoteRtdr is an interface to the remote rtdr
* @exception RemoteException will be thrown for RMI errors
*/
public EventCallbackImpl(RemoteRtdr remoteRtdr) throws RemoteException
{
this.remoteRtdr = remoteRtdr;
}

/**
* The is called to provide a deadman point. This will fail on the server
if i'm dead.
* @exception RemoteException will be thrown for RMI errors
*/
public void deadManCheck() throws RemoteException
{
}

/**
* Callback point to handle changes that this client has subscribed to
* @param index for the event reference
* @param reason for the change
* @param record is the one with the change
* @exception RemoteException will be thrown for RMI errors
*/
public void handleChange(int index,int reason,RtdrRecordData record)
throws RemoteException
{
try
{
RemoteOHCRefNum remoteOHCRefNum = remoteRtdr.findEvent(index);
remoteOHCRefNum.handleChange(record,reason);
}
catch (Exception ex)
{
}
}
}
 

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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top