How to make multiple AsyncCallback calls in a Loop in GWTP? - gwt

This question is very useful. There're some questions about calling multiple AsyncCallback but they didn't tell how to call them in a loop.
Here is my problem. I am doing a project using Gwt-platform. I got a presenter TestPresenter.java which has these codes:
#Inject
DispatchAsync dispatchAsync;
private AsyncCallback<GetDataResult> getDataCallback = new AsyncCallback<GetDataResult>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(GetDataResult result) {
// do Something o show the gui here
}
};
public void load_All_Gui_At_Once() {
for(int i=0; i<5; i++) {
GetData getDataAction=new GetData(i);
dispatchAsync.execute(getDataAction, getDataCallback);
}
}
The problem is that the program show the data but it showed in the wrong order. This is cos the next Async method started to run while the previous one has not finish yet.
Some suggested me to put the 2nd call inside onSuccess, but that is only for simple 2 sync calls. But in my case, I have to loop many unknown number of Async calls, then how can i do it?

This is a question similar to this one. All your calls are executed in the same instant, but the response time is unknown and it is not guaranteed the order. So the solution is almost the same, call the loop inside the callback. Your code should look like:
#Inject
DispatchAsync dispatchAsync;
private AsyncCallback<GetDataResult> getDataCallback = new AsyncCallback<GetDataResult>() {
int idx = 0;
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(GetDataResult result) {
if (result != null) {
// do Something or show the gui here
}
if (idx < 5) {
GetData getDataAction = new GetData(idx);
dispatchAsync.execute(getDataAction, getDataCallback);
}
idx ++;
}
};
public void load_All_Gui_At_Once(){
// Start the loop, calling onSuccess the first time
getDataCallback.onSuccess(null);
}

Related

Wrapping event listeners in Observables

I've seen a lot of examples of how to turn finite things like arrays or Iterables into Observables, but I'm not sure I understand how to make an Observable out of something live and effectively unbounded like an event receiver. I studied the RxJava2 docs and came up with this, using an Android LocationListener as an example.
Is there a simpler and/or more correct way to do this? I'm aware of the "RxBus" concept, but it seems like a way of clinging to the old event bus paradigm.
final Observable<Location> locationObservable = Observable.create(new ObservableOnSubscribe<Location>() {
final LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
#Override
public void subscribe(final ObservableEmitter<Location> emitter) throws Exception {
final LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(final Location location) {
emitter.onNext(location);
}
#Override
public void onStatusChanged(final String s, final int i, final Bundle bundle) {
// TODO ???
}
#Override
public void onProviderEnabled(final String s) {
// TODO ???
}
#Override
public void onProviderDisabled(final String s) {
// TODO ???
}
};
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
emitter.setCancellable(new Cancellable() {
#Override
public void cancel() throws Exception {
mLocationManager.removeUpdates(listener);
}
});
emitter.setDisposable(new Disposable() {
private AtomicBoolean mDisposed;
#Override
public void dispose() {
if(mDisposed.compareAndSet(false, true)) {
mLocationManager.removeUpdates(listener);
}
}
#Override
public boolean isDisposed() {
return mDisposed.get();
}
});
}
});
using Observable.create() is indeed a correct way.
However, with RxJava2 the default way is to extend an Observable, you can see this answer for greater details.
some comments though regarding your implementation:
- there is no point setting both Cancellable and Disposable, as the later one will cancel/dispose the first one, you can see the difference between them here.
- I think it's best practice, to register cancellable/disposable before you start listening to update, in order to prevent weird edge cases races.

execute asynccallback first

I have this code:
searchButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
statusLabel.setText("Searching...");
final String query = searchField.getText();
RootPanel.get("flickr").clear();
AsyncCallback<Flickr> ac=new AsyncCallback<Flickr>(){
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(Flickr result) {
for(Photo p:result.getPhotos().getPhoto())
{
flck.add(p);
}
statusLabel.setText("");
}
};
mashupService.getFlickrPhotos(query, ac);
if(!flck.isEmpty())
{
for(int i=0;i<flck.size();i++)
{
RootPanel.get("flickr").add(new HTML("<img src='http://farm"+flck.get(i).getFarm()+".staticflickr.com/"+flck.get(i).getServer()+"/"+flck.get(i).getId()+"_"+flck.get(i).getSecret()+".jpg'/><br/>"));
}
}
}
});
I want execute first onSuccess (have flick.add)... but it executes after of if(!flck.isEmpty)... and I need have flck with data but I can't...
When I press secont time the same button, flck have data of first onClick...
Thanks in advance
Move the code inside the onSuccess() method that is depended on the result of AsyncCallback.
It's clear from the name that AsyncCallback is just like a AJAX request that talks to server asynchronously means the execution of code is not sequential.
Just move if(!flck.isEmpty)... inside onSuccess() method.

Waiting until application return Sucess or Failure(AsyncCallBack)

Just for example, let's check the code below
private void loadUserFromServer() {
dispatchAsync.execute(new FindLoggedUserAction(),
new AsyncCallback<FindLoggerUserResult>() {
#Override
public void onFailure(Throwable caught) {
//do something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
//dosomething with user
result.getUser();
}
operationTwo();
}
My problem is, I have to execute operationTwo(); after some result of dipatcher(Success or failure).
This is just an example, let's assume I can't put operationTwo() inside the onSucess or onFailure()
My real PROBLEM
My GateKeeper of presenters that user must be login.
private UserDTO user;
#Override
public boolean canReveal() {
if(getUser() == null){
ShowMsgEvent.fire(eventBus,"Must Login first", AlertType.ERROR);
return false;
}
return true;
}
}
public UserDTO getUser()
{
if(user == null)
{
//call server
loadUserFromServer();
}
return user;
}
private void loadUsuarioFromServer() {
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
}
});
As you can see, when a Presenter with that Gatekeeper is called and user is null,
getUser() is called, but when dispatch executes, the method doesn't wait until the return of Sucess or Failure
Result: getUser() returns null.
After the sucessful result of dispatch, getUser() returns a DTO. But, as you can see canReveal() already returned false.
Do not think that GateKeeper is a good approach to handle security in your case. You will not be able to reach stable work. Problem that you will have:
You are not handling network connection lost. If you code is already cached but you need to reload User it will be a big problem with double checking.
Sync calls are always problematic, specially with bad network connection. You will have tons of not responding messages.
To handle presenter access it will be better to use revealInParent method. Most of your presenter already overrides it and it looks like:
#Override
protected void revealInParent() {
RevealContentEvent.fire(...);
}
So you can just not fire Reveal event before you actually download user data. In your case the code will looks like:
#Override
protected void revealInParent() {
if(getUser() == null){
RevealContentEvent.fire(...);
return;
}
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
RevealContentEvent.fire(...);
}
});
We have also encountered similar problems. Its better to use Async call chaining. Since you can't do that there are two options for your problem
Setup a timer which will check from time to time whether the user is null or not and return only after when user is populated.
Use JSNI (Native code) and make the synchronous call. But beware this is bad practice
Yes, as Abhijith mentioned in previous answer there are 2 options -
1) Synchronous calls - which GWT doesn't support. So it is ruled out.
2) Setting timer - unless user logs in control will not come out of the timer loop. So failed status will never return from the timer. This approach serves only half of your requierment(serving only success state).
To solve your problem you try the following code snippet -
private UserDTO user;
private CanRevealCallBack revealCallBack;
public interface CanRevealCallBack {
returnStatus(boolean status);
}
#Override
public void canReveal(CanRevealCallBack callBack) {
revealCallBack = callBack;
if(user == null){
loadUserFromServer();
}
else{
revealCallBack.returnStatus( true );
}
}
private void loadUsuarioFromServer() {
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
,new AsyncCallback<BuscarUsuarioLogadoResult>() {
#Override
public void onFailure(Throwable caught) {
//something
}
#Override
public void onSuccess(BuscarUsuarioLogadoResult result) {
if(!(result.getDto().equals(user)))
{
setUsuario(result.getDto(), false); //Set user UserDTO user
//event for update Presenter Login/Logout
// and Label with username
fireUserUpdateEvents();
}
else
{
setUsuario(result.getDto(), false);
}
if(result.getDto() == null){
revealCallBack.returnStatus( true );
}
else{
revealCallBack.returnStatus( false );
}
}
});
So, you have to pass a revealCallback to the canReveal method. CallBack gets executed and returns u the status on success of the async call. In returnStatus method of the callback you can program the logic with the correct user log-in status.

Decouple GWT Asynchronous callbacks

I have the following problem:
I am trying to model a process using GWT, where i have a couple of views with a couple of submit buttons. And pressing button1 will create a server interaction and if everything was ok, the next view will be loaded. My problem is now that I get really nasty spaghetti code (just very highlevel to show you what i mean):
onClick {
AsyncCallback {
onSuccess {
load new view with another clickhandler and an asynccallback
}
}
}
Is there some way to create some kind of abstraction or something? Maybe a state pattern? How? Thanks a lot!
This is actually a very good question - and probably one without a definitive answer. It's a problem that applies to many frameworks, not just GWT, so I like your idea to look at this with some simplified code. I'll make this a little bit longer, to show what even just 4 very simple callbacks look like:
Nested callbacks
alice.call("a", new Callback() {
#Override
public void onSuccess() {
bob.call("b", new Callback() {
#Override
public void onSuccess() {
charlie.call("c", new Callback() {
#Override
public void onSuccess() {
daisy.call("d", new Callback() {
#Override
public void onSuccess() {
// finished
}
});
}
});
}
});
}
});
Named callbacks
You can use your IDE to refactor this easily into named callbacks (hint: Please read the callbacks from bottom to top!):
final Callback daisyCallback = new Callback() {
#Override
public void onSuccess() {
// finished
}
};
final Callback charlieCallback = new Callback() {
#Override
public void onSuccess() {
daisy.call("d", daisyCallback);
}
};
final Callback bobCallback = new Callback() {
#Override
public void onSuccess() {
charlie.call("c", charlieCallback);
}
};
final Callback aliceCallback = new Callback() {
#Override
public void onSuccess() {
bob.call("b", bobCallback);
}
};
alice.call("a", aliceCallback);
Problem: The control flow is not so immediately obvious anymore.
Still, an IDE can help by using "Search References" (Ctrl-G in Eclipse) or something similar.
Event Bus (or Observer/Publish-Subscribe pattern)
This is how the same calls look like with an event bus:
alice.call("a", new Callback() {
#Override
public void onSuccess() {
bus.fireEvent(BusEvent.ALICE_SUCCESSFUL_EVENT);
}
});
bus.addEventListener(BusEvent.ALICE_SUCCESSFUL_EVENT, new BusEventListener() {
#Override
public void onEvent(final BusEvent busEvent) {
bob.call("b", new Callback() {
#Override
public void onSuccess() {
bus.fireEvent(BusEvent.BOB_SUCCESSFUL_EVENT);
}
});
}
});
bus.addEventListener(BusEvent.BOB_SUCCESSFUL_EVENT, new BusEventListener() {
#Override
public void onEvent(final BusEvent busEvent) {
charlie.call("c", new Callback() {
#Override
public void onSuccess() {
bus.fireEvent(BusEvent.CHARLIE_SUCCESSFUL_EVENT);
}
});
}
});
bus.addEventListener(BusEvent.CHARLIE_SUCCESSFUL_EVENT, new BusEventListener() {
#Override
public void onEvent(final BusEvent busEvent) {
daisy.call("d", new Callback() {
#Override
public void onSuccess() {
bus.fireEvent(BusEvent.DAISY_SUCCESSFUL_EVENT);
}
});
}
});
bus.addEventListener(BusEvent.DAISY_SUCCESSFUL_EVENT, new BusEventListener() {
#Override
public void onEvent(final BusEvent busEvent) {
// finished
}
});
Under the right circumstances (when it's very clear what each event means, and
if you don't have too many), this pattern can make things very nice and clear.
But in other cases, it can make the control flow more confusing (and you easily get twice the lines of code).
It's harder to use your IDE to find out about the control flow.
The GWT History mechanism is a very positive example for where to use this technique reasonably.
Divide and Conquer
In my experience, it's often a good idea to "divide and conquer" by mixing nesting and named callbacks:
final Callback charlieCallback = new Callback() {
#Override
public void onSuccess() {
daisy.call("d", new Callback() {
#Override
public void onSuccess() {
// finished
}
});
}
};
alice.call("a", new Callback() {
#Override
public void onSuccess() {
bob.call("b", new Callback() {
#Override
public void onSuccess() {
charlie.call("c", charlieCallback);
}
});
}
});
Depending on the situation, two nested callbacks are often still readable, and they reduce jumping around between methods when reading the code by 50%.
(I created a pastebin of my examples here, if you like to play around with them: http://pastebin.com/yNc9Cqtb)
Spaghetti code is a tricky problem in GWT as it is in Javascript, where much of your code is structured around asynchronous callbacks.
Some of the techniques to deal with it that are described in the answers to this question could apply.
The suggested approach to avoid coupling between widgets is to use EventBus. Read more details here https://developers.google.com/web-toolkit/articles/mvp-architecture#events
Hope it helps.
changeview(boolean first){
if(first)
{
firstView.setVisible(true);
secondView.setVisible(false);
}else{
firstView.setVisible(false);
secondView.setVisible(true);
}
}
onClick {
AsyncCallback {
onSuccess {
changeView(false);
}
}
}
Switch between views by above.
Use MVP from very beginning. Use Activities and Places. Your code will be clean.

GWT RunAsync - Strange behavior in release mode

As suggested in this question GWT - Where should i use code splitting while using places/activities/mappers?, I created an ActivityProxy to nest my activities.
I based my implementation on this http://code.google.com/p/google-web-toolkit/issues/detail?id=5129 (6th comment), with one modification: I added a check on the provider before calling GWT.RunAsync:
if (provider != null)
{
GWT.runAsync(new RunAsyncCallback()
{
#Override
public void onFailure(Throwable reason)
{
// ...
}
#Override
public void onSuccess()
{
ActivityProxy.this.nestedActivity = provider.create();
//...
}
});
}
But for some reason, this doesn't work in release mode: the onFailure methode is never called but my activity is never displayed the first time I use it. If I reload the place, everything display just fine.
Then I realised that doing the following solves the problem:
GWT.runAsync(new RunAsyncCallback()
{
#Override
public void onFailure(Throwable reason)
{
// ...
}
#Override
public void onSuccess()
{
if (provider != null)
{
ActivityProxy.this.nestedActivity = provider.create();
//...
}
}
});
So even if I don't understand why it works, I started using it for all my activities.
I ran into the problem again when I decided to use a generator for my ActivityProxy (to avoid writing a provider for each Activity). The synthax becomes GWT.create(ActivityProxy).wrap(MyActivity.class);
Basically, the generated code looks like this:
if (clazz.getName() == "FooClass")
{
nestedActivity = new FooClass(); //inside a RunAsync
}
if (clazz.getName() == "BarClass")
{
nestedActivity = new BarClass(); //inside a RunAsync
}
And the same problem occurs: my app fails to display my activities the first time they are used.
So simple question : "Why?"