Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;

import com.sun.codemodel.JCatchBlock;
import com.sun.codemodel.JStatement;
import com.sun.codemodel.JTryBlock;
import com.sun.codemodel.JVar;
import org.androidannotations.annotations.Background;
import org.androidannotations.api.BackgroundExecutor;
import org.androidannotations.api.BackgroundExecutor.Task;
Expand Down Expand Up @@ -60,7 +64,17 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) t
JMethod executeMethod = anonymousTaskClass.method(JMod.PUBLIC, codeModel.VOID, "execute");
executeMethod.annotate(Override.class);

executeMethod.body().add( previousMethodBody );
// Catch exception in user code
JTryBlock tryBlock = executeMethod.body()._try();
tryBlock.body().add(previousMethodBody);
JCatchBlock catchBlock = tryBlock._catch(holder.classes().THROWABLE);
JVar caughtException = catchBlock.param("e");
JStatement uncaughtExceptionCall = holder.classes().THREAD
.staticInvoke("getDefaultUncaughtExceptionHandler")
.invoke("uncaughtException")
.arg(holder.classes().THREAD.staticInvoke("currentThread"))
.arg(caughtException);
catchBlock.body().add(uncaughtExceptionCall);

Background annotation = element.getAnnotation(Background.class);
String id = annotation.id();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class Classes {
*/
public final JClass RUNTIME_EXCEPTION = refClass(RuntimeException.class);
public final JClass EXCEPTION = refClass(Exception.class);
public final JClass THROWABLE = refClass(Throwable.class);
public final JClass CHAR_SEQUENCE = refClass(CharSequence.class);
public final JClass CLASS_CAST_EXCEPTION = refClass(ClassCastException.class);
public final JClass SERIALIZABLE = refClass(Serializable.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class ThreadActivityTest {

private ThreadActivity_ activity;

private volatile boolean propagatedExceptionToGlobalExceptionHandler;

@Before
public void setup() {
activity = new ThreadActivity_();
Expand Down Expand Up @@ -320,4 +322,44 @@ public void run() {
Assert.assertTrue("Handler field not associated to the main thread", handler.getLooper() == Looper.getMainLooper());
}

@Test
public void propagateExceptionToGlobalExceptionHandler() {

// Prepare lock on which we'll wait for the
// background exception handler to catch the exception
final Object LOCK = new Object();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
synchronized (LOCK) {
propagatedExceptionToGlobalExceptionHandler = true;
LOCK.notify();
}
}
});

propagatedExceptionToGlobalExceptionHandler = false;
activity.backgroundThrowException();

// If the default uncaught exception handler is not called
// after 2 secs this method returns and the following assert will fail.
waitOn(LOCK, 2000);
Assert.assertTrue("Exception should have been caught in the DefaultUncaughtExceptionHandler during @Background call.",
propagatedExceptionToGlobalExceptionHandler);
}

/**
* Call wait() on the given object with the specified timeout.
* Avoid boilerplate code like synchronized or try..catch.
*/
private void waitOn(Object lock, long timeout) {
synchronized (lock) {
try {
lock.wait(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}