I have a situation when some cassandra queries may fail and I want to rethrow the exception back to the calling method where I need to perform some task based on the exception occurred, I am not able to achieve it with possible approached available like registering uncaughtExceptionHandler mechanism or by adding a callback handler to the Future object returned by the executeAsync() method of cassandra driver. Please help me out.
ThreadPoolExcecutor.java-
class ThreadPoolExecutor {
private static ThreadPoolExecutor instance;
ExecutorService executor;
public static synchronized ThreadPoolExecutor getInstance()
{
if( instance == null )
{
instance = new ThreadPoolExecutor();
}
return instance;
}
private ThreadPoolExecutor()
{
executor = Executors.newFixedThreadPool(16);
}
}
My Runnable class -
class CassanndraExecCommand implements Runnable {
private final Session session;
private final Statement statement;
public CassanndraExecCommand( Session session, Statement statement )
{
this.session = session;
this.statement = statement;
}
#Override
public void run()
{
ResultSetFuture future = session.executeAsync(statement);
Futures.addCallback(future, new FutureCallback<ResultSet>() {
#Override
public void onSuccess( ResultSet result )
{
// do nothing";
}
#Override
public void onFailure( Throwable t )
{
throw new RuntimeException(t);
}
});
}
}
As you can see above that I am rethrowing the exception in case of failure. Now question is how do I catch this exception in my calling method which is given below -
public static void executeSaveorUpdate( Statement statement, String keyspaceName )
{
ThreadPoolExecutor.getInstance().executor
.execute(new CassanndraExecCommand(getSession(keyspaceName), statement));
}
Note- cassandra version I am using is 2.2.6
You cannot catch exception that has been thrown in a different thread.
So, all you can do is to handle exception using a callback.
That's the price we all pay for async non-blocking calls performance.
Btw, if you need callback for failure only, you can omit "onSuccess":
Futures.addCallback(future,
new MoreFutures.FailureCallback<T>() {
#Override
public void onFailure(Throwable t) {
//Do whatever you need with t
}
},
executor);
I suggest to use ExecutorService.submit(Runnable) method instead of execute. Submit will return Future<T> object for you, so you can easily handle exception if any.
Future<Void> result = ThreadPoolExecutor.getInstance().executor
.submit(new CassanndraExecCommand(getSession(keyspaceName), statement));
try {
result.get();
} (catch ExecutionException e) {
// e.getCause() will return your root exception
}
Hope it helps!
Aside, I think it will be better to implement Callable instead of Runnable with CassanndraExecCommand. This allows you to handle Cassandra response completely (both good and bad) and avoid callbacks.
Related
Can I get a future object from a handler?
Handler handler = new Handler(getMainLooper());
Future<String> future = handler.post(new Callable<String>() {
public String call() throw Exception {
// run in the main thread
return askForPassword();
}
}); // can I do something like this?
String password = future.get(); // wait until finish
// do network things...
I have a network thread and I need to ask the user for password, since I need to show an input dialog I have to do this on Main thread, but handler can not return values.
I can do the same thing by
Handler handler = new Handler(getMainLooper());
String password = null;
handler.post(() -> {
// run in the main thread
password = askForPassword();
});
while (password == null) { /*wait until finish*/ }
// do network things...
But this looks stupid and inconvenient
Handler is fundamentally asynchronous and thus whatever you put there is not guaranteed to run immediately (moreover, you can postDelayed or postAtTime). Then it is clear, that you can not return any value from the Handler directly to the code that posted it. So you have to work this around.
Another obstacle is that in Java your closure can capture only final variables and you have to work this around as well.
New API (CompletableFuture)
Unfortunately original Future Java API is not suitable for composition. If you target new devices only and thus can use newer CompletableFuture, you may do something like this:
CompletableFuture<String> askForPasswordNewApi() {
// your UI code that creates Future
}
void doNetworkThingNewApi() {
// some network stuff
final CompletableFuture<String> passwordFutureWrapper = new CompletableFuture<String>();
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
CompletableFuture<String> future = askForPasswordNewApi();
// bind the real future to the outer one
future.handle((r, ex) -> {
if (ex != null)
passwordFutureWrapper.completeExceptionally(ex);
else
passwordFutureWrapper.complete(r);
return 0;
});
}
});
// wait until finish
// don't forget to handle InterruptedException here
String password = passwordFutureWrapper.get();
// do more network things...
}
The idea is rather simple: create outer final variable passwordFutureWrapper that can be captured by the Handler and bind this wrapper to the real future
Side note: if your askForPassword already returns Future but you can't use the new API, you probably have re-implemented something similar to CompletableFuture anyway, so you just need to modify this code a bit to allow binding of one future to another.
Old API
If you can't use CompletableFuture in your code yet, but still somehow has a method with a Future-based signature:
Future<String> askForPasswordOldApi()
you may do it more explicitly:
void doNetworkThingOldApi() {
// some network stuff
final CountDownLatch syncLock = new CountDownLatch(1);
final Future<String>[] futureWrapper = new Future<String>[1];
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
final CompletableFuture<String> future = askForPasswordOldApi();
futureWrapper[0] = future;
syncLock.countDown();
}
});
String password;
try {
// 1 minute should be quite enough for synchronization between threads
if (!syncLock.await(1, TimeUnit.MINUTES)) {
// log error, show some user feedback and then stop further processing
return;
}
password = futureWrapper[0].get(); // wait until finish
} catch (InterruptedException ex) {
// log error, show some user feedback and then stop further processing
return;
} catch (ExecutionException ex) {
// log error, show some user feedback and then stop further processing
return;
}
// do more network things...
}
The idea here is following:
Use single-element array as a simple container to work around final-closure limitations
Use CountDownLatch to ensure synchronization between the network and the UI threads i.e. that futureWrapper[0] is not null by the time we start waiting on the result with get.
Update (design for library API)
If you are designing API and want to have a single entry for login with different additional scenarios handled by a callback, I'd do using custom implementation of something similar to CompletableFuture:
public interface ResultHandler<T> {
void resolve(T result);
void cancel();
}
class ResultHandlerImpl<T> implements ResultHandler<T> {
enum State {
Empty,
Resolved,
Cancelled
}
private final Object _lock = new Object();
private State _state = State.Empty;
private T _result;
#Override
public void resolve(T result) {
synchronized (_lock) {
if (_state != State.Empty) // don't override current state
return;
_result = result;
_state = State.Resolved;
_lock.notifyAll();
}
}
#Override
public void cancel() {
synchronized (_lock) {
if (_state != State.Empty) // don't override current state
return;
_state = State.Cancelled;
_lock.notifyAll();
}
}
public boolean isCancelled() {
synchronized (_lock) {
return _state == State.Cancelled;
}
}
public boolean isDone() {
synchronized (_lock) {
return _state == State.Resolved;
}
}
public T get() throws InterruptedException, CancellationException {
while (_state == State.Empty) {
synchronized (_lock) {
_lock.wait();
}
}
if (_state == State.Resolved)
return _result;
else
throw new CancellationException();
}
}
I would probably make interface public but implementation ResultHandlerImpl package-private so it would be harder for the users to mess up with implementation details. Then in callback methods I'd pass my callback ResultHandler as a parameter (actually it obviously would be a ResultHandlerImpl):
public interface LoginCallback {
void askForPassword(ResultHandler<String> resultHandler);
}
And my login method would look something like this (assuming you have private methods tryRestoreSession that doesn't need password and loginWithPassword that requires):
public boolean login(final LoginCallback loginCallback) {
if (tryRestoreSession()) {
return true;
} else {
final ResultHandlerImpl<String> passwordHandler = new ResultHandlerImpl<>();
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
// run in the main thread
loginCallback.askForPassword(passwordHandler);
}
});
String password;
try {
password = passwordHandler.get();
} catch (CancellationException e) {
return false;
} catch (InterruptedException e) {
return false;
}
return loginWithPassword(password);
}
}
What I think is important here:
I think that passing a callback to LoginCallback makes it easier to write an asynchronous UI-based implementation using standard Java.
ResultHandlerImpl has cancel method. So if the user, for example, forgot the password there is a way to cancel whole login process and not get stuck with a background thread waiting for a password forever
ResultHandlerImpl uses explicit synchronization and wait/notifyAll to establish happens-before relationship between actions on different threads to avoid.
ResultHandlerImpl uses wait/notifyAll so the background thread doesn't consume CPU (and battery) while waiting for the UI.
UPDATED using "wait and notify" instead of looping
UPDATED 2 synchronized methods
Finally I end up with object wrapper(thansk to #SergGr ) and handler
class ObjectWrapper<T> {
T object;
boolean ready;
synchronized void set(T object) {
this.object = object;
this.ready = true;
notifyAll();
}
T get() {
while (!ready) {
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
return null;
}
}
}
return object;
}
}
In my network thread
Handler handler = new Handler(getMainLooper());
ObjectWarpper<String> wrapper = new ObjectWarpper<>();
handler.post(() -> wrapper.set(askForPassword()));
String password = wrapper.get();
I'm implementing a layer to wrap a 3rd party communication layer.
The contract I need to implement is:
FutureTask<SomeData> send(Request request);
My layer has an onMessageReceived method, which is called by the 3rd party when a response arrives.
The approach I've taken to implement my layer is as follows:
I have a callable, which waits on a condition with a timeout:
interface MyCallable<T> extends Callable<T> {
void signal();
}
class CallableWithSignal<T> implements MyCallable<T> {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private long waitTime;
public CallableWithSignal(int waitTimeSeconds){
this.waitTime=waitTimeSeconds;
}
#Override
public T call() throws Exception {
lock.lock();
try {
boolean wasSignaled = condition.await(waitTime, TimeUnit.SECONDS);
if(wasSignaled)
return null;
System.out.println("throwing exeption");
throw new Exception("timeout");
} finally {
lock.unlock();
}
}
#Override
public void signal() {
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}
}
I also have extended FutureTask to expose the set method, as follows:
class MyFutureTask<V> extends FutureTask<V> {
private MyCallable<V> myCallable;
public MyFutureTask(MyCallable<V> r) { super(r); myCallable = r;}
#Override
public void set(V x) { super.set(x); }
#Override
public void setException(Throwable t) { super.setException(t); }
#Override
protected void done() {
super.done();
myCallable.signal();
}
}
When the task is done, I signal the callable to stop it.
So every time a send is called, I create a new MyFutureTask, run it using an executor, save it in a map and return it.
When onMessageReceived is called I find the task in the map and set its result with the set method.
Is this a good approach?
And another question: is it a good approach to move the executor logic inside the task? I mean, to create a start method for it, which will run the task using the executor.
please advice.
I am writing an Spring-mvc application.
I am executing task using ThreadPoolTaskExecutor.
I have below sample code.
MyClass.java
public class MyClass {
public void startProcess() {
ThreadPoolTaskExecutor taskExecutor = //Initializing
for (int i = 1; i <= 5; i++) {
taskExecutor.execute(new MyRunnable());
// I can call taskExecutor.submit(task); also, if required
}
}
}
MyRunnable.java
public class MyRunnable implements Runnable {
#Override
public void onRun() {
try {
//Code which generates exception like below
throw new Exception("Runtime Exception");
} catch (Exception e1) {
// log or throw the exception
}
}
}
I want to notify startProcess() about the exception occurred in MyRunnable's run method.
Can any one please guide me for this.
I found below links but it is not solving my problem.
Handling exceptions from Java ExecutorService tasks
http://java.dzone.com/articles/spring-async-and-exception
Thanks.
Edit:
One more question. If I am using #Async for asynchronous call to my some other method and If I want to check for the exception occured in async method then what should I do? As async method also returns future object.
Answer for #Async question I got from here
Instead of Runnable, implement Callable. A Callable can throw an exception, and when you retrieve the result of the Callable using a Future, you will get the exception thrown as an ExecutionException:
public class MyCallable implements Callable<Void> {
public Void call() throws Exception {
try {
//Code which generates exception like below
throw new Exception("Runtime Exception");
} catch (Exception e1) {
// log or throw the exception
}
return null; // To satisfy the method signature
}
}
In MyClass:
List<Future<Void>> futures = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
Future<Void> future = taskExecutor.submit(new MyCallable());
futures.add(future);
}
// After all tasks have started, now wait for all of them to complete (they run in parallel)
// and check if there were any exceptions
for (Future<Void> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
// Access the exception thrown by the different thread.
e.getCause().printStackTrace();
}
}
You can add constructor with some listener to your Thread.
Like:
ExceptionListener:
public class ExceptionListener{
public void doSomething(long threadId,Exception e){
//...e.g., notify startProcess()
}
}
MyRunnable:
public class MyRunnable implements Runnable {
private ExceptionListener listener;
private MyRunnable(ExceptionListener exception) {
this.listener = listener;
}
#Override
public void run() {
//...
listener.doSomething(Thread.currentThread().getId(),new Exception("Runtime Exception"));
//...
}
}
startProcess():
public void startProcess() {
ThreadPoolTaskExecutor taskExecutor = //Initializing
ExceptionListener listener= new ExceptionListener();
for (int i = 1; i <= 5; i++) {
taskExecutor.execute(new MyRunnable(listener();
// I can call taskExecutor.submit(task); also, if required
}
}
Or, you can use Thread.UncaughtExceptionHandler, like described here.
edited.
Clarification:
if exception occurs, I have to stop my further execution of other
processes. So I want to catch or get notified about the exception in
startProcess method. – Naman Gala 1 hour ago
Answer:
I suppose that your worker thread will have while cycle. So you can just pass volatile
boolean to each thread and set it up to true or
false in case of exception, cycle condition will be this boolean
variable. – Maksym 58 mins ago
Is there a lightweight pattern to cancel long running method, which replaces code like this:
public void longComputations() {
... first step...
if ( cancelled ) {
rollbackWork();
return;
}
... second step...
if ( cancelled ) {
rollbackWork();
return;
}
... third step...
if ( cancelled ) {
rollbackWork();
return;
}
}
I know that I can make a Task class, subdivide steps to task objects, make a queue and just do tasks step by steps in loop with cancelation checking, but I'm just wondering is there any simple code-structure pattern for such situation.
I am not aware of such a mechanism. Since you have to track your work in order to be able to perform rollbackWork(), a well-designed object-oriented solution is your best choice anyway, if you want to further evolve this logic! Typically, such a scenario could be implemented using the command pattern, which I still find pretty lightweight:
// Task or Command
public interface Command {
void redo();
void undo();
}
A scheduler or queue could then take care of executing such task / command implementations, and of rolling them back in order.
How about this edit, not a pattern though? Exceptions are very cheap, so it should be fast.
public void caller(){
try{
longComputations();
} catch (MeaningfulRuntimeException e){
rollbackWork(e.getStep());
}
}
public void longComputations() {
... first step...
checkStatus(1);
... second step...
checkStatus(2);
... third step...
checkStatus(3);
}
public void checkStatus(int step){
if ( cancelled ) {
... we may rollback here or throw an exception ...
throw MeaningfulRuntimeException(step);
}
}
If the steps call methods which throw InterruptedException then you can use Thread.interrupt(). You will still need to maintain enough state information to do the rollback properly.
If the steps cannot be interrupted this way, you should not consider relying on the deprecated Thread.stop() mechanism since it is inherently unsafe.
It seems that either way it makes sense to do exactly what you described: encapsulate this workflow logic in a class independent of the computation steps. It should support cancellation and/or interruption and accept a bunch of tasks to be executed. Note that the tasks to be fed into the workflow should provide at least two methods: one to perform the computation and one to roll it back.
You might want to consider using the java.util.concurrent package. You need to wrap your working steps as Callables (or Runnables).
public class InterruptibleTest {
public static void main(String[] args) { try {
final ExecutorService queue = Executors.newFixedThreadPool(1);
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
queue.submit(new Callable<Void>() { #Override public Void call() { busyWait(1000); return null; } });
final AtomicBoolean cancelled = new AtomicBoolean();
new Thread() { #Override public void run() {
try { Thread.sleep(1500); } catch (InterruptedException ex) { }
queue.shutdownNow();
cancelled.set(true);
}
}.run();
if (cancelled.get()) { rollback(); }
queue.shutdown();
System.out.println("Finished");
} catch (Exception ex) { ex.printStackTrace(System.err); } }
public synchronized static void busyWait(int millis) {
System.out.println("Start");
long until = System.currentTimeMillis() + millis;
while (System.currentTimeMillis() < until) { }
System.out.println("Stopped");
}
public synchronized static void rollback() {
System.out.println("Rollback!");
}
}
Note that shutdownNow() might call interrupt() on the currently executing work thread. You will probably also need to synchronize your rollback() because shutdownNow() returns before non-interruptible code finishes execution.
How can I get output from Java anonymous classes? In .Net I would use closures.
executor = Executors.newSingleThreadExecutor();
final Runnable runnable = new Runnable() {
public Exception exception;
#Override
public void run() {
try {
doSomething();
}
catch (Exception exception) {
// I'd like to report this exception, but how?
// the exception member is not readable from outside the class (without reflection...)
this.exception = exception;
}
}
};
executor.submit(runnable);
// Here I'd like to check if there was an exception
The Executor interface offers no way to do this. However, when you call newSingleThreadExecutor() you will get an ExecutorService which contains functionality for that.
Calling ExecutorService.submit() returns an instance of Future<?>, which you can use to get the result value of the computation.
If the execution resulted in an exception, calling get will cause an ExecutionException to be thrown.
To obtain an exception from a task run on an executor you want to use Callable instead of Runnable.
The call() method of Callable can throw checked exceptions. When you call get() on your Future instance it will throw an ExecutionException if your call() method threw a checked exception. You can then access the underlying checked exception by calling getCause() on the ExecutionException.
Hackish.... but, you could have a static variable/method that the Runnable calls to report the exception
public class Driver {
static Exception exec;
static final Runnable runnable = new Runnable() {
public Exception exception;
public void run() {
try {
throw new Exception("asdf");
}
catch (Exception exception) {
exec = exception;
}
}
};
public static void main(String[] args) throws Exception{
ExecutorService e = Executors.newSingleThreadExecutor();
e.submit(runnable);
e.shutdown();
while(e.isShutdown()==false){
Thread.sleep(2000);
}
System.out.println(exec);
}
You could wrap your thrown exception in a RuntimeException and put your executor.submit() call in a try/catch block:
executor = Executors.newSingleThreadExecutor();
final Runnable runnable = new Runnable() {
#Override
public void run() {
try {
doSomething();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
};
try{
executor.submit(runnable);
} catch (Throwable t) {
Throwable cause = t.getCause();
//do what you want with the cause
}
If you declare the exception to be final, the anonymous class will be able to store the value there, and you can check the variable when the run() is done.
Edit to add: Sorry, I meant to make it a final array of one exception. Idea does this automatically for me, so I often forget about the extra redirection.
final Exception[] except;