Rethrow Error from @PostConstruct method instead of wrapping it in RuntimeException#3039
Conversation
Marcono1234
left a comment
There was a problem hiding this comment.
Thanks! I have added two suggestions.
The direct project members might have additional comments though.
| new GsonBuilder().registerTypeAdapterFactory(new PostConstructAdapterFactory()).create(); | ||
|
|
||
| Throwable thrown = | ||
| org.junit.Assert.assertThrows( |
There was a problem hiding this comment.
Test compilation fails because this should use an import for org.junit.Assert instead of the qualified name, respectively a static import.
There was a problem hiding this comment.
Good catch — switched to the static import so assertThrows is used directly. The qualified org.junit.Assert.assertThrows(...) left the import static unused, which the build rejected. Thanks!
| assertThat(thrown).isInstanceOf(Error.class); | ||
| assertThat(thrown).isNotInstanceOf(RuntimeException.class); |
There was a problem hiding this comment.
Could make this more specific to check for the exact custom error:
| assertThat(thrown).isInstanceOf(Error.class); | |
| assertThat(thrown).isNotInstanceOf(RuntimeException.class); | |
| assertThat(thrown).isInstanceOf(AssertionError.class); | |
| assertThat(thrown).hasMessageThat().isEqualTo("error from post-construct"); |
(Or maybe even change assertThrows(Throwable.class, ...) to AssertionError error = assertThrows(AssertionError.class, ...)?)
There was a problem hiding this comment.
Done — switched to assertThrows(AssertionError.class, ...), so it now also asserts the propagated throwable is an AssertionError rather than a wrapping RuntimeException.
One wrinkle on the exact message: Gson.fromJson re-tags AssertionErrors with an "AssertionError (GSON <version>): " prefix (keeping the original as the cause), so isEqualTo("error from post-construct") does not hold on the top-level message. I used hasMessageThat().contains("error from post-construct") to keep the specificity while staying robust to the version tag.
There was a problem hiding this comment.
One wrinkle on the exact message:
Gson.fromJsonre-tagsAssertionErrors with an"AssertionError (GSON <version>): "prefix
Ah, maybe it would be better to use a different Error subclass then (or directly Error), possibly even a custom subclass of Error (to no cause confusion when using any of the existing Error subclasses, e.g. throwing an error such as StackOverflowError might be confusing).
There was a problem hiding this comment.
Good call — switched to a dedicated CustomTestError extends Error thrown from @PostConstruct, so there is no AssertionError re-tagging and no overlap with a meaningful JVM error such as StackOverflowError. The message assertion is now exact (isEqualTo("error from post-construct")).
3bf9f7a to
3d53dc5
Compare
…ntimeException PostConstructAdapterFactory rethrows a RuntimeException cause as-is but wraps everything else. An Error thrown by the @PostConstruct method (AssertionError, OutOfMemoryError, ...) is unchecked like RuntimeException and should propagate as-is, not be smothered in a RuntimeException. Rethrow Error the same way. Adds a regression test.
3d53dc5 to
7648fad
Compare
PostConstructAdapterFactoryrethrows aRuntimeExceptioncause as-is, but wraps everything else (throw new RuntimeException(e.getCause())). AnErrorthrown by the@PostConstructmethod —AssertionError,OutOfMemoryError,NoClassDefFoundError, … — is unchecked likeRuntimeExceptionand should propagate unchanged, not be wrapped in aRuntimeException(where acatch (RuntimeException)could swallow what is meant to be unrecoverable).This adds the symmetric
else if (e.getCause() instanceof Error) throw (Error) e.getCause();, matching how the same block already treatsRuntimeException. Thenew RuntimeException(...)fallback stays for genuinely checked causes. Includes a regression test.