I am using realm in my firebase service and i am closing the instance of realm in my finally block but the problem arises when i perform an asynchronous operation in my try block in which case the finally executes before the async complete and the realm instance is closed which causes the app to crash since the async operation performs realm related tasks.
try {
// perform async task that requires realm
} catch (Exception e) {
e.printStackTrace();
} finally {
if (realm != null && !realm.isClosed())
realm.close();
}
This is what the code roughly looks like.If i try closing the realm instance anywhere else i get an error saying that i am accessing the realm instance from the incorrect thread,is there a way i can wait until the async operation is completed and only then close the realm instance.
So, you really can't perform an asynchronous task inside a try/catch block.
... and by "can't" I don't mean that it is bad practice, I mean that it is simply not possible, by the very definition of "asynchronous".
What you are doing inside the try/catch block is enqueuing the task, for later execution. Once the task is enqueued (not executed!) the try/catch block is exited.
If you want the try/catch block around the asynchronously executed code, you need to execute it at part of the asynchronous task.
Furthermore, as you will see in the documentation, you cannot pass most Realm objects between threads. You cannot open the realm on some thread and then pass it, open, to an asynchronous task.
Related
I'm writing stock quotes processing engine and receiving async notifications from postgresql database with pgjdbc-ng-0.6 library. I'd like to know if my database connection is still alive, so I wrote in thread's run() method
while (this.running) {
try {
this.running = pgConnection.isValid(Database.CONNECTION_TIMEOUT);
Thread.sleep(10000);
} catch (SQLException e) {
log.warn(e.getMessage(), e);
gracefullShutdown();
} catch (InterruptedException e) {
gracefullShutdown();
}
}
I read isValid() declaration and it stated that the function will return false if timeout reached. However, isValid() just hangs indefinitely and run() is never exited. To create connectivity issues I disable VPN my application uses to connect to database. Rather rude way,but function must return false... Is this bug in driver or another method exists?
I tried setNetworkTimeout() in PGDataSource, but without any success.
One of the possible handlings of this problem for Enterprise developers is to use existing threadPool to create a separate thread for submitting in
Callable with test call() for DB (in case of Oracle it may be "SELECT 'OK' FROM dual"),
using statement object.execute('...'), (not executeUpdate, because it
may cause the call to get stuck), and further using for example - future.get(3, TimeUnit.Seconds).
Using this approach in a final call you need to catch InterruptedException
for get() call. If Callable throws you set database availability as false, if not then true.
Before using this approach inside the Enterprise application you have to ensure you have access to application server threadPool executor in certain object and #Autowire it there.
I am having trouble with waiting for fresh data on a worker thread. The data object is copied to realm on a main thread, but almost immediately after that I need to access this object from a worker thread, which then reports that no such object exists in realm right now ( its newly opened realm instance ) . I remember that there was a method load() that would block execution to the point of next update, but it was removed in newer versions. And I can't use change notification for this as this is not a Looper thread..
The only way I can think of right now is to sleep the thread for some magic period of time and pray to god that it has updated already, but that approach is imho wildly indeterministic.
Can anybody advise here, how can I ensure that I read the most current data at the time ?
A possible hack would be to create a transaction that you cancel at the end.
realm.beginTransaction(); // blocks while there are other transactions
... // you always see the latest version of the Realm here
realm.cancelTransaction();
This works if the thread is started after the UI thread saves the object into the Realm.
You can also try this workaround: https://stackoverflow.com/a/38839808/2413303 (although it doesn't really help with waiting)
try using QueryListener, which is trigger whenewer object, satisfying certain criteria is updated
using realm.beginTransaction() and realm.commitTransaction() instead of realm.executeTransaction(Realm.Transaction)
The problem with this is that executeTransaction() automatically handles calling realm.cancelTransaction() in case an exception is thrown, while the other alternative typically neglects the try-catch.
Yes, you’re supposed to call cancel on transactions that aren’t going to end up being committed.
For example, on background threads:
// SAY NO TO THIS
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction(); // NO
realm.copyToRealm(dog)
realm.commitTransaction(); // NO NO NO NO NO
// YOU NEED TO CLOSE THE REALM
// ----------------------
// SAY YES TO THIS
Realm realm = null;
try { // I could use try-with-resources here
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.insertOrUpdate(dog);
}
});
} finally {
if(realm != null) {
realm.close();
}
}
// OR IN SHORT (Retrolambda)
try(Realm realmInstance = Realm.getDefaultInstance()) {
realmInstance.executeTransaction((realm) -> realm.insertOrUpdate(dog));
}
The problem with this is that on background threads, having an open Realm instance that you don’t close even when the thread execution is over is very costly, and can cause strange errors. As such, it’s recommended to close the Realm on your background thread when the execution is done in a finally block. This includes IntentServices.
I have multiple threads calling an API. API opens a socket which doesn't have timeout set on it. However, I have timeout set on future.get()..If socket is kept open forever does future's timeout come in action and get out of the processing of task which calls an API ?
The Future.get will throw a TimeoutException when the timeout expires.
Yet, the underlying task will keep executing unless you have a way to interrupt it. It can be for instance by closing the socket if you have access to it or by any mechanism that the API provides.
You can try to interrupt the execution but it is up to code to catch the interruption (via Thread.interrupted()) so it may have no effect depending on the underlying task implementation:
try {
Future<R> future = // ...
} catch (TimeoutException e) {
// ...
future.cancel(true); // try to interrupt
}
I am having difficulty trying to correctly program my application in the way I want it to behave.
Currently, my application (as a Java Servlet) will query the database for a list of items to process. For every item in the list, it will submit an HTTP Post request. I am trying to create a way where I can stop this processing (and even terminate the HTTP Post request in progress) if the user requests. There can be simultaneous threads that are separately processing different queries. Right now, I will stop processing in all threads.
My current attempt involves implementing the database query and HTTP Post in a Callable class. Then I submit the Callable class via the Executor Service to get a Future object.
However, in order properly to stop the processing, I need to abort the HTTP Post and close the database's Connection, Statement and ResultSet - because the Future.cancel() will not do this for me. How can I do this when I call cancel() on the Future object? Do I have to store a List of Arrays that contains the Future object, HttpPost, Connection, Statement, and ResultSet? This seems overkill - surely there must be a better way?
Here is some code I have right now that only aborts the HttpPost (and not any database objects).
private static final ExecutorService pool = Executors.newFixedThreadPool(10);
public static Future<HttpClient> upload(final String url) {
CallableTask ctask = new CallableTask();
ctask.setFile(largeFile);
ctask.setUrl(url);
Future<HttpClient> f = pool.submit(ctask); //This will create an HttpPost that posts 'largefile' to the 'url'
linklist.add(new tuple<Future<HttpClient>, HttpPost>(f, ctask.getPost())); //storing the objects for when I cancel later
return f;
}
//This method cancels all running Future tasks and aborts any POSTs in progress
public static void cancelAll() {
System.out.println("Checking status...");
for (tuple<Future<HttpClient>, HttpPost> t : linklist) {
Future<HttpClient> f = t.getFuture();
HttpPost post = t.getPost();
if (f.isDone()) {
System.out.println("Task is done!");
} else {
if (f.isCancelled()) {
System.out.println("Task was cancelled!");
} else {
while (!f.isDone()) {
f.cancel(true);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("!Aborting Post!");
try {
post.abort();
} catch (Exception ex) {
System.out.println("Aborted Post, swallowing exception: ");
ex.printStackTrace();
}
}
}
}
}
}
Is there an easier way or a better design? Right now I terminate all processing threads - in the future, I would like to terminate individual threads.
I think keeping a list of all the resources to be closed is not the best approach. In your current code, it seems that the HTTP request is initiated by the CallableTask but the closing is done by somebody else. Closing resources is the responsibility of the one who opened it, in my opinion.
I would let CallableTask to initiate the HTTP request, connect to database and do it's stuff and, when it is finished or aborted, it should close everything it opened. This way you have to keep track only the Future instances representing your currently running tasks.
I think your approach is correct. You would need to handle the rollback yourself when you are canceling the thread
cancel() just calls interrupt() for already executing thread. Have a look here
http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html:
As it says
An interrupt is an indication to a thread that it should stop what it
is doing and do something else. It's up to the programmer to decide
exactly how a thread responds to an interrupt, but it is very common
for the thread to terminate.
Interrupted thread would throw InterruptedException
when a thread is waiting, sleeping, or otherwise paused for a long
time and another thread interrupts it using the interrupt() method in
class Thread.
So you need to explicitly code for scenarios such as you mentioned in executing thread where there is a possible interruption.
I have a very long running task that periodically polls a web service for XML content. I am using a Scheduled executor for these periodic runs and everything works fine.
The JavaDoc of ScheduledExecutorService scheduleAtFixedRate state that
... If any execution of the task encounters an exception, subsequent executions are suppressed ...*
This clearly implies that in case of unhandled exceptions, The application even though running , is effectively in a stopped state and doing nothing. I want to ensure that the task execution does not stop, Apart from catching all exceptions, is there any other way to deal with this?
#Override
public void run() {
try {
// fetch xml feed from network,
// parse the feed and dump to file the json.
} catch (Exception e) {
logger.error("Unhandled exception " + e);}
}
}
I don't think that there is another way around other than catching all Exceptions in the run method.
If you don't mind using 3rd party libraries, you could use Quartz. Take a look at here.
hth