views:

408

answers:

2

I am using some third party library to connect to a server via async protocol and get response back. For example method to get userid by username looks like this:

public int getUserid(String username) {
     int userid = 0;

 connection.call("getUserid", new Responder() {
  public void onResult(final int result) {
   System.out.println("userid: " + result);
   //how to assign received value to userid and return it?
  }
 }, username);

 //wait for response
 while (userid == 0) {
      try{
       Thread.sleep(100);
      } catch (Exception e) {}
     }


     return userid;
}

The problem is I can't assign returned "result" from server response to "userid" variable from the method (in order to return it after). How to solve this? I probably can assign it to some class variable rather than method variable but I want to keep it within method scope so I don't have to deal with concurrency issues.

Thanks.

+1  A: 

If I understand your question correctly, you're asking how you can write a variable from inside an anonymous class.

Anonymous classes can only access final variables, and can't directly "write" them.

A straightforward solution that is "good enough" is to create sort of a ValueBox class with a single value field and a getter and setter. You can then instantiate a new one in the function as a final variable, and have your anonymous class access it. The anonymous class will use its getter and setter to write/read.

The fact that the variable is final just means that you can't aim the reference anywhere else, but you can still change the contents of the referred object from either function.

The bigger problem you are going to have is in waiting until the callback has been called. This sort of wait-sleep might be good enough, but you may want to consider timeouts, threads, etc, depending on what you're trying to achieve.

In addition, this all assumes that you are never going to call this twice on the connection. Otherwise, you need to provide more info to us on your synchronization model.

Here's some sample code:

public int getUserid(String username) {
        final ValueBox<Integer> userid = new ValueBox<Integer>();

        connection.call("getUserid", new Responder() {
                public void onResult(final int result) {
                        System.out.println("userid: " + result);
                        userId.setValue(result);
                        //how to assign received value to userid and return it?
                }
        }, username);

        //wait for response
        while (userid.isEmpty()) {
                try{
                        Thread.sleep(100);
                } catch (Exception e) {}
        }

      return userid.getValue();
}
Uri
Thanks. It needs to be called more than once though... Which syncronization model do you mean, to read/write from this ValueBox object? It is going to be pretty complicated...
serg
The problem is that you could have multiple calls to getUserId before you ever get to process the userId (e.g., imagine you had 5 calls in the first 100ms). You would then have the risk of getting things overwritten, etc. What do you want to do in those situations?
Uri
Probably don't process further requests until current one is done.
serg
No synchronization is needed and this is thread-safe as written. Since the userid variable is a method local variable a new instance will be created for each call and nothing special is needed.
John Meagher
A: 

The simplest change is to use something like java.util.concurrent.SynchronousQueue. But possibly you want to provide an event driven interface yourself.

Tom Hawtin - tackline