/* * Copyright 2006-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.retry.policy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.HashMap; import java.util.Map; import org.junit.Test; import org.springframework.retry.RecoveryCallback; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; import org.springframework.retry.support.DefaultRetryState; import org.springframework.retry.support.RetryTemplate; public class FatalExceptionRetryPolicyTests { @Test public void testFatalExceptionWithoutState() throws Throwable { MockRetryCallback callback = new MockRetryCallback(); callback.setExceptionToThrow(new IllegalArgumentException()); RetryTemplate retryTemplate = new RetryTemplate(); // Make sure certain exceptions are fatal... Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>(); map.put(IllegalArgumentException.class, false); map.put(IllegalStateException.class, false); // ... and allow multiple attempts SimpleRetryPolicy policy = new SimpleRetryPolicy(3, map); retryTemplate.setRetryPolicy(policy); RecoveryCallback<String> recoveryCallback = new RecoveryCallback<String>() { public String recover(RetryContext context) throws Exception { return "bar"; } }; Object result = null; try { result = retryTemplate.execute(callback, recoveryCallback); } catch (IllegalArgumentException e) { // We should swallow the exception when recovery is possible fail("Did not expect IllegalArgumentException"); } // Callback is called once: the recovery path should also be called assertEquals(1, callback.attempts); assertEquals("bar", result); } @Test public void testFatalExceptionWithState() throws Throwable { MockRetryCallback callback = new MockRetryCallback(); callback.setExceptionToThrow(new IllegalArgumentException()); RetryTemplate retryTemplate = new RetryTemplate(); Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>(); map.put(IllegalArgumentException.class, false); map.put(IllegalStateException.class, false); SimpleRetryPolicy policy = new SimpleRetryPolicy(3, map); retryTemplate.setRetryPolicy(policy); RecoveryCallback<String> recoveryCallback = new RecoveryCallback<String>() { public String recover(RetryContext context) throws Exception { return "bar"; } }; Object result = null; try { retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState("foo")); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // If stateful we have to always rethrow. Clients who want special // cases have to implement them in the callback } result = retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState("foo")); // Callback is called once: the recovery path should also be called assertEquals(1, callback.attempts); assertEquals("bar", result); } private static class MockRetryCallback implements RetryCallback<String, Exception> { private int attempts; private Exception exceptionToThrow = new Exception(); public String doWithRetry(RetryContext context) throws Exception { this.attempts++; // Just barf... throw this.exceptionToThrow; } public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } } }