Am I throwing correctly?

Asked

Viewed 145 times

1

I’m doing like a Firebase DAO that performs and handles Auth, Database and Storage. But Firebase emits some exceptions depending on the scenario, password with less than 6 digits, email already registered, etc.

I’m trying to throw these exceptions forward using the throw but he asks me to make a Ry, I do not understand why if I am passing the error to be treated further forward because it forces me to treat the error.

//-------------------- FirebaseAuth ------------------------------
    public void createAuth(User user) {       

       mFirebaseAuth = ConfigurationFirebase.getFirebaseAuth();
       mFirebaseAuth.createUserWithEmailAndPassword(user.getEmail(), user.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
           @Override
           public void onComplete(@NonNull Task<AuthResult> task) {
                //Fazer algo caso a criação do usuário tenha ocorrido com sucesso.
           }
       }).addOnFailureListener(new OnFailureListener() {
           @Override
           public void onFailure(@NonNull Exception e) {
                  if (e.getClass().equals(FirebaseAuthWeakPasswordException.class)) {

                      try {
                          throw new FirebaseAuthWeakPasswordException(e.getCause().toString(), e.getLocalizedMessage().toString(), e.getMessage().toString());
                      } catch (FirebaseAuthWeakPasswordException e1) {
                          e1.printStackTrace();
                      }

                  } else if (e.getClass().equals(FirebaseAuthUserCollisionException.class)) {

                      try {
                          throw new FirebaseAuthUserCollisionException(e.getCause().toString(), e.getLocalizedMessage().toString());
                      } catch (FirebaseAuthUserCollisionException e1) {
                          e1.printStackTrace();
                      }

                  }
           }
       });

    }
  • Enter the code that is causing the problem, the error message, and use the tags to indicate which programming language/platform you are using.

1 answer

1


This will not work because the method you are calling is asynchronous. This exception would be thrown to another thread, where the network call is taking place, and it wouldn’t work anyway. This DAO pattern you’re trying to do simply doesn’t work in asynchronous paradigms without changes.

You have not specified the programming language or execution environment, but if it is an environment in which there is no problem in locking the thread current while waiting for the result, you can use Tasks.await to make your code wait until the completion of the Task resulting from createUserWithEmailAndPassword. Example:

public void createAuth(User user) throws FirebaseAuthWeakPasswordException {

    Task<AuthResult> createUserAccountTask = mFirebaseAuth.createUserWithEmailAndPassword(user.getEmail(), user.getPassword());
    try {
        // Nessa linha, a execução da thread atual vai congelar até a tarefa concluir (com sucesso ou erro)
        Tasks.await(createUserAccountTask);

        if (createUserAccountTask.isSuccessful()) {
            //Fazer algo caso a criação do usuário tenha ocorrido com sucesso.
        } else {
            Exception e = createUserAccountTask.getException();
            if (e.getClass().equals(FirebaseAuthWeakPasswordException.class)) {
                throw new FirebaseAuthWeakPasswordException(e.getCause().toString(), e.getLocalizedMessage().toString(), e.getMessage().toString());
            } else if (e.getClass().equals(FirebaseAuthUserCollisionException.class)) {
                throw new FirebaseAuthUserCollisionException(this.e.getCause().toString(), this.e.getLocalizedMessage().toString());
            }
        }

    } catch (ExecutionException e) {
        // faça alguma coisa aqui em caso de ExecutionException
    } catch (InterruptedException e) {
        // faça alguma coisa aqui caso a tarefa seja interrompida no meio
    }

}

However, be aware that this can freeze the user screen if you run on thread leading.

A common and simple approach to implement when it is not possible to block the current thread execution is to use so-called callbacks or listeners. You must require that those who call your function pass to it, in addition to the user and password, objects that explain what to do when the task is completed. For example, you can define these interfaces:

@FunctionalInterface
interface UserCreationSuccessfulListener {
    void onUserCreated();
}

@FunctionalInterface
interface UserCreationFailedListener {
    void onFailedToCreateUser(Exception e);
}

And then you can change your function to be like this:

public void createAuth(User user, final UserCreationSuccessfulListener successListener, final UserCreationFailedListener failureListener) throws FirebaseAuthWeakPasswordException {

    mFirebaseAuth.createUserWithEmailAndPassword(user.getEmail(), user.getPassword())
            .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                @Override
                public void onSuccess(AuthResult authResult) {
                    successListener.onUserCreated();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {

                    if (e.getClass().equals(FirebaseAuthWeakPasswordException.class)) {
                        failureListener.onFailedToCreateUser(
                                new FirebaseAuthWeakPasswordException(e.getCause().toString(), e.getLocalizedMessage(), e.getMessage())
                        );
                    } else if (e.getClass().equals(FirebaseAuthUserCollisionException.class)) {
                        failureListener.onFailedToCreateUser(new FirebaseAuthUserCollisionException(e.getCause().toString(), e.getLocalizedMessage()));
                    } else {
                        failureListener.onFailedToCreateUser(e);
                    }

                }
            }
            );

}

And use it like this:

createAuth(user, new UserCreationSuccessfulListener() {
    @Override
    public void onUserCreated() {
        // fazer algo aqui em caso de sucesso
    }
}, new UserCreationFailedListener() {
    @Override
    public void onFailedToCreateUser(Exception e) {
        // fazer algo aqui em caso de erro
    }
});

Or better yet:

createAuth(user, () -> {
    // fazer algo aqui em caso de sucesso
}, (error) -> {
    // fazer algo aqui em caso de erro
});

There are other options. You can, for example, return the Task that the createUserWithEmailAndPassword and let the client code of your function turn with the result. One problem is that it creates a client code dependency with the Google Play Services API.

  • Vlw Pablo, to solve the problem I could run the methods in Threads, an asynctask or even use an Rxandroid?

  • or the firebase jobdispatcher?

  • If you’re talking about the solution 1 that I gave you, if you’re going to use threads or asynctasks to make it work, you’re just passing the complexity from one point to another. And the worst: you may end up having to replicate thread-handling logic and asynctasks in multiple places if the method is called multiple times. It’s not interesting. It’s best to accept the asynchronous nature of the function and create even asynchronous Apis. Rxandroid is an option, yes, but I personally find it more suitable for more complex situations, such as a callback that is called several times, for example.

  • The API itself Tasks Google Play Services is really cool, and Firebase already uses it natively, so you won’t have to keep making conversions. If you don’t have trouble learning how to use it, it’s a good one.

  • I understood the reason of using an RX or an Asynctask, the concern would be to remove the processing from Activity because it violates the rule of not doing heavy parallel processing on Uithread, having to update some view that can only be done by Uithread. But in my case I just want to perform the task of saving data in firebase, fetching data in firebase etc. This DAO will return Exceptions, booleans etc and in Activity I will turn to use an Handler.post or something like that. ????

  • Pablo, to solve the problem of Android asynchronous communication, do you think it’s better: Rxandroid, Google Tasks, Firebase Jobdispatcher or deal with Interfaces? Dealing with interfaces is very confusing, I’m trying but do not leave the place!!!

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.