Details
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
index 34e2fd8..d5855d0 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
@@ -56,6 +56,8 @@ import org.killbill.commons.locker.LockFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.MoreObjects;
+
public abstract class OperationControlCallback extends OperationCallbackBase<Payment, PaymentApiException> implements OperationCallback {
protected final PaymentProcessor paymentProcessor;
@@ -151,30 +153,26 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
}
@Override
- protected OperationException rewrapExecutionException(final PaymentStateContext paymentStateContext, final ExecutionException e) {
- if (e.getCause() instanceof OperationException) {
- return (OperationException) e.getCause();
- } else if (e.getCause() instanceof LockFailedException) {
+ protected OperationException unwrapExceptionFromDispatchedTask(final PaymentStateContext paymentStateContext, final Exception e) {
+
+ // If this is an ExecutionException we attempt to extract the cause first
+ final Throwable originalExceptionOrCause = e instanceof ExecutionException ? MoreObjects.firstNonNull(e.getCause(), e) : e;
+
+ if (originalExceptionOrCause instanceof OperationException) {
+ return (OperationException) originalExceptionOrCause;
+ } else if (originalExceptionOrCause instanceof LockFailedException) {
final String format = String.format("Failed to lock account %s", paymentStateContext.getAccount().getExternalKey());
logger.error(String.format(format));
- return new OperationException(e, getOperationResultOnException(paymentStateContext));
+ } else if (originalExceptionOrCause instanceof TimeoutException) {
+ logger.warn("RetryOperationCallback call TIMEOUT for account {}", paymentStateContext.getAccount().getExternalKey());
+ } else if (originalExceptionOrCause instanceof InterruptedException) {
+ logger.error("RetryOperationCallback call was interrupted for account {}", paymentStateContext.getAccount().getExternalKey());
} else /* most probably RuntimeException */ {
logger.warn("RetryOperationCallback failed for account {}", paymentStateContext.getAccount().getExternalKey(), e);
- return new OperationException(e, getOperationResultOnException(paymentStateContext));
}
- }
-
- @Override
- protected OperationException wrapTimeoutException(final PaymentStateContext paymentStateContext, final TimeoutException e) {
- logger.warn("RetryOperationCallback call TIMEOUT for account {}", paymentStateContext.getAccount().getExternalKey());
return new OperationException(e, getOperationResultOnException(paymentStateContext));
}
- @Override
- protected OperationException wrapInterruptedException(final PaymentStateContext paymentStateContext, final InterruptedException e) {
- logger.error("RetryOperationCallback call was interrupted for account {}", paymentStateContext.getAccount().getExternalKey());
- return new OperationException(e, getOperationResultOnException(paymentStateContext));
- }
protected void executePluginOnSuccessCalls(final List<String> paymentControlPluginNames, final PaymentRoutingContext paymentControlContext) {
for (final String pluginName : paymentControlPluginNames) {
@@ -253,10 +251,8 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
final DateTime retryDate = executePluginOnFailureCalls(paymentStateControlContext.getPaymentControlPluginNames(), paymentControlContext);
if (retryDate != null) {
((PaymentStateControlContext) paymentStateContext).setRetryDate(retryDate);
- return OperationResult.FAILURE;
- } else {
- return OperationResult.EXCEPTION;
}
+ return getOperationResultOnException(paymentStateContext);
}
private DateTime executePluginOnFailureCalls(final List<String> paymentControlPluginNames, final PaymentRoutingContext paymentControlContext) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
index 6a81f1d..8ab58ff 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
@@ -66,12 +66,12 @@ public abstract class OperationCallbackBase<CallbackOperationResult, CallbackOpe
logger.debug("Successful plugin call for account {} with result {}", account.getExternalKey(), operationResult);
return operationResult;
} catch (final ExecutionException e) {
- throw rewrapExecutionException(paymentStateContext, e);
+ throw unwrapExceptionFromDispatchedTask(paymentStateContext, e);
} catch (final TimeoutException e) {
- throw wrapTimeoutException(paymentStateContext, e);
+ throw unwrapExceptionFromDispatchedTask(paymentStateContext, e);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
- throw wrapInterruptedException(paymentStateContext, e);
+ throw unwrapExceptionFromDispatchedTask(paymentStateContext, e);
}
}
@@ -83,12 +83,5 @@ public abstract class OperationCallbackBase<CallbackOperationResult, CallbackOpe
//
protected abstract CallbackOperationResult doCallSpecificOperationCallback() throws CallbackOperationException;
- //
- // The methods below allow to convert the exceptions thrown back by the Executor into an appropriate OperationException
- //
- protected abstract OperationException rewrapExecutionException(final PaymentStateContext paymentStateContext, final ExecutionException e);
-
- protected abstract OperationException wrapTimeoutException(final PaymentStateContext paymentStateContext, final TimeoutException e);
-
- protected abstract OperationException wrapInterruptedException(final PaymentStateContext paymentStateContext, final InterruptedException e);
+ protected abstract OperationException unwrapExceptionFromDispatchedTask(final PaymentStateContext paymentStateContext, final Exception e);
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
index 6d57033..ba6e48d 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
@@ -85,24 +85,26 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
}
@Override
- protected OperationException rewrapExecutionException(final PaymentStateContext paymentStateContext, final ExecutionException e) {
+ protected OperationException unwrapExceptionFromDispatchedTask(final PaymentStateContext paymentStateContext, final Exception e) {
+
+ // If this is an ExecutionException we attempt to extract the cause first
+ final Throwable originalExceptionOrCause = e instanceof ExecutionException ? MoreObjects.firstNonNull(e.getCause(), e) : e;
+
//
// Any case of exception (checked or runtime) should lead to a TransactionStatus.UNKNOWN (and a XXX_ERRORED payment state).
// In order to reach that state we create PaymentTransactionInfoPlugin with an PaymentPluginStatus.UNDEFINED status (and an OperationResult.EXCEPTION).
//
- final Throwable originalExceptionOrCause = MoreObjects.firstNonNull(e.getCause(), e);
if (originalExceptionOrCause instanceof LockFailedException) {
logger.warn("Failed to lock account {}", paymentStateContext.getAccount().getExternalKey());
+ } else if (originalExceptionOrCause instanceof TimeoutException) {
+ logger.error("Plugin call TIMEOUT for account {}", paymentStateContext.getAccount().getExternalKey());
+ } else if (originalExceptionOrCause instanceof InterruptedException) {
+ logger.error("Plugin call was interrupted for account {}", paymentStateContext.getAccount().getExternalKey());
} else {
logger.warn("Payment plugin call threw an exception for account {}", paymentStateContext.getAccount().getExternalKey(), originalExceptionOrCause);
}
return convertToUnknownTransactionStatusAndErroredPaymentState(originalExceptionOrCause);
- }
- @Override
- protected OperationException wrapTimeoutException(final PaymentStateContext paymentStateContext, final TimeoutException e) {
- logger.error("Plugin call TIMEOUT for account {}", paymentStateContext.getAccount().getExternalKey());
- return convertToUnknownTransactionStatusAndErroredPaymentState(e);
}
//
@@ -122,16 +124,10 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
paymentStateContext.getCallContext().getCreatedDate(),
PaymentPluginStatus.UNDEFINED,
null);
-
paymentStateContext.setPaymentTransactionInfoPlugin(paymentInfoPlugin);
return new OperationException(e, OperationResult.EXCEPTION);
}
- @Override
- protected OperationException wrapInterruptedException(final PaymentStateContext paymentStateContext, final InterruptedException e) {
- logger.error("Plugin call was interrupted for account {}", paymentStateContext.getAccount().getExternalKey());
- return new OperationException(e, OperationResult.EXCEPTION);
- }
@Override
protected abstract PaymentTransactionInfoPlugin doCallSpecificOperationCallback() throws PaymentPluginApiException;