RahulDeep Attri
RahulDeep Attri

Reputation: 418

Root cause & Propagation of Exception in SAP Cloud SDK

Suppose I have a supplier and some exception occurs while invoking get method of that supplier.

 Supplier<> supplier = () -> getSomething();
 ResilienceDecorator.executeSupplier( //Edit 1 - Could be ResilienceDecorator.executeCallable
                supplier,
                resilienceConfiguration,
                throwable -> {
                   log.error("Exception occured", throwable);
                   return null;
                });

Edit 1 - Also same for ResilienceDecorator.executeCallable. I need a consistent API to know what went wrong during execution i.e. What was the checked exception (Edit 1 - or Unchecked exception) causing the failure so I can handle business logic. The throwable is not root cause of exception or whatever the supplier had thrown.

If we do not provide a throwable function like above then every exception is wrapped in a ResilienceRuntimeException and we need a chain of getCause().getCause() to know what went wrong. This is internal to sdk which might change. Again a consistent API is needed.

Is there any alternative & consistent way to know what exception the supplier is throwing? I might need to bubble it up or write a user friendly message based on the exception occured, depending upon buisness logic.

Edit 1- An example of my current situation.

Supplier<MatDocItm> supplier = () -> {
        ErpHttpDestination erpHttpDestination = DestinationAccessor.getDestination(S4_SYSTEM).asHttp().decorate(DefaultErpHttpDestination::new);
        return new CustomCommand(erpHttpDestination, params).execute();     
    }

    try {
        MatDocItm = ResilienceDecorator.executeSupplier(
                supplier,
                configuration
        );
    } catch (ResilienceRuntimeException e) {
        throw new ReadException("Failed to read from SAP S/4HANA", e);
    }

The supplier can throw runtime exceptions and based on these exceptions I want to give a User friendly error message with proper description.

The supplier can throw a DestinationAccessException (which is runtime exception) if a destination cannot be accessed, is not configured correctly, or does not fulfill certain prerequisites. Not only the exceptions occured in supplier, I have TimeLimiterConfiguration & if timeout occurs then a TimeoutException can be thrown.

For above MatDocItm example the ResilienceRuntimeException.getCause() will give com.sap.cloud.sdk.cloudplatform.thread.exception.ThreadContextExecutionException. ResilienceRuntimeException.getCause().getCause() will reveal exception that actually caused the error i.e DestinationAccessException. Now ThreadContextExecutionException is internal to sdk and can change if sdk implementation changes. Will this implementation detail remain frozen and never change in future or is there any alternative way to get the root cause?

Upvotes: 1

Views: 224

Answers (1)

Alexander D&#252;mont
Alexander D&#252;mont

Reputation: 938

I would recommend ExceptionUtils.throwableOfType for matching exception type and sub classes. Alternatively ExceptionUtils.throwableOfThrowable for matching exact type only. The utility class already provided by dependency org.apache.commons:commons-lang3:3.10

Example:

@Nullable
YourException cause = ExceptionUtils.throwableOfType(throwable, YourException.class);

You can handle the nullable result in an If statement.

As a fan of fluent APIs, I would rather go with java.util.Optional or io.vavr.control.Option.

Upvotes: 1

Related Questions