Search code examples
gwtasynchronousgwtp

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.


Solution

  • 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:

    1. 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.
    2. 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(...);
          }
       });