As stated in the Javadoc for RetryListener.onRetryPolicyExhaustion(), the supplied Throwable should be:
the last exception thrown by the
Retryableoperation
However, RetryTemplate.execute() currently supplies the final, composite RetryException to RetryListener.onRetryPolicyExhaustion(), whose cause happens to be the last exception thrown by the Retryable operation.