I tried to find an answer online for it, but I couldn't find one which is specific for Firebase implementations.
I can choose between OnCompleteListener and OnSuccessListener for a lot of operations in Firebase, and I'd like to know how can I choose between them?.
I have read the documentation for OnComplete and OnSuccess, but as I can see from Firebase documentations, this one for example, for one specific operation (like get operation in the example), they sometimes use OnSuccessListener and sometimes they use OnCompleteListener.
How can I know which one is better in every situation?
Does it matter? Considering that I'd like to know for every operation if it was succussful or not.
As the name suggests, onSuccess() will fire when a task is completed successfully.
onComplete() will fire when the task is completed, even if it failed.
In the method, you can call Task.isSuccessful() and Task.getException().
In onSuccess() you can be certain that isSuccessful() will return true, and getException() will return null (so there's not much point calling them).
In onComplete() isSuccessful() may be false, and you have the opportunity to deal with the failure, perhaps using getException() to obtain more detail.
If you need to handle failed tasks (and you should!), you have two choices:
Use and OnCompleteListener, and if(task.isSuccessful()) { ... } else {...} -- this puts the success and failure code close together, and may be useful if those routines share state.
Use separate OnSuccessListener and OnFailureListener -- this allows you to write listeners with a bit more cohesion, in that each handler specialises in one thing. Of course, one class may implement both interfaces, giving you another way to have both see the same state.
To add to what slim answered above in my use of Firebase.
I find out that this two listeners (OnCompleteListener and OnSuccessListener)
Have different callback times in writing data to their servers.
The general rule of thumb
If you're relying on a systematic(sequential) way of writing to the servers in order to
perform some logic then use OnCompleteListener
If you're not dependent on a systematic(non-sequential i.e async tasks) way of writing to the servers in order to
perform some logic then use OnSuccessListener
Sometimes you may find that you need to use value of the result say for example getting device token.. only the onSuccess will give InstanceIdResult and not onComplete... so therefore you must use onSuccess...
// Get The Device Token And Put It Into Firebase Instance
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String DeviceToken = instanceIdResult.getToken();
}
});
Related
I have a service method where I request an entity by ID from the database. If the entity has the attribute paid == false, I set it to true and do something. If paid==true it just returns.
#Override
#Transactional(rollbackFor={ServiceException.class})
public void handleIntentSucceeded(PaymentIntent intent) throws ServiceException {
LOGGER.trace("handleIntentSucceeded({})", intent);
CreditCharge charge = transactionRepository.findByPaymentIntentId(intent.getId());
if(charge.getPaid()) {
return;
// do some stuff
charge.setPaid(true);
transactionRepository.save(charge);
}
Now if there are multiple requests with the same intent at the same time, this method would no longer be consistent because, for example, the first request receives the charge with paid==false, so it does "some things" and if the second request comes to this method before the first request has saved the charge with paid==true, it would also do "some things" even if the first request already does so. Is this a correct conclusion?
To be sure that only one request can process this method at a time, to avoid "some things" being done multiple times, I could set the Transactional to #Transactional(isolation = Isolation.SERIALIZABLE). This way any request can process this method/transaction only if the request has committed the Transactional before.
Is this the best approach or is there a better way?
One solution, as already mentioned above is to use OptimisticLocking. However, an OptimisticLockingException will lead to a failed http request. If this is a problem, you can handle the exception.
But in case you are sure, that you will not run multiple instances of the application and there are not big requirements for perfomance, or you simply want to deal with the problem later and until that use a "workaround", you can make the method synchronized (https://www.baeldung.com/java-synchronized). That way, the Java runtime will ensure, that the method cannot be run in parallel.
I would probably look for a way of optimisically locking the record (e.g. using some kind of update counter), so that only the first concurrent transaction changing the paid property would complete successfully.
Any subsequent transaction which was trying to modify the same entity in the meantime would then fail, and their actions done during do some stuff would rollback.
Optimistic vs. Pessimistic locking
edit: REPEATABLE_READ isolation level (as suggested by one of the comments) might also behave similarly to optimistic locking; though this might depend on the implementation
I wanted to set up this variable called userName, which should get a new value inside the ValueEventListener. However, when setting the new value inside the function, it doesn't change. The output is still ""
private fun getName(){
var userName = ""
val user = fbAuth.currentUser
var uid = user!!.uid
mDatabase = FirebaseDatabase.getInstance().getReference("users")
mDatabase.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented")
}
override fun onDataChange(snapshot: DataSnapshot) {
userName = snapshot.child(uid).child("name").getValue().toString()
}
})
println(userName)
}
Expected output: John (value of name child),
current output: ""
The listener is asynchronous, if you put the println statement below the username = line, then it will print.
In fact, go ahead and do that; observe the timestamps; which one prints first? The empty one or the one inside the callback?
the var is being modified by the callback, but the println executes first, long before (in computer times, that is) Firebase emits its value.
Additionally, I would invert the order of the mDatabase lines.
You are essentially requesting a value and then listening for results; the result may have already been emitted. You should add the listener first, then request the data.
Update: what if I need the value for another callback?
Welcome to the world of asynchronous programming :-)
What you describe is a set of independent asynchronous operations. You need value A, and value B, but you can't obtain value B, until you have value A. Both are asynchronous and take time, but you don't have time on the main thread, or rather, you have ~16ms to compute, measure, and draw your screen so the OS can keep up with 60 frames per second. That's not a lot of time and part of the reason why asynchronous programming exists!
This other answer already provides a working sample of what you need. This other external link has a more concrete example of the Observer Listener pattern.
In short, what you want is an instance of an object which can be invoked once the an operation completes.
In a regular synchronous function, each statement is executed after the other and no statement will be executed until the previous one is not finished; all statements are therefore, blocking statements.
For example:
var times = 2
var message = "Hello"
var world = "World"
println("The message is $message $times")
println(world)
Will print:
The message is Hello 2
World
This is because the execution point will go from one line to the other, waiting for the previous one to execute. If one operation takes time, the thread will be blocked (from performing anything else) until that operation completes and the execution point can move to the next instruction.
As you can imagine, the Main Thread in iOS and Android (and well, Windows, macOS, Linux, etc) cannot be blocked, or the OS wouldn't be able to respond to your touches and other things happening (for e.g., on a mobile phone, an incoming phone call wouldn't be able to be processed if the UI is not responsive and you cannot tap "answer").
This is why we use other "threads" to off-load things that are not super fast. This comes with a mindset change, as well as correct planning, for things are now more complicated.
Let's see a simple example (some pseudo code, so bear any obvious glaring mistakes, this is just to illustrate the point, not to write a solution).
fun main() {
var hello = "Hello"
var message = thisTakesTime()
println("The message is $hello $message")
println(hello)
}
fun thisTakesTime(): String {
// do something that takes 1 second (1000 ms)
Thread.sleep(1000)
return "World"
}
This will print
The message is Hello World
Hello
As you can see, nothing changed, except that for one entire second, the main thread was unresponsive. If you were to run this on Android, for example, it will work, but your app will not respond for a second, during the Thread.sleep. One second is fast, try 10 seconds; this exceeds the Android Operating System limit of 5 seconds for the main thread to be unresponsive, before deciding the ANR (application not responding) dialog is needed; this is the infamous "It looks like XXX application is not responding, wait or close".
What can you do?
Initially, if you have too many callbacks (where callback A cannot execute until callback B finished, and callback B cannot execute until callback C finished), and you start nesting them like that, you end up in the infamous Callback-Hell (in Javascript, but valid for any language/platform).
Basically tracking all these asynchronous callbacks and ensuring that by the time the response comes, your next callback is ready, and so forth is a pain, and it introduces exponential complexity if, for example, callback C fails in the middle, now you have to let callback B know that C failed and therefore it will have to fail too, which -in turn- has to let callback A (the original!) know that B failed, and therefore A has to do something about it, does A need to know that B failed because of C? or does A only cares for B and B alone and the reasons behind B's failure are irrelevant?
Well, as you can see, even talking about this gets complicated and messy and I didn't even cover other possible scenarios, equally as complex.
What I'm trying to say here is not that you shouldn't use callbacks; it's that you have to carefully plan where, and when to use them.
Kotlin has alternatives to reduce/remove the callback hell by using Coroutines but these are a moderately advanced topic and it also requires a fundamental change in how you design your components and pieces.
All in all, for your use case, remember the golden rule of OOP: Make small concrete classes that do very few things, and do them well. If you need to start adding too many if () all over the place, then chances are you're mixing business logic, random decisions, and "whatabout" cases all over the place.
Imagine you have a class that processes Location data and uploads it to a server.
You may be tempted to:
Write all the code in the Activity/Fragment (or ViewModel); quickly becomes a mess.
Create a LocationUtils with static methods (or singleton pattern); a mess already, but also hard to test, and mock. What if you need more than one type of processing? Or what if you want to store them in a database, are you going to add more static methods?
Create a small LocationProcessor class, that receives two points (lat/long) does the processing in a small function, and returns the processed data, then create another class called LocationUploader, that receives clean input from a Processor, and uploads it to a server. None of these classes should think about "what if I don't have permissions, what if the user turns location off", etc. These are problems that exceed the responsibility of a class whose intention was to process location coordinates, nothing else. There should be other classes responsible for that. Remember, small classes, small responsibilities == less to worry about in a single file.
Conclusion?
Well, at this point there are better answers which will give you the copy-paste version of what you're looking for; I believe the concept you have to take out of this wall of text today, is that in order to write modern, testable, and simple functional code, a change in how you plan things must happen.
Long story short: when things are not synchronous, you need to keep something (an object) ready to be called back (hence the name callback), listening (or observing) (hence why we call them listener or observers), the emission of something (usually called an Observable, because it can be "observed").
Good luck!
Yes, the listener is asynchronous, it will only work if you print the variable inside onDataChange method.
However you can use a callback strategy to wait for Firebase to return the data. Something like this:
interface MyCallback {
fun onCallback(value: String )
}
fun readData(myCallback: MyCallback){
mDatabase.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
userName = snapshot.child(uid).child("name").getValue().toString()
myCallback.onCallback(value)
}
})
}
fun test(){
readData(object: MyCallback {
override fun onCallback(value : String) {
println(value)
}
})
}
As Martin says, it's an asynchronous operation, you should handle the text output after the asynchronous process has completed:
mDatabase.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented")
}
override fun onDataChange(snapshot: DataSnapshot) {
userName = snapshot.child(uid).child("name").getValue().toString()
println(userName) //--> Asynchronous request has ended, show the name
}
})
I am using google Firebase database in android. I need two fetch two set of data from database - userInfo and assignmentInfo. Then I need to combine them and show the data in a recycler view. What is the best way to approach this? As the fetching of data is async, this is getting messy.
One way i can think of is, check in both async functions success if other has completed. If so, get its data, combine and initialize the adapter. Is this the best way do this?
I have solved this kind of problem when i had to download something from a database before login in the user into the app, with this i fixed this problem.
To use ObservableInteger you can do this
first declare it
private ObservableInteger mObsInt;
then in your onCreate you will have a listener waiting for the values of the mObsInt to change, after those values change you can do anything you want
//Listener
mObsInt = new ObservableInteger();
mObsInt.set(0);
mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
{
#Override
public void onIntegerChanged(int newValue)
{
if (mObsInt.get()==1)
//Do something if the first asyncTask finishes
if (mObsInt.get()==2){
//Do something if the second asyncTask finishes, in this case i just go to another activity when both asyncTasks finish
Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
startActivity(mainIntent);
finish();
}
}
});
So, how it works
ObservableInteger will be looking for changes in the variable mObsInt, so lets say if mObsInt is equal to 1 it will do something, if is equal to 2 will do another thing, so, to solve this problem with 2 asynctasks is easy, when one of the asynctasks finishes mObsInt will be equal to 1 , if the other asyncTask finishes so mObsInt will be mObsInt++ , and then your mObsInt will be equal to 2, the listener will be waiting for the values, and then do what you want to do when the values match your if statment at the onCreate method
now, just in your asynctasks just put in your onPostExecute() method this line
mObsInt.set(mObsInt.get()+1);
so if the first async finish, mObsint == 1 , if the second finish mObsInt == 2, and then you handle what you want to do in your onCreate method
hope this helps for you, it helped me
You can get more info at this doc : https://developer.android.com/reference/android/databinding/ObservableInt.html
happy coding !
This can be achieved using a simple variable which will be incremented or will be keeping a flag if the both data is available to be merged and returned successfully from Firebase. However, this is neither the best approach and nor will work all the time as it can fail if the both async thread tries to update the flag at the same time. Then with the implementation given above, will work only if you can make the whole operation thread-safe.
If you consider building a thread-safe implementation on your own, that is not so difficult either. You might just consider using a Synchronized function which will update the flag you are keeping to detect if the both data from firebase is fetched.
However, I would suggest to get your implementation done using a LocalBroadcastReceiver. Which is easier to implement and this is an Android solution. Though there might be a several other approaches which are great as well, I think the implementation with BroadcastReceiver will serve your purpose fully.
You can check this answer for checking the implementation of a BroadcastReceiver. When the first part of the data is fetched from firebase, send the broadcast to be received by the BroadcastReceiver in your Activity and set a flag value for example, 1. Then when the second part is received, you will have to set the value to 2 again by just sending the broadcast on getting response from firebase. And then, when the value is found 2, that means the both operations has completed and now you can merge the two lists.
To avoid the overall thread-safe and fail safety coding overhead, you might consider fetching the data from firebase, synchronously. On getting the data for the first part, initiate the fetch operation for the second part for better control over your code.
I have just put some ideas, pick any that suits you. Hope that helps!
The simplest way I use in projects w/o Rx/Coroutines/other stuff. Just create AtomicInteger. Init it with value equals number of async operations. Then in each callback of your async functions call this:
if(counter.decrementAndGet == 0) { your_final_action}.
If you need some help with other ways like I mentioned before, feel free to ask me.
I've spent a lot of time looking at this and there are a tonne of ways to background in Java (I'm specifically looking at Java 8 solutions, it should be noted).
Ok, so here is my (generic) situation - please note this is an example, so don't spend time over the way it works/what it's doing:
Someone requests something via an API call
The API retrieves some data from a datastore
However, I want to cache this aggregated response in some caching system
I need to call a cache API (via REST) to cache this response
I do not want to wait until this call is done before returning the response to the original API call
Some vague code structure:
#GET
# // api definitions
public Response myAPIMethod(){
// get data from datastore
Object o = getData();
// submit request to cache data, without blocking
saveDataToCache();
// return the response to the Client
return Response.ok(data).build();
}
What is the "best" (optimal, safest, standard) way to run saveDataToCache in the background without having to wait before returning data? Note that this caching should not occur too often (maybe a couple of times a second).
I attempted this a couple of ways, specifically with CompletableFutures but when I put in some logging it seemed that it always waited before returning the response (I did not call get).
Basically the connection from the client might close, before that caching call has finished - but I want it to have finished :) I'm not sure if the rules are the same as this is during the lifetime of a client connection.
Thanks in advance for any advice, let me know if anything is unclear... I tried to define it in a way understandable to those without the domain knowledge of what I'm trying to do (which I cannot disclose).
You could consider adding the objects to cache into a BlockingQueue and have a separate thread taking from the queue and storing into cache.
As per the comments, the cache API is already asynchronous (it actually returns a Future). I suppose it creates and manages an internal ExecutorService or receives one at startup.
My point is that there's no need to take care of the objects to cache, but of the returned Futures. Asynchronous behavior is actually provided by the cache client.
One option would be to just ignore the Future returned by this client. The problem with this approach is that you loose the chance to take a corrective action in case an error occurrs when attempting to store the object in the cache. In fact, you would never know that something went wrong.
Another option would be to take care of the returned Future. One way is with a Queue, as suggested in another answer, though I'd use a ConcurrentLinkedQueue instead, since it's unbounded and you have mentioned that adding objects to the cache would happen as much as twice a second. You could offer() the Future to the queue as soon as the cache client returns it and then, in another thread, that would be running an infinite loop, you could poll() the queue for a Future and, if a non null value is returned, invoke isDone() on it. (If the queue returns null it means it's empty, so you might want to sleep for a few milliseconds).
If isDone() returns true, you can safely invoke get() on the future, surrounded by a try/catch block that catches any ExecutionException and handles it as you wish. (You could retry the operation on the cache, log what happened, etc).
If isDone() returns false, you could simply offer() the Future to the queue again.
Now, here we're talking about handling errors from asynchronous operations of a cache. I wouldn't do anything and let the future returned by the cache client go in peace. If something goes wrong, the worst thing that may happen is that you'd have to go to the datastore again to retrieve the object.
I really want to abuse #Asynchronous to speed up my web application, therefore I want to understand this a bit more in order to avoid incorrectly using this annotation.
So I know business logic inside this annotated method will be handled in a separated thread, so the user wont have to wait. So I have two method that persist data
public void persist(Object object) {
em.persist(object);
}
#Asynchronous
public void asynPersist(Object object) {
em.persist(object);
}
So I have couple scenario I want to ask which one of these scenario is not ok to do
1. B is not depend on A
A a = new A();
asynPersist(a); //Is it risky to `asynPersist(a) here?`
B b = new B();
persist(b);
//Cant asynPersist(B) here because I need the `b` to immediately
//reflect to the view, or should I `asynPersist(b)` as well?
2. Same as first scenario but B now depend on A. Should I `asynPersist(a)`
3. A and B are not related
A a = new A();
persist(a); //Since I need `a` content to reflect on the view
B b = new B();
asynPersist(b); //If I dont need content of b to immediately reflect on the view. Can I use asyn here?
EDIT: hi #arjan, thank you so much for your post, here is another scenario I want to ask your expertise. Please let me know if my case does not make any sense to u.
4. Assume User has an attribute call `count` type `int`
User user = null;
public void incVote(){
user = userDAO.getUserById(userId);
user.setCount(u.getCount() + 1);
userDAO.merge(user);
}
public User getUser(){ //Accessor method of user
return user;
}
If I understand you correctly, if my method getUserById use #Asynchronous, then the line u.setCount(u.getCount() + 1); will block until the result of u return, is it correct? So in this case, the use of #Asynchronous is useless, correct?
If the method merge (which merge all changes of u back to database) use #Asynchronous, and if in my JSF page, I have something like this
<p:commandButton value="Increment" actionListener="#{myBean.incVote}" update="cnt"/>
<h:outputText id="cnt" value="#{myBean.user.count}" />
So the button will invoke method incVote(), then send and ajaxical request to tell the outputText to update itself. Will this create an race condition (remember we make merge asynchronous)? So when the button tell the outputText to update itself, it invoke the accessor method getUser(), will the line return user; block to wait for the asynchronous userDAO.merge(user), or there might possible a race condition here (that count might not display the correct result) and therefore not recommend to do so?
There are quite a few places where you can take advantage of #Asynchronous. With this annotation, you can write your application as intended by the Java EE specification; don't use explicit multi-threading but let work being done by managed thread pools.
In the first place you can use this for "fire and forget" actions. E.g. sending an email to a user could be done in an #Asynchronous annotated method. The user does not need to wait for your code to contact the mail-server, negotiate the protocol, etc. It's a waste of everyone's time to let the main request processing thread wait for this.
Likewise, maybe you do some audit logging when a user logs in to your application and logs off again. Both these two persist actions are perfect candidates to put in asynchronous methods. It's senseless to let the user wait for such backend administration.
Then there is a class of situations where you need to fetch multiple data items that can't be (easily) fetched using a single query. For instance, I often see apps that do:
User user = userDAO.getByID(userID);
Invoice invoice = invoiceDAO.getByUserID(userID);
PaymentHistory paymentHistory = paymentDAO.getHistoryByuserID(userID);
List<Order> orders = orderDAO.getOpenOrdersByUserID(userID);
If you execute this as-is, your code will first go the DB and wait for the user to be fetched. It sits idle in between. Then it will go fetch the invoice and waits again. Etc etc.
This can be sped up by doing these individual calls asynchronously:
Future<User> futureUser = userDAO.getByID(userID);
Future<Invoice> futureInvoice = invoiceDAO.getByUserID(userID);
Future<PaymentHistory> futurePaymentHistory = paymentDAO.getHistoryByuserID(userID);
Future<List<Order>> futureOrders = orderDAO.getOpenOrdersByUserID(userID);
As soon as you actually need one of those objects, the code will automatically block if the result isn't there yet. This allows you to overlap fetching of individual items and even overlap other processing with fetching. For example, your JSF life cycle might already go through a few phases until you really need any of those objects.
The usual advice that multi threaded programming is hard to debug doesn't really apply here. You're not doing any explicit communication between threads and you're not even creating any threads yourself (which are the two main issues this historical advice is based upon).
For the following case, using asynchronous execution would be useless:
Future<user> futureUser = userDAO.getUserById(userId);
User user = futureUser.get(); // block happens here
user.setCount(user.getCount() + 1);
If you do something asynchronously and right thereafter wait for the result, the net effect is a sequential call.
will the line return user; block to wait for the asynchronous userDAO.merge(user)
I'm afraid you're not totally getting it yet. The return statement has no knowledge about any operation going on for the instance being processed in another context. This is not how Java works.
In my previous example, the getUserByID method returned a Future. The code automatically blocks on the get() operation.
So if you have something like:
public class SomeBean {
Future<User> futureUser;
public String doStuff() {
futureUser = dao.getByID(someID);
return "";
}
public getUser() {
return futureUser.get(); // blocks in case result is not there
}
}
Then in case of the button triggering an AJAX request and the outputText rendering itself with a binding to someBean.user, then there is no race condition. If the dao already did its thing, futureUser will immediately return an instance of type User. Otherwise it will automatically block until the User instance is available.
Regarding doing the merge() operation asynchronous in your example; this might run into race conditions. If your bean is in view scope and the user quickly presses the button again (e.g. perhaps having double clicked the first time) before the original merge is done, an increment might happen on the same instance that the first merge invocation is still persisting.
In this case you have to clone the User object first before sending it to the asynchronous merge operation.
The simple examples I started this answer with are pretty save, as they are about doing an isolated action or about doing reads with an immutable type (the userID, assume it is an int or a String) as input.
As soon as you start passing mutable data into asynchronous methods you'll have to be absolutely certain that there is no mutation being done to that data afterwards, otherwise stick to the simple rule to only pass in immutable data.
You should not use asynch this way if any process that follows the asynch piece depends on the outcome. If you persist data that a later thread needs, you'll have a race condition that will be a bad idea.
I think you should take a step back before you go this route. Write your app as recommended by Java EE: single threaded, with threads handled by the container. Profile your app and find out where the time is being spent. Make a change, reprofile, and see if it had the desired effect.
Multi-threaded apps are hard to write and debug. Don't do this unless you have a good reason and solid data to support your changes.