class RetryableOnException implements Retryable<T, E> {

    @Override
    public T exec(DelegateRetry<T, E> delegate) throws E {
        while (counter.getAndIncrement() < param.getNbRetry()) {
            try {
                return delegate.call();
            } catch (Exception e) {
                boolean attemptExceedNbRetry = counter.get() >= param.getNbRetry();
                boolean shouldStopRetry = retryOn.negate().test(e);
                if (attemptExceedNbRetry || shouldStopRetry) {
                    throw e;
                }
                sleep(counter.get(), delegate.toString(), param, randomSleep, onException, e);
            }
        }

        throw new IllegalStateException("Unreachable statement.");
    }

    public  RetryableOnException(RetryableParameters param, Predicate<Exception> retryOn, Consumer<Exception> onException);
    public  RetryableOnException(RetryableParameters param, Predicate<Exception> retryOn);
    public  RetryableOnException(RetryableParameters param);

}