diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index 88b7a8b5..05b90fc8 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -65,6 +65,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.gemfire.config.annotation.PeerCacheConfigurer; import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport; import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator; +import org.springframework.data.gemfire.util.SpringUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -583,7 +584,9 @@ public class CacheFactoryBean extends AbstractFactoryBeanSupport type, Arrays.toString(JndiDataSourceType.values()))); jndiDataSource.getAttributes().put("type", jndiDataSourceType.getName()); - JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps()); + + SpringUtils.safeRunOperation(() -> + JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps())); }); return cache; diff --git a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java index c1d20788..a71b23f2 100644 --- a/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java +++ b/src/main/java/org/springframework/data/gemfire/util/SpringUtils.java @@ -30,12 +30,16 @@ import java.util.function.Supplier; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.util.StringUtils; /** - * SpringUtils is a utility class encapsulating common functionality on objects and other class types. + * Abstract utility class encapsulating common functionality on {@link Object Objects} + * and other {@link Class Class types}. * * @author John Blum + * @see org.springframework.beans.factory.BeanFactory + * @see org.springframework.beans.factory.config.BeanDefinition * @since 1.8.0 */ @SuppressWarnings("unused") @@ -137,4 +141,24 @@ public abstract class SpringUtils { return exceptionHandler.apply(cause); } } + + public static void safeRunOperation(VoidReturningExceptionThrowingOperation operation) { + safeRunOperation(operation, cause -> new InvalidDataAccessApiUsageException("Failed to run operation", cause)); + } + + public static void safeRunOperation(VoidReturningExceptionThrowingOperation operation, + Function exceptionConverter) { + + try { + operation.run(); + } + catch (Throwable cause) { + throw exceptionConverter.apply(cause); + } + } + + @FunctionalInterface + public interface VoidReturningExceptionThrowingOperation { + void run() throws Throwable; + } } diff --git a/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java b/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java index 0323d93f..90275b99 100644 --- a/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/util/SpringUtilsUnitTests.java @@ -32,6 +32,7 @@ import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newI import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException; import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Supplier; @@ -43,6 +44,7 @@ import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.dao.InvalidDataAccessApiUsageException; /** * Unit tests for {@link SpringUtils}. @@ -403,4 +405,49 @@ public class SpringUtilsUnitTests { throw expected; } } + + @Test + public void safeRunOperationRunsSuccessfully() { + + AtomicBoolean operationRan = new AtomicBoolean(false); + + SpringUtils.safeRunOperation(() -> operationRan.set(true)); + + assertThat(operationRan.get()).isTrue(); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + public void safeRunOperationThrowsInvalidDataAccessApiUsageException() { + + try { + SpringUtils.safeRunOperation(() -> { throw new Exception("TEST"); }); + } + catch (InvalidDataAccessApiUsageException expected) { + + assertThat(expected).hasMessageContaining("Failed to run operation"); + assertThat(expected).hasCauseInstanceOf(Exception.class); + assertThat(expected.getCause()).hasMessage("TEST"); + assertThat(expected.getCause()).hasNoCause(); + + throw expected; + } + } + + @Test(expected = IllegalStateException.class) + public void safeRunOperationThrowsCustomRuntimeException() { + + try { + SpringUtils.safeRunOperation(() -> { throw new Exception("TEST"); }, + cause -> new IllegalStateException("FOO", cause)); + } + catch (IllegalStateException expected) { + + assertThat(expected).hasMessage("FOO"); + assertThat(expected).hasCauseInstanceOf(Exception.class); + assertThat(expected.getCause()).hasMessage("TEST"); + assertThat(expected.getCause()).hasNoCause(); + + throw expected; + } + } }