Bug 457687 - Dependency Injection should not catch Errors According to the JavaDoc, an Error is "a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch". Re-throw Errors that are raised by methods invoked by DI. The underlying issue is that the Reflection API wraps Errors in an ITE. It has been admitted in a JDK bug [1] that this is a bad practice but cannot be changed for compatibility reasons. The recommended workaround is to re-throw Errors wrapped in ITEs. [1] http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4386935 Change-Id: I109b64cc98b63e9852043fd232eb0664f3156ea4 Signed-off-by: Ralf Sternberg <rsternberg@eclipsesource.com>
diff --git a/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/ConstructorRequestor.java b/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/ConstructorRequestor.java index 791a033..f4d9b9d 100644 --- a/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/ConstructorRequestor.java +++ b/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/ConstructorRequestor.java
@@ -47,6 +47,11 @@ throw new InjectionException(e); } catch (InvocationTargetException e) { Throwable originalException = e.getCause(); + // Errors such as ThreadDeath or OutOfMemoryError should not be trapped + // http://bugs.eclipse.org/bugs/show_bug.cgi?id=457687 + if (originalException instanceof Error) { + throw (Error) originalException; + } throw new InjectionException((originalException != null) ? originalException : e); } finally { if (!wasAccessible)
diff --git a/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/MethodRequestor.java b/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/MethodRequestor.java index 670ae42..6c29d21 100644 --- a/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/MethodRequestor.java +++ b/bundles/org.eclipse.e4.core.di/src/org/eclipse/e4/core/internal/di/MethodRequestor.java
@@ -59,6 +59,11 @@ throw new InjectionException(e); } catch (InvocationTargetException e) { Throwable originalException = e.getCause(); + // Errors such as ThreadDeath or OutOfMemoryError should not be trapped + // http://bugs.eclipse.org/bugs/show_bug.cgi?id=457687 + if (originalException instanceof Error) { + throw (Error) originalException; + } throw new InjectionException((originalException != null) ? originalException : e); } finally { if (!wasAccessible)
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/manual/InjectionErrorReportingTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/manual/InjectionErrorReportingTest.java index f073132..1baf1f5 100644 --- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/manual/InjectionErrorReportingTest.java +++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/manual/InjectionErrorReportingTest.java
@@ -15,14 +15,13 @@ import javax.inject.Inject; import javax.inject.Named; -import junit.framework.TestCase; - import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.EclipseContextFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.di.InjectionException; import org.eclipse.e4.core.di.annotations.Creatable; -import org.junit.Ignore; + +import junit.framework.TestCase; /** * Manual test to observe error reporting. The JUnits in this @@ -243,15 +242,17 @@ } /** - * Manual test to check error message for recursive object creation + * Manual test to check error message for recursive object creation Although + * bug 377343 disabled throwing InjectionExceptions on recursive creation, + * the fix for bug 457687 now exposes java.lang.Errors (such as + * StackOverflowError) rather than wrapping them in an InjectionException. */ - @Ignore("Exception on recursive creations removed with bug 377343") public void testRecursionError() { IEclipseContext context = EclipseContextFactory.create(); boolean exception = false; try { ContextInjectionFactory.make(InjectedRecursive.class, context); - } catch (InjectionException e) { + } catch (StackOverflowError e) { basicLog(e); exception = true; } @@ -261,14 +262,14 @@ exception = false; try { ContextInjectionFactory.make(InjectedRecursive.class, context); - } catch (InjectionException e) { + } catch (StackOverflowError e) { basicLog(e); exception = true; } assertFalse(exception); } - private void basicLog(InjectionException e) { + private void basicLog(Throwable e) { e.printStackTrace(System.out); } }