Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return String from a callback - Java

does anyone know how I can solve the following problem. I want to return a String from a callback, but I get only "The final local variable s cannot be assigned, since it is defined in an enclosing type", because of final.

 public String getConstraint(int indexFdg) {
    final String s;
    AsyncCallback<String> callback = new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {
            caught.printStackTrace();
        }

        public void onSuccess(String result) {
            s = result;
        }
    };
    SpeicherService.Util.getInstance().getConstraint(indexFdg, callback);
    return s;
    }
like image 719
ph09 Avatar asked Jul 27 '11 16:07

ph09


People also ask

Can a callback return a value?

A callback function can return a value, in other words, but the code that calls the function won't pay attention to the return value. Yes, it makes fun sense to try and return a value from a promise callback.

How do you return a callback in JavaScript?

We create a new promise, an object that will be returned from our callback using the new Promise() function. We invoke a . then() function on our promise object which is an asynchronous function and passes our callback to that function. That callback function takes in two parameters, a resolve, and a reject.

Is callback same as return?

Return statements are used to indicates the end of a given function's execution whereas callbacks are used to indicate the desired end of a given function's execution.


2 Answers

The whole point of an asynchronous callback is to notify you of something that happens asynchronously, at some time in the future. You can't return s from getConstraint if it's going to be set after the method has finished running.

When dealing with asynchronous callbacks you have to rethink the flow of your program. Instead of getConstraint returning a value, the code that would go on to use that value should be called as a result of the callback.

As a simple (incomplete) example, you would need to change this:

 String s = getConstraint();
 someGuiLabel.setText(s);

Into something like this:

 myCallback = new AsyncCallback<String>() {
     public void onSuccess(String result) {
         someGuiLabel.setText(result);
     }
 }
 fetchConstraintAsynchronously(myCallback);

Edit

A popular alternative is the concept of a future. A future is an object that you can return immediately but which will only have a value at some point in the future. It's a container where you only need to wait for the value at the point of asking for it.

You can think of holding a future as holding a ticket for your suit that is at the dry cleaning. You get the ticket immediately, can keep it in your wallet, give it to a friend... but as soon as you need to exchange it for the actual suit you need to wait until the suit is ready.

Java has such a class (Future<V>) that is used widely by the ExecutorService API.

like image 51
Mark Peters Avatar answered Oct 23 '22 12:10

Mark Peters


An alternative workaround is to define a new class, called SyncResult

public class SyncResult {
    private static final long TIMEOUT = 20000L;
    private String result;

    public String getResult() {
        long startTimeMillis = System.currentTimeMillis();
        while (result == null && System.currentTimeMillis() - startTimeMillis < TIMEOUT) {
            synchronized (this) {
                try {
                    wait(TIMEOUT);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        synchronized (this) {
            notify();
        }
    }
}

Then change your code to this

public String getConstraint(int indexFdg) {
    final SyncResult syncResult = new SyncResult();
    AsyncCallback<String> callback = new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {
            caught.printStackTrace();
        }

        public void onSuccess(String result) {
            syncResult.setResult(result);
        }
    };
    SpeicherService.Util.getInstance().getConstraint(indexFdg, callback);
    return syncResult.getResult();
}

The getResult() method will be blocked until setResult(String) method been called or the TIMEOUT reached.

like image 37
songlebao Avatar answered Oct 23 '22 11:10

songlebao