Issue
I am writing a class in java which is going to fetch results from a MongoDB database and then return the results back to the main program. My code is as follows:
public Document[] search(Document query, String databaseName, String collectionName) {
Log.i(TAG, "Search query: " + query);
_mongoClient.getDatabase(databaseName).getCollection(collectionName).find(query).continueWith(
new Continuation<List<Document>, Object>() {
@Override
public Object then(@NonNull final Task<List<Document>> task) throws Exception {
if (!task.isSuccessful()) {
Log.e(TAG, "Failed to execute query");
} else {
if (task.getResult().size() == 0) {
Log.i(TAG, "Query failed to return any results");
return null;
}
results = new Document[task.getResult().size()];
for (Integer i = 0; i < task.getResult().size(); i++) {
results[i] = task.getResult().get(i);
Log.i("test", results[i].getString("username").toString());
}
}
return null;
}
});
return results;
}
The issue with my code is that it doesn't wait for the code inside the method for retrieving the database to run. Instead it jumps straight to the return statement. I have tried using AsyncTask like this:
private class WaitForDB extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(context);
pd.setMessage("Please wait");
pd.setCancelable(false);
pd.show();
}
protected Void doInBackground(Void... params) {
Document query = new Document("username", "a");
_mongoClient.getDatabase("gapp").getCollection("parent").find(query).continueWith(
new Continuation<List<Document>, Object>() {
@Override
public Object then(@NonNull final Task<List<Document>> task) throws Exception {
if (!task.isSuccessful()) {
Log.e(TAG, "Failed to execute query");
} else {
if (task.getResult().size() == 0) {
Log.i(TAG, "Query failed to return any results");
return null;
}
results = new Document[task.getResult().size()];
for (Integer i = 0; i < task.getResult().size(); i++) {
results[i] = task.getResult().get(i);
Log.i("test", results[i].getString("username").toString());
}
}
return null;
}
});
return null;
}
@Override
protected void onPostExecute(Void result) {
if (pd.isShowing()) {
pd.dismiss();
}
}
}
However, this does not work either. So, I would like to know, is there a way for the program to wait until the data is retrieved from the database? And if yes, how?
I will appreciate any kind of help. Thanks in advance.
Solution
The first code doesn't wait only because you wrote it that way. If you want to observe that, put more log statements outside of error conditions or where you are building the result list, as well as before the return statements. The result list will be built after the return results
.
What you can do is pass the "continuation" through to the method as a parameter
public void search(Document query, String databaseName, String collectionName, Continuation<List<Document>, Object> continuation) {
Log.i(TAG, "Search query: " + query);
_mongoClient.getDatabase(databaseName)
.getCollection(collectionName)
.find(query)
.continueWith(continuation);
} //end method
And that's it for that method. Do your processing elsewhere where you need the documents
For example, rather than trying to make this a blocking call for results
Document[] documents = search(...);
// process documents
You need to invoke the function, which waits for results to be received, then executes the inner callback function
// Do not define documents here
search(query, database, collection,
new Continuation<List<Document>, Object>() {
@Override
public Object then(@NonNull final Task<List<Document>> task) throws Exception {
if (!task.isSuccessful()) {
Log.e(TAG, "Failed to execute query");
} else {
List<Document> documents = task.getResults();
// process documents
}
});
// if you did define documents outside this, it'll still be empty
If you want to reduce all this code just to get an actual Document array, you need to define your own interface, but this is the most flexible working solution without extra classes
Answered By - OneCricketeer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.