From d27f425eb2416ebe28ddd6bb762c13e7e5ed5462 Mon Sep 17 00:00:00 2001 From: pavlospt Date: Tue, 26 Sep 2017 17:53:20 +0300 Subject: [PATCH] WIP --- .../workable/errorhandler/ErrorHandler.java | 41 ++++++++++++++----- .../errorhandler/ErrorHandlerTest.java | 12 ++++++ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/errorhandler/src/main/java/com/workable/errorhandler/ErrorHandler.java b/errorhandler/src/main/java/com/workable/errorhandler/ErrorHandler.java index 5d75b62..9c0adcc 100644 --- a/errorhandler/src/main/java/com/workable/errorhandler/ErrorHandler.java +++ b/errorhandler/src/main/java/com/workable/errorhandler/ErrorHandler.java @@ -62,7 +62,7 @@ private ErrorHandler() { this.otherwiseActions = new ArrayList<>(); this.alwaysActions = new ArrayList<>(); this.errorCodeMap = new HashMap<>(); - this.localContext = new ThreadLocal(){ + this.localContext = new ThreadLocal() { @Override protected Context initialValue() { return new Context(); @@ -92,6 +92,24 @@ public static ErrorHandler createIsolated() { return new ErrorHandler(); } + /** + * Create a new @{link ErrorHandler}, isolated from the default one. + *

+ * In other words, designed to handle all errors by itself without delegating + * to the default error handler. + * + * @return returns a new {@code ErrorHandler} instance + */ + public static ErrorHandler withBindingsFrom(ErrorHandler errorHandler) { + if (errorHandler == null) { + throw new IllegalStateException("errorHandler is not initialized"); + } + + ErrorHandler eh = new ErrorHandler(); + eh.errorCodeMap = errorHandler.errorCodeMap; + return eh; + } + /** * Create a new @{link ErrorHandler}, that delegates to the default one. *

@@ -157,7 +175,8 @@ public ErrorHandler on(Class exceptionClass, Action action) * See {@link #bindClass(Class, MatcherFactory)} and {@link #bind(Object, MatcherFactory)} * on how to associate arbitrary error codes with actual Throwables via {@link Matcher}. *

- * @param the error code type + * + * @param the error code type * @param errorCode the error code * @param action the associated action * @return the current {@code ErrorHandler} instance - to use in command chains @@ -203,6 +222,7 @@ public ErrorHandler always(Action action) { /** * Skip all following actions registered via an {@code on} method + * * @return the current {@code ErrorHandler} instance - to use in command chains */ public ErrorHandler skipFollowing() { @@ -214,6 +234,7 @@ public ErrorHandler skipFollowing() { /** * Skip all actions registered via {@link #always(Action)} + * * @return the current {@code ErrorHandler} instance - to use in command chains */ public ErrorHandler skipAlways() { @@ -225,6 +246,7 @@ public ErrorHandler skipAlways() { /** * Skip the default matching actions if any + * * @return the current {@code ErrorHandler} instance - to use in command chains */ public ErrorHandler skipDefaults() { @@ -294,13 +316,13 @@ public void handle(Throwable error) { /** * Bind an {@code errorCode} to a {@code Matcher}, using a {@code MatcherFactory}. - * + *

*

* For example, when we need to catch a network timeout it's better to just write "timeout" * instead of a train-wreck expression. So we need to bind this "timeout" error code to an actual * condition that will check the actual error when it occurs to see if its a network timeout or not. *

- * + *

*

      * {@code
      *   ErrorHandler
@@ -319,9 +341,8 @@ public void handle(Throwable error) {
      * }
      * 
* - * - * @param the error code type - * @param errorCode the errorCode value, can use a primitive for clarity and let it be autoboxed + * @param the error code type + * @param errorCode the errorCode value, can use a primitive for clarity and let it be autoboxed * @param matcherFactory a factory that given an error code, provides a matcher to match the error against it * @return the current {@code ErrorHandler} instance - to use in command chains */ @@ -332,12 +353,12 @@ public ErrorHandler bind(T errorCode, MatcherFactory matcherFacto /** * Bind an {@code errorCode} Class to a {@code Matcher}, using a {@code MatcherFactory}. - * + *

*

* For example, when we prefer using plain integers to refer to HTTP errors instead of * checking the HTTPException status code every time. *

- * + *

*

      * {@code
      *   ErrorHandler
@@ -359,7 +380,7 @@ public  ErrorHandler bind(T errorCode, MatcherFactory matcherFacto
      * }
      * 
* - * @param the error code type + * @param the error code type * @param errorCodeClass the errorCode class * @param matcherFactory a factory that given an error code, provides a matcher to match the error against it * @return the current {@code ErrorHandler} instance - to use in command chains diff --git a/errorhandler/src/test/java/com/workable/errorhandler/ErrorHandlerTest.java b/errorhandler/src/test/java/com/workable/errorhandler/ErrorHandlerTest.java index 049666d..8efe2a1 100644 --- a/errorhandler/src/test/java/com/workable/errorhandler/ErrorHandlerTest.java +++ b/errorhandler/src/test/java/com/workable/errorhandler/ErrorHandlerTest.java @@ -282,6 +282,18 @@ public void testErrorHandlerBlockExecutorIgnoresNotMatchedException() { Mockito.verifyNoMoreInteractions(actionDelegateMock); } + @Test + public void testErrorHandlerBlockExecutorIgnoresNotMatchedExceptionWithParentBindings() { + ErrorHandler + .withBindingsFrom(ErrorHandler.defaultErrorHandler()) + .on("closed:bar", (throwable, errorHandler) -> actionDelegateMock.action3()) + .handle(new BarException("What a shame", false)); + + verify(actionDelegateMock, times(1)).action3(); + verify(actionDelegateMock, times(0)).defaultAction3(); + Mockito.verifyNoMoreInteractions(actionDelegateMock); + } + @Test public void testErrorHandlerIfSkipDefaults() { InOrder testVerifier = inOrder(actionDelegateMock);