views:

321

answers:

6

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
+6  A: 

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.

andri
So I should not use Runnable, right?
ripper234
If you want to get some result, you should use Callable. There is no way to return a value as a result from Runnable (IIRC calling `get` for runnables returned null)
andri
Rather, the task I want to perform proper has no return value, but I would like to be notified on exceptions. Runnable.run() doesn't declare exceptions, so I can't use that. Callable must return something.I can have the callable return the exception, but that seems a bit suboptimal. Ideally I'd like another similar class whose 'run equivalent' can throw exceptions, but returns void. Oh well.
ripper234
You can always throw runtime exceptions from Runnables :)
andri
Just return null or new Object() from the Callable and ignore it.
Mark
Doesn't quite cut it, because I don't control the code throwing the exception, and wrapping it is uglier than a Callable that always returns null.
ripper234
Simply declare your Callable to return Void and then return null when your method completes.
Adamski
A: 

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;

PanCrit
I don't believe this is correct; if you declare the exception to be final you won't be able to update the exception from the class's run() method (as you cannot modify final references).
Adamski
+2  A: 

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.

Mark
This answer is bang-on; Other answers providing hacky solutions involving Runnable should be ignored. The standard idiom for this type of problem is to use Callable, not Runnable.
Adamski
+1; this is what Callable was invented for.
Alex Feinman
Callable is for getting output, so if you want to convert the exception into a return value indicating failure, defeating the point of exceptions in the first place, then Callable<Exception> is appropriate. Or just use the mechanisms given in the library - putting in a Runnable returns a Future<?>, and getting the value rethrows the exception.
Pete Kirkham
If you use Runnable though you cannot through a checked exception, so I'd still advocate the use of a Callable<Void> instead, as it offers greater flexibility.
Adamski
*throw (not through!) ... The heat is getting to me.
Adamski
A: 

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);

}
Rick
A: 

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
}
akf
A: 

It is bit ugly, but you can set it to member of containing class.

public class Containing {
    private Exception exception;

    public void doIt() {
        Executor executor = Executors.newSingleThreadExecutor();

        final Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    throw new Exception();
                } catch (Exception exception) {
                    Containing.this.exception = exception;
                }
            }
        };
        executor.execute(runnable);
       // Here I'd like to check if there was an exception
       if (exception != null) {
           System.out.println("There was");
       }
    }

    public static void main(String args[]) {
        new Containing().doIt();
    }

}
Mikko Maunu