0

As Firebase SDK create a demon thread in background to synchronize data. I use the solution suggested as the link to create an AtomicBoolean to wait until the task completed.

java Firebase: delay exit until writes finish

I tried to remove the key in the web admin console. The task become never completed without any timeout exception.

public static void main(String[] args) throws IOException {
    InputStream serviceAccount = Appl.class.getClassLoader().getResourceAsStream("testing-fcf995d2ab6f.json");

    FirebaseOptions.Builder builder = new FirebaseOptions.Builder();
    builder.setCredentials(GoogleCredentials.fromStream(serviceAccount));
    builder.setDatabaseUrl("https://golden-attic-93815.firebaseio.com/");
    FirebaseOptions firebaseOptions = builder.build();

    FirebaseApp.initializeApp(firebaseOptions);

    FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();

    DatabaseReference ref = firebaseDatabase.getReference("techoffice/database/example");

    DatabaseReference usersRef = ref.child("users");

    final AtomicBoolean done = new AtomicBoolean(false);
    Map<String, User> users = new HashMap<String, User>();
    users.put("testerA", new User("Tester A"));
    users.put("testerB", new User("Tester B"));
    usersRef.setValue(users, new DatabaseReference.CompletionListener(){
        public void onComplete(DatabaseError error, DatabaseReference ref) {
            if (error != null){
                System.err.println("Error " + error.getMessage());
            }else {
                System.out.println("Completed");
            }
            done.set(true);
        }
    });
    while(!done.get());
}

I get the same result if I change to setValueAsync.

ApiFuture<Void> apiFuture = usersRef.setValueAsync(users);
apiFuture.get();
Ben Cheng
  • 769
  • 10
  • 25
  • how you can tell the **"The task become never completed"** , add this line at end of your main function `System.out.println("Task Completed");` , what do you get now – Ali Faris Jan 28 '18 at 10:34
  • 1
    If I add "System.out.println("Task Completed");", The Task is also not stopped. Because "while(!done.get());" always return false. – Ben Cheng Jan 28 '18 at 10:38
  • i think you can use `usersRef.setValueAsync(users)` method which returns ApiFuture and if you want to wait write operation you may check `ApiFuture.isDone()`. – forsaken Jan 28 '18 at 11:09
  • I get same result. For ApiFuture apiFuture = usersRef.setValueAsync(users); apiFuture.get(); – Ben Cheng Jan 28 '18 at 11:37

1 Answers1

0

This is not how you can change the value of your done AtomicBoolean variable. Using your code it will always be false because onComplete() method is called asynchronous, which means that by the time you are using this line of code:

while(!done.get());

You haven't get the data yet from your database. So to solve this, you need to change the logic of your code and use a callback. This means that you need to wait for the data and after that to be able to use that statement. This is a classic issue with asynchronous APIs and for that I recomand you read my answer from this post. The onDataChange() method is called in the same way. Please see also the last part of my answer in which I have exaplained how to get the data outside.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193