3

I'm using Firebase JAVA sdk in my Spring Boot application.

Trying to verify a firebase token:

Map resp = new HashMap();

Task<FirebaseToken> task = FirebaseAuth.getInstance().verifyIdToken(info.getToken())
        .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
            @Override
            public void onSuccess(FirebaseToken decodedToken) {
                logger.info(decodedToken.getClaims());

                String uid = decodedToken.getUid();
                User user = userDao.loadUserByUID(uid);

                if (user == null) {
                     ...........
                }
                SimpleSignInAdapter.signin(user.getUsername());

                resp.put("status", "success");
                resp.put("token", jwtTokenProvider.createToken(SecurityContextHolder.getContext().getAuthentication()));
                logger.info(resp);
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                resp.put("status", "fail");
                resp.put("message", e.getMessage());
            }
        });
try {
    Tasks.await(task);
    logger.info(resp);
    return resp;
} catch (ExecutionException | InterruptedException e) {
    resp.put("status", "fail");
    resp.put("message", e.getMessage());
    return resp;
}

Tasks.await(task) suppose to block a code execution until task is finished. However it doesn't block the code and logger.info(resp); return resp; getting executed before it's finished:

2017-09-20 16:10:30,613 INFO  [http-nio-8080-exec-1] impl.FirebaseServiceImpl (FirebaseServiceImpl.java:98) - {}
2017-09-20 16:10:30,613 INFO  [pool-2-thread-2] impl.FirebaseServiceImpl$2 (FirebaseServiceImpl.java:56) - {"aud":******" ******}}
2017-09-20 16:10:43,966 INFO  [pool-2-thread-2] impl.FirebaseServiceImpl$2 (FirebaseServiceImpl.java:84) -{status=success, token=......}

What can be a possible reason ?

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
user1935987
  • 3,136
  • 9
  • 56
  • 108
  • 1
    @DougStevenson is correct. I think you can simplify the code and the semantics by using the return value of `Tasks.await()` and getting rid of the async callbacks altogether. Since you're waiting on the task to finish, the callbacks don't really contribute anything meaningful in this case. – Hiranya Jayathilaka Sep 20 '17 at 20:30

1 Answers1

4

I think you're misinterpreting the logs. Tasks.await() is doing its job. Bear in mind that the success listener is not obligated to execute precisely before or after Tasks.await(). It will execute some time after the task is complete, just like Tasks.await() returns some time after the task is complete. Also note that the log lines are coming from two different threads: http-nio-8080-exec-1 and pool-2-thread-2, and there's no guarantee about the order in which those two threads will continue when the task is complete.

Now, if you want to ensure that the thread running Tasks.await() executes only after the success listener, you'll have to use something like a CountDownLatch to block the first thread until the work in the success listener is complete.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • I understand that the success listener is not obligated to execute precisely. However, as i understand `Tasks.await(task)` suppouse to block the main thread until `Task task` is finshed, including it's listeners. it is also shown this way in multiple tutorials, so i suppose that is the expected behavior. – user1935987 Sep 25 '17 at 07:51
  • Can you show where exactly in the documentation are you reading that the listeners *must* be fully complete before the task itself is complete? – Doug Stevenson Sep 25 '17 at 16:50
  • Had my head scratching for a few minutes with the same problem - as soon as I started reading your answer it made total sense, thanks! – Mark Sep 23 '18 at 13:53