I have a method that has an anonymous inner class. I want to throw an unchecked exception from inside the anonymous inner class, and catch it outside of the class. I'm having trouble doing this.
#Override
public void showAchievements(){
androidLauncher.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
loadingView.showLoadingView();
Games.getAchievementsClient(androidLauncher, signedInAccount)
.getAchievementsIntent()
.addOnSuccessListener(new OnSuccessListener<Intent>() {
#Override
public void onSuccess(Intent intent) {
throw new RuntimeException("Test exception");
}
});
} catch (Exception e){
// Not catching
}
}
});
}
My exception is not being caught. What am I doing wrong?
You are throwing an exception in a callback method.
Either the callback method is never invoked, it is not invoked synchronously, or
the code that ultimately invokes the callback method is catching it.
Without seeing more of your code, it is impossible to say which.
This is because you have to move your try-catch-statement inside the onSuccess method. The listener is called at a later point.
Related
I have a callback which may throw a custom exception.
I'm trying to throw it, but it's not being catched on the outer scope, nor the compiler let me catch it, it says: "Exception is never thrown is the corresponding try block", even though it is.
this is my code:
public void openAsync(MessageAsyncCallback callback) {
try {
this.sendChannelOpen(this.getChannel(), getChannelOpenData().getFlags(), new MessageAsyncCallback() {
#Override
public void onComplete() throws NanoException {
// INanoPacket message = transport.getMessageByClassName(AudioServerHandshake.class.getName());
INanoPacket message = transport.getMessageByClassName(AudioClientHandshake.class.getName());
Log.info("Got audio server handshake, trying to client-handshake it");
sendClientHandshakeAsync((AudioServerHandshake) message, callback);
}
});
} catch (NanoException e) {
System.exit(-2);
}
}
and it doesn't let me catch NanoException
EDIT:
inside transport.getMessageByClassName I throw a NanoException.
EDIT2:
this is the method who invokes the exception:
public INanoPacket getMessageByClassName(String destClassName) throws NanoException {//} throws NanoException {
long startTime = System.currentTimeMillis(); // fetch starting time
INanoPacket message = this.getMessageFromTCPQueue();
while (!(message.getClass().getName().equals(destClassName)) && isRuntimeValid(startTime)) {
this.insertToTCPQueue(message); // put message back in queue
message = this.getMessageFromTCPQueue();
}
if (!(message.getClass().getName().equals(destClassName))) {
// timeout...
throw new NanoException("Couldn't find destination message: " + destClassName);
}
return message;
}
and I want to handle the exception not even in openAsync but on the method that calls openAsync.
why? because I'm handling messages coming from a remote device, this is why it's async. and I'm using some kind of timeout to wait for a specific message, and if the message isn't coming I want to restart the whole program.
Please notice that in your code you are not invoking onComplete method, you are defining it.
The exception would be thrown in a separate part of the code, possibly separate Thread (as it seems to be async). Therefore the "Exception is never thrown is the corresponding try block" message is right, as the exception will never be thrown when invoking this.sendChannelOpen(...) method.
Your try-catch statement needs to wrap the place where you invoke the onComplete method. As only by invoking onComplete method can you expect NanoException.
EDIT based on comments:
If you need to handle the exception throw in getMessageByClassName you can do it in onComplete method and not rethrow it. If you want to handle it somewhere else, you'd need to provide us the code of sendChannelOpen method or a place where the callback is invoked.
EDIT2 (based on question edits):
Please see the code below, as an example of how you can communicate between threads. I've used Latch, but there are other classes in java.util.concurrent that you may find useful.
BTW, I'm not going into the discussion why you want to restart the whole app on your NanoException, although there might be other options worth considering for recovering from that Exception.
import java.util.concurrent.CountDownLatch;
class NanoException extends Exception {}
interface MessageAsyncCallback {
void onComplete() throws NanoException;
}
public class AsyncApp {
private static final CountDownLatch errorLatch = new CountDownLatch(1);
public static void main(String[] args) {
new AsyncApp().run();
}
void run() {
sendChannelOpen("something", new MessageAsyncCallback() {
#Override
public void onComplete() throws NanoException {
// the whole try-catch-sleep is not really needed, just to wait a bit before exception is thrown
try {
// not needed, just to wait a bit before exception is thrown
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new NanoException();
}
throw new NanoException();
}
});
try {
System.out.println("This is a main thread and we wait here, while the other thread executes...");
errorLatch.await();
System.out.println("Latch has reached 0, will now exit.");
System.exit(-2);
} catch (InterruptedException e) {
System.out.println("Error in main thread.");
System.exit(-1);
}
}
void sendChannelOpen(String notImportant, MessageAsyncCallback troublesomeCallback) {
runSomethingInSeparateThread(troublesomeCallback);
}
void runSomethingInSeparateThread(MessageAsyncCallback troublesomeCallback) {
new Thread(() -> {
try {
troublesomeCallback.onComplete();
} catch (NanoException e) {
System.out.println("You can catch it here, and do system exit here or synchronize with main Thread as below");
errorLatch.countDown();
}
}).start();
}
}
I have a method. This method has a catch block.
// pseudo code
private void function() {
try {
// something
} catch(exception e) {
// error handling
}
}
This method is called in another class
In one scenario the class is implemented with its own catch block
// pseudo code
private void anotherFunction() {
try {
function();
} catch {
//another catch block
}
Now I just want to execute the code in the catch block where the function is called and don't call the catch block implemented in the class. Is there a way to do this or should I think about another approach?
A workaround is to move your logic to another method which doesn't handle that exception, but just passes it upwards e.g:
public void unsafeFunction() throws Exception{
// something
}
And then call that method from your both classes, where both handle the exception differently:
public void function(){
try {
unsafeFunction();
} catch(Exception e){
// error handling
}
}
And:
public void anotherFunction(){
try {
unsafeFunction();
} catch(Exception e){
// other error handling
}
}
That way you leave what should be done with the exception to the caller.
Another completly different approach is to use the java.util.function.Consumer interface from Java 8 and accept that in your function, the caller then can just pass the error-handler into it:
public void function(Consumer<? super Exception> errorHandler){
try{
// something
} catch(Exception e){
// delegate to handler
errorHandler.accept(e);
}
}
Which can then be used like this:
public void someFunction(){
function(e -> {
// error handling
});
}
And:
public void anotherFunction(){
function(e -> {
// other error handling
});
}
There must be a reason to catch the exception. Say that reason can be tested in a separate method:
private boolean testCircumstanceThrowingException() {
if (exceptionalCircumstance) {
return false;
} else {
return true;
}
}
then you can implement your original function as:
private void functionCatchingException(){
if (testCircumstanceThrowingException()) {
//error handling
}
function();
}
and
private void anotherFunction() {
if (testCircumstanceThrowingException()) {
//error handling
}
function();
}
this way, during the normal running of the application, no exceptions are thrown. And this is how it should be because exceptions are for exceptional circumstances. If you somehow get to a state where exceptions are expected then something is wrong.
You should only rely on excpetions if there is no other way. For instance, if your specific use of the function cannot test the exceptional circumstance and you're required to use function. Take a look at Lino's answer for possible workarounds.
Java purists will notice that you can simply do return exceptionalCircumstance; but this code was just intended to show that a function that tests for the exceptional circumstance may be required; the result may not even be a boolean.
Of course you may now want to rename functionCatchingException :)
In your first code snippet:
private void function() {
try {
// something
}
catch (Exception e) {
// error handling
throw e; // rethrow?
}
}
you basically have two options with Java. You can either swallow the exception, or you can rethrow it. If you swallow it, then the caller of this method won't see an exception. If you rethrow, then the caller would also get an exception.
If neither of these behaviors are what you really want, then you might want to rethink your design.
You can throw the exception to the caller method using the keyword throw:
private void function(){
try{
//something
} catch(Exception e){
//error handling
throw e;
}
}
Then your anotherFunction() catch block will be executed.
You can learn more from here: The Java Tutorials
I am currently working with an AsyncTask and in the doInBackground method runs a piece of code which requires a certain exception to be handled. Since the doInBackground method is overridden, I can't add a throws clause to the method. I have inserted a try-catch method which catches the exception but since my method returns a Summoner object, I had to include a return null; statement and I find my code still executing this statement.
My experience with AsyncTask is pretty limited so if you require more information or I'm overlooking something here, feel free to point it out.
public class GetSummonerData extends AsyncTask<String, Void, Summoner>
{
#Override
protected void onPreExecute()
{
Button button = (Button) findViewById(R.id.btnSearch);
button.setText("Loading...");
}
#Override
protected Summoner doInBackground(String... asyncParams)
{
try
{
String summonerName = asyncParams[1];
RiotApi api = new RiotApi("api-key");
Map<String, Summoner> summoners = null;
//The following line of code will call the API
summoners = api.getSummonersByName(Region.valueOf(asyncParams[0]), summonerName);
//stage 1
return summoners.get(summonerName);
}
catch (RiotApiException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Summoner result)
{
//stage 2
startNewIntent(result);
}
}
public void startNewIntent(Summoner summoner)
{
Intent intent = new Intent(this, ProfileActivity.class);
intent.putExtra("summoner", summoner);
startActivity(intent);
}
At stage 1, the summoners variable holds 1 Summoner object. At stage 2 the returned result in onPostExecute equals null. Why is the return null executed even though there is a return statement within the try block?
The reason return null is executed is because an exception has been thrown during the try-catch block. This causes all remaining execution of the try block to be aborted (including the return statement) and the catch block to be executed instead.
Once the catch block exits the return null after it is then executed since execution continues as normal.
Try this simple code:
public class Class1 {
public Class1() {
super();
}
public String fetchString(int i) {
try {
int j = 1/i;
return "passed";
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Class1 class1 = new Class1();
System.out.println(class1.fetchString(1));
System.out.println(class1.fetchString(0));
}
}
You will realize that when exception is thrown, it is caught, and hence the return statement in "Try" block is never called/executed. (exception is thrown at 1/i when i =0).
Same is happening with your code.
Regarding your other observation, you can't add any new exception to the method you are implementing of interface. Check following example.
public interface myinterface
{
public void foo();
}
Now consider this
public class Ximpl implements myinterface
{
public void foo() throws IOException
{
}
}
Now if client has a code like
myinterface varx = new Ximpl();
//he can do that
varx.foo(); //without putting it in try catch block. (Remember polymorphism)??
If you really want to throw an exception in catch block, create an instance of Runtime Exception, which need not to be declared.
You can use this trick, Wrap the exception in a RuntimeException and rethrow it. Like this
try {
Files.createDirectories(Paths.get(""));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
In this way you don't need to return null.
You can even create your own version of exception that extends RuntimeException. That way you don't need to add it to method signatures and don't force other to catch it. Just like this
public class MyValidationException extends RuntimeException {
}
It is possible to throw exception inside onFailure() method of GWT's RPC call? Because this method will be called later, after server response, I apologize that here may happen something bad..
For example:
public void method() {
try {
rpc.invoke(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void arg0) {}
#Override
public void onFailure(Throwable arg0) {
throw new RuntimeException("Error message"); //HERE
}
});
}
catch (Exception e) {
Window.alert(e.getMessage()); // AND CATCH ABOVE EXCEPTION HERE
}
}
I usually use the following approach on my GWT projects:
1) Create an MyExceptionsHandler:
#Singleton
public class MyExceptionsHandler implements
GWT.UncaughtExceptionHandler,
RpcFailureEvent.Handler, // create corresponding GwtEvent-s
AnyOtherErrorEvent.Handler {
public MyExceptionsHandler(EventBus evenBus) {
eventBus.addHandler(RpcFailureEvent.TYPE, this);
eventBus.addHandler(AnyOtherErrorEvent.TYPE, this);
}
// implement corresponding methods for interfaces
}
2) On entry point:
GWT.setUnchaughtExceptionHandler(myExceptionHandler);
3) In any other place you have an error, which you don't know how to handle:
rpc.invoke(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void arg0) {}
#Override
public void onFailure(Throwable arg0) {
eventBus.fireEvent(new RpcFailureEvent(<any context info you think helpful>));
}
});
Yes, it's possible.
#Override
public void onFailure(Throwable arg0) {
throw new RuntimeException(arg0);
}
This code is absolutely valid. But to what purpose are you creating and throwing a new instance of RuntimeException?
At that if you write
new RuntimeException("Error message")
you lose all information about occurred exception.
And don't forget that in GWT all calls from client to a remote service are handled asynchronously. And the onFailure() callback method are called immediatly when an asynchronous call fails to complete normally.
No, you can't. Well, you can throw the exception, but it won't be handled by the catch block you defined, since the AsyncCallback is an anonymous class that does not run in the same scope and is not called at the same time as your catch block.
You can however try to use GWT.setUncaughtExceptionHandler(), see the details at http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/core/client/GWT.html.
What I want is a standard JDK class that look like this:
interface ExplodingRunnable {
void run() throws Exception;
}
Callable is no good, because its call() method is required to return a value, but I need a void.
Runnable is no good, because its run() method doesn't declare throws Exception.
I sort of need a combination of the two. Any ideas?
EDIT: I should have mentioned that I tried Callable<Void> but it requires you to define a method:
public Void call() {
// run your code;
return null; // ugly!
}
I'm looking for something a bit nicer.
Why do I want this?
I'm implementing a standard why of catching "will never happen" Exceptions (they will never happen, but various APIs define their methods throwing Exceptions) and throwing any Exceptions that might occur by wrapping them in an (unchecked) RuntimeException, so the caller can simply pass a "ExplodingRunnable" in and not have to code loads of perfunctory try/catch blocks that will never be exercised.
FINAL EDIT It looks like what I was looking for doesn't exist. The accepted answer is the closest to "correct", but it looks like there is no solution to answer the question as asked.
Could you just use Callable<Void>?
An interface with only one method, which returns void and throws Exception.
Among all java and javax classes, only one fits that description:
package java.lang;
public interface AutoCloseable
{
void close() throws Exception;
}
Well... the word "close" has many meanings...
You want to surround a bunch of statements with some extra handling, there is no sin to define your own interface here. You may find that your API requires users to learn 4 new phrases
Util.muckException( new ExplodingRunnable() { public void run() throws Exception
^1 ^2 ^3 ^4
You can actually cut down two, and user code would look like this
new MuckException(){ public void run() throws Exception
{
statement_1;
...
statement_n;
}};
public abstract class MuckException
{
public abstract run() throws Exception;
public MuckException()
{
try{ run(); }
catch(Exception e){ throw new Error(e); }
}
}
Just use Callable, ignore the return value and document things as ignoring the returned value and recommend returning null. Just because you can return something does not mean you have to.
I would just use Callable<Void> and learn to love it. ;)
You can have the checked exception not declared with the following.
Runnable runs = new Runnable() {
public void run() {
try {
// do something
} catch(Exception e) {
// rethrows anything without the compiler knowing.
// the method is deprecated but can be used on the current thread.
Thread.currentThread().stop(e);
}
}
});
Future future = executorService.submit(run);
try {
future.get();
} catch (ExecutionException ee) {
Throwable e = ee.getCause(); // can be the checked exception above.
}
and not have to code loads of perfunctory try/catch blocks that will never be exercised.
I had the same issue and fixed it a little differently
// Exceptions class
public RuntimeException wrap(Exception e) {
return e instanceof RuntimeException ? ((RuntimeException)e) : new RuntimeException(e);
}
// user code
try {
foo.bar();
} catch (Exception e) {
throw Exceptions.wrap(e);
}