HashedErrorHandler implements CycleErrorHandler<T, R> { @Override public R handleError(long cycle, T throwable, String errMsg) { Class<?> errorClass = throwable.getClass(); CycleErrorHandler<T, R> errorHandler = null; while (errorHandler == null) { errorHandler = handlers.get(errorClass); errorClass = errorClass.getSuperclass(); if (!upperBound.isAssignableFrom(errorClass)) { break; } } errorHandler = (errorHandler == null) ? defaultHandler : errorHandler; return errorHandler.handleError(cycle, throwable, errMsg); }  @java.lang.SafeVarargs final void setGroup(String groupName, Class<? extends T>... exceptions); Set<Class<? extends T>> getGroup(String groupName); @java.lang.SafeVarargs final synchronized void setHandlerForClasses(
            CycleErrorHandler<T, R> errorHandler,
            Class<? extends T>... errorClasses
    ); final synchronized void setHandlerForGroup(String groupName, CycleErrorHandler<T, R> errorHandler); final synchronized void setHandlerForPattern(
            String pattern,
            CycleErrorHandler<T, R> errorHandler
    ); final synchronized void resetAllClassHandlers(); final synchronized Map<Class<? extends T>, CycleErrorHandler<T, R>> getHandlers(); @java.lang.SafeVarargs final synchronized void addValidClasses(Class<? extends T>... validClasses); Set<Class<? extends T>> getValidClasses(); HashedErrorHandler<T, R> setDefaultHandler(CycleErrorHandler<T, R> errorHandler); HashedErrorHandler<T, R> setUpperBound(Class<? extends T> upperBound); @Override R handleError(long cycle, T throwable, String errMsg); List<String> getGroupNames();  }
@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = ".*actually.*") public void testDefaultHandlerThrowsException() { handler.handleError(1L, new InvalidParameterException("this is an invalid exception, actually")); }