@Override public T recover(Object[] args, Throwable cause) { Method method = findClosestMatch(args, cause.getClass()); if (method == null) { throw new ExhaustedRetryException("Cannot locate recovery method", cause); } SimpleMetadata meta = methods.get(method); Object[] argsToUse = meta.getArgs(cause, args); boolean methodAccessible = method.isAccessible(); try { ReflectionUtils.makeAccessible(method); @SuppressWarnings("unchecked") T result = (T) ReflectionUtils.invokeMethod(method, target, argsToUse); return result; } finally { if (methodAccessible != method.isAccessible()) { method.setAccessible(methodAccessible); } } }
protected <E extends Throwable> void rethrow(RetryContext context, String message) throws E { if (this.throwLastExceptionOnExhausted) { @SuppressWarnings("unchecked") E rethrow = (E) context.getLastThrowable(); throw rethrow; } else { throw new ExhaustedRetryException(message, context.getLastThrowable()); } }
/** * Convenience method to get an exception classifier based on the provided transaction attributes. * * @return an exception classifier: maps to true if an exception should cause rollback */ protected Classifier<Throwable, Boolean> getRollbackClassifier() { Classifier<Throwable, Boolean> classifier = new BinaryExceptionClassifier(noRollbackExceptionClasses, false); // Try to avoid pathological cases where we cannot force a rollback // (should be pretty uncommon): if (!classifier.classify(new ForceRollbackForWriteSkipException("test", new RuntimeException())) || !classifier.classify(new ExhaustedRetryException("test"))) { final Classifier<Throwable, Boolean> binary = classifier; Collection<Class<? extends Throwable>> types = new HashSet<>(); types.add(ForceRollbackForWriteSkipException.class); types.add(ExhaustedRetryException.class); final Classifier<Throwable, Boolean> panic = new BinaryExceptionClassifier(types, true); classifier = (Classifier<Throwable, Boolean>) classifiable -> { // Rollback if either the user's list or our own applies return panic.classify(classifiable) || binary.classify(classifiable); }; } return classifier; }
@Override public Object recover(RetryContext context) throws Exception { /* * If the last exception was not skippable we don't need to * do any scanning. We can just bomb out with a retry * exhausted. */ if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) { throw new ExhaustedRetryException( "Retry exhausted after last attempt in recovery path, but exception is not skippable.", context.getLastThrowable()); } inputs.setBusy(true); data.scanning(true); scan(contribution, inputs, outputs, chunkMonitor, true); return null; }
@Override public T recover(Object[] args, Throwable cause) { Method method = findClosestMatch(args, cause.getClass()); if (method == null) { throw new ExhaustedRetryException("Cannot locate recovery method", cause); } SimpleMetadata meta = methods.get(method); Object[] argsToUse = meta.getArgs(cause, args); boolean methodAccessible = method.isAccessible(); try { ReflectionUtils.makeAccessible(method); @SuppressWarnings("unchecked") T result = (T) ReflectionUtils.invokeMethod(method, target, argsToUse); return result; } finally { if (methodAccessible != method.isAccessible()) { method.setAccessible(methodAccessible); } } }
protected <E extends Throwable> void rethrow(RetryContext context, String message) throws E { if (this.throwLastExceptionOnExhausted) { @SuppressWarnings("unchecked") E rethrow = (E) context.getLastThrowable(); throw rethrow; } else { throw new ExhaustedRetryException(message, context.getLastThrowable()); } }
/** * Convenience method to get an exception classifier based on the provided transaction attributes. * * @return an exception classifier: maps to true if an exception should cause rollback */ protected Classifier<Throwable, Boolean> getRollbackClassifier() { Classifier<Throwable, Boolean> classifier = new BinaryExceptionClassifier(noRollbackExceptionClasses, false); // Try to avoid pathological cases where we cannot force a rollback // (should be pretty uncommon): if (!classifier.classify(new ForceRollbackForWriteSkipException("test", new RuntimeException())) || !classifier.classify(new ExhaustedRetryException("test"))) { final Classifier<Throwable, Boolean> binary = classifier; Collection<Class<? extends Throwable>> types = new HashSet<Class<? extends Throwable>>(); types.add(ForceRollbackForWriteSkipException.class); types.add(ExhaustedRetryException.class); final Classifier<Throwable, Boolean> panic = new BinaryExceptionClassifier(types, true); classifier = new Classifier<Throwable, Boolean>() { @Override public Boolean classify(Throwable classifiable) { // Rollback if either the user's list or our own applies return panic.classify(classifiable) || binary.classify(classifiable); } }; } return classifier; }
/** * Convenience method to get an exception classifier based on the provided transaction attributes. * * @return an exception classifier: maps to true if an exception should cause rollback */ protected Classifier<Throwable, Boolean> getRollbackClassifier() { Classifier<Throwable, Boolean> classifier = new BinaryExceptionClassifier(noRollbackExceptionClasses, false); // Try to avoid pathological cases where we cannot force a rollback // (should be pretty uncommon): if (!classifier.classify(new ForceRollbackForWriteSkipException("test", new RuntimeException())) || !classifier.classify(new ExhaustedRetryException("test"))) { final Classifier<Throwable, Boolean> binary = classifier; Collection<Class<? extends Throwable>> types = new HashSet<Class<? extends Throwable>>(); types.add(ForceRollbackForWriteSkipException.class); types.add(ExhaustedRetryException.class); final Classifier<Throwable, Boolean> panic = new BinaryExceptionClassifier(types, true); classifier = (Classifier<Throwable, Boolean>) classifiable -> { // Rollback if either the user's list or our own applies return panic.classify(classifiable) || binary.classify(classifiable); }; } return classifier; }
/** * Convenience method to get an exception classifier based on the provided transaction attributes. * * @return an exception classifier: maps to true if an exception should cause rollback */ protected Classifier<Throwable, Boolean> getRollbackClassifier() { Classifier<Throwable, Boolean> classifier = new BinaryExceptionClassifier(noRollbackExceptionClasses, false); // Try to avoid pathological cases where we cannot force a rollback // (should be pretty uncommon): if (!classifier.classify(new ForceRollbackForWriteSkipException("test", new RuntimeException())) || !classifier.classify(new ExhaustedRetryException("test"))) { final Classifier<Throwable, Boolean> binary = classifier; Collection<Class<? extends Throwable>> types = new HashSet<Class<? extends Throwable>>(); types.add(ForceRollbackForWriteSkipException.class); types.add(ExhaustedRetryException.class); final Classifier<Throwable, Boolean> panic = new BinaryExceptionClassifier(types, true); classifier = (Classifier<Throwable, Boolean>) classifiable -> { // Rollback if either the user's list or our own applies return panic.classify(classifiable) || binary.classify(classifiable); }; } return classifier; }
@Override public Object recover(RetryContext context) throws Exception { /* * If the last exception was not skippable we don't need to * do any scanning. We can just bomb out with a retry * exhausted. */ if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) { throw new ExhaustedRetryException( "Retry exhausted after last attempt in recovery path, but exception is not skippable.", context.getLastThrowable()); } inputs.setBusy(true); data.scanning(true); scan(contribution, inputs, outputs, chunkMonitor, true); return null; }
@Override public Object recover(RetryContext context) throws Exception { /* * If the last exception was not skippable we don't need to * do any scanning. We can just bomb out with a retry * exhausted. */ if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) { throw new ExhaustedRetryException( "Retry exhausted after last attempt in recovery path, but exception is not skippable.", context.getLastThrowable()); } inputs.setBusy(true); data.scanning(true); scan(contribution, inputs, outputs, chunkMonitor, true); return null; }
@Override public Object recover(RetryContext context) throws Exception { /* * If the last exception was not skippable we don't need to * do any scanning. We can just bomb out with a retry * exhausted. */ if (!shouldSkip(itemWriteSkipPolicy, context.getLastThrowable(), -1)) { throw new ExhaustedRetryException( "Retry exhausted after last attempt in recovery path, but exception is not skippable.", context.getLastThrowable()); } inputs.setBusy(true); data.scanning(true); scan(contribution, inputs, outputs, chunkMonitor, true); return null; }