I have the following code snippet:
private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>();
public void fetchAsync(final String attrName) {
QueryAsyncCallback asyncCallback = new QueryAsyncCallback() {
@Override
public void onSuccess(Message response) {
final Data value = response.results().get("value");
String text = value.toString();
CompletableFuture<String> result = CompletableFuture.completedFuture(text);
valContainer.setVal(result);
}
@Override
public void onError(CallbackError error) {
LOG.info("Error occurred");
}
@Override
public void onTimeout() {
LOG.info("Timeout occurred");
}
};
Message request = new Messsage("com.example.val", "local", 0, "fetch");
request.parameters().put("name", attrName);
MsgOptions options = new MsgOptions(5000);
try {
queue.query(request, options, asyncCallback);
} catch (QueueAccessException e) {
e.printStackTrace();
}
}
Right now, I can easily get the values I made a query for in onSuccess()
callback. ValContainer
is just a generic container so that I can save the values inside anonymous class. Unfortunately, in Main function I am trying to access this valContainer
but sadly as this is asynchronous query I am getting NullPointerException.
...
((JavaServiceImpl) javaService).fetchAsync("test");
System.out.println("inMain value: " + ((JavaServiceImpl) javaService).getValContainer().getVal().get()); <-- this is going to be NullPointerException
...
Then after 100ms I am getting the value in onSuccess()
method. Here basically doing Thread.sleep(100)
would be sufficient to acquire the value I am hoping to get but I really do not want to block the thread. Is there a way to do it in a neat way?
Don't leave the val
un-initialized in ValContainer
. Initialize it as new CompletableFuture<>()
.
private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>(new CompletableFuture<>());
public class ValContainer<T> {
T val;
public ValContainer(T val) {
this.val = val;
}
}
Then change your onSuccess
method as
String text = value.toString();
valContainer.getVal().complete(text);
You don't need to create a CompletableFuture
in onSuccess
method.
With this, [..]getValContainer().getVal().get()
blocks till the future is complete.