Skip to content

@Retryable could allow exception translation #35476

@ah1508

Description

@ah1508

When a method executes code that may throw an exception, it is usual to hide the exception if is not expected:

public void foo() {
  try {
     // method calls
  } catch(BusinessException /*parent class of business exception*/e) {
    throw e; // message should be shown (or translated and shown) to the user
  } catch(Throwable t /*not a business exception, which means it is not expected */) {
    // log information about t, 
    // home made retry (for tx serialization failure for instance) or:
    throw new RuntimException("an error occured");   // because e may show sensitive details that should not exit the method
  }
}

However if the exception is not a BusinessException its type would not visible to the retry interceptor, which makes fine grained interception configuration impossible. If we want to use @Retryable the best we can do here is excludes = BusinessException.class but then NPE will trigger retry.

How about a rethrow property ?:

@Retryable(includes = CannotAcquireLockException.class, rethrow = RuntimeException.class)
public void foo() {
  try {
     // method calls
  } catch(Throwable t) {
    // apply log policy depending on the exception (business exception thrown by our code vs unexpected)
    // throw t;
  }
}

retry will apply for CannotAcquireLockException, and if the max attemps is reached the exception rethrown by the interceptor to the caller would be an instance of RuntimeException.

Or:
@Retryable(includes = CannotAcquireLockException.class, rethrow = @Rethrow(type = RuntimeException.class, message = "..."))

An other option, an ExceptionTranslator (Function<Throwable, Throwable>) could be used:

@Retryable(includes = CannotAcquireLockException.class, translator = MyExceptionTranslator.class)
public void foo() {
  try {
     // method cals
  } catch(Throwable t) {
    // apply log policy depending on the exception (business exception thrown by our code vs unexpected)
    // throw t;
  }
}

The retry interceptor would call the translator and eventually throw what the translation function returns.

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: declinedA suggestion or change that we don't feel we should currently apply

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions