DATAGEODE-306 - Add overloaded safeDoOperation(:VoidReturningThrowableOperation, backupOperation:Runnable) method.
Redefine safeDoOperation(:VoidReturningThrowableOperation) in terms of the overloaded method. Edit Javadoc.
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.util;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
@@ -26,38 +25,116 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* SpringUtils is a utility class encapsulating common functionality on objects and other class types.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Class
|
||||
* @see java.lang.Object
|
||||
* @see java.util.function.Function
|
||||
* @see java.util.stream.Stream
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
* @see org.springframework.beans.factory.config.RuntimeBeanReference
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
* @see org.springframework.core.annotation.Order
|
||||
* @since 1.8.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class SpringUtils {
|
||||
|
||||
public static BeanDefinition addDependsOn(BeanDefinition bean, String... beanNames) {
|
||||
/**
|
||||
* Determines whether a given bean registered in the {@link BeanFactory Spring container} matches by
|
||||
* both {@link String name} and {@link Class type}.
|
||||
*
|
||||
* @param beanFactory {@link BeanFactory Spring container} in which to resolve the bean.
|
||||
* @param beanName {@link String name} of the bean.
|
||||
* @param beanType {@link Class type} of the bean.
|
||||
* @return a boolean value indicating whether the {@link BeanFactory Spring container} contains a bean
|
||||
* matching by both {@link String name} and {@link Class type}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see java.lang.Class
|
||||
* @see java.lang.String
|
||||
*/
|
||||
public static boolean isMatchingBean(@NonNull BeanFactory beanFactory, String beanName, Class<?> beanType) {
|
||||
return beanFactory.containsBean(beanName) && beanFactory.isTypeMatch(beanName, beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of bean dependencies (by name) to the given {@link BeanDefinition}.
|
||||
*
|
||||
* @param beanDefinition {@link BeanDefinition} to add the bean dependencies to.
|
||||
* @param beanNames {@link String} array containing names of beans to which the {@link BeanDefinition}
|
||||
* has a dependency.
|
||||
* @return the given {@link BeanDefinition}.
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
*/
|
||||
@NonNull
|
||||
public static BeanDefinition addDependsOn(@NonNull BeanDefinition beanDefinition, @Nullable String... beanNames) {
|
||||
|
||||
List<String> dependsOnList = new ArrayList<>();
|
||||
|
||||
Collections.addAll(dependsOnList, nullSafeArray(bean.getDependsOn(), String.class));
|
||||
Collections.addAll(dependsOnList, ArrayUtils.nullSafeArray(beanDefinition.getDependsOn(), String.class));
|
||||
dependsOnList.addAll(Arrays.asList(nullSafeArray(beanNames, String.class)));
|
||||
bean.setDependsOn(dependsOnList.toArray(new String[dependsOnList.size()]));
|
||||
beanDefinition.setDependsOn(dependsOnList.toArray(new String[0]));
|
||||
|
||||
return bean;
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to return the {@link Integer order} of the given {@link Object} if it is {@link Ordered}
|
||||
* or {@literal null} if the given {@link Object} is not {@link Ordered}.
|
||||
*
|
||||
* @param target {@link Object} to evaluate; may be {@literal null}.
|
||||
* @return the {@link Integer order} of the given {@link Object} if {@link Ordered},
|
||||
* otherwise return {@literal null}.
|
||||
* @see org.springframework.core.Ordered
|
||||
*/
|
||||
public static @Nullable Integer getOrder(@Nullable Object target) {
|
||||
return target instanceof Ordered ? ((Ordered) target).getOrder() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bean of the given {@link Class type} in an ordered {@link Stream}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the beans.
|
||||
* @param beanFactory {@link BeanFactory} from which to acquire the beans.
|
||||
* @param beanType {@link Class type} of the beans.
|
||||
* @return an ordered {@link Stream} of beans from the {@link BeanFactory} of the given {@link Class type}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see java.util.stream.Stream
|
||||
* @see java.lang.Class
|
||||
*/
|
||||
public static <T> Stream<T> getOrderedStreamOfBeansByType(@NonNull BeanFactory beanFactory,
|
||||
@NonNull Class<T> beanType) {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(beanType,"Bean type must not be null");
|
||||
|
||||
return beanFactory.getBeanProvider(beanType).orderedStream();
|
||||
}
|
||||
|
||||
public static Optional<Object> getPropertyValue(BeanDefinition beanDefinition, String propertyName) {
|
||||
|
||||
return Optional.ofNullable(beanDefinition)
|
||||
.map(it -> it.getPropertyValues())
|
||||
.map(BeanDefinition::getPropertyValues)
|
||||
.map(propertyValues -> propertyValues.getPropertyValue(propertyName))
|
||||
.map(propertyValue -> propertyValue.getValue());
|
||||
.map(PropertyValue::getValue);
|
||||
}
|
||||
|
||||
public static BeanDefinition setPropertyReference(BeanDefinition beanDefinition,
|
||||
@@ -116,25 +193,131 @@ public abstract class SpringUtils {
|
||||
return type != null ? type.getSimpleName() : null;
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(Supplier<T> valueSupplier) {
|
||||
return safeGetValue(valueSupplier, (T) null);
|
||||
public static Class<?> nullSafeType(Object target) {
|
||||
return nullSafeType(target, null);
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(Supplier<T> valueSupplier, T defaultValue) {
|
||||
return safeGetValue(valueSupplier, (Supplier<T>) () -> defaultValue);
|
||||
public static Class<?> nullSafeType(Object target, Class<?> defaultType) {
|
||||
return target != null ? target.getClass() : defaultType;
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(Supplier<T> valueSupplier, Supplier<T> defaultValueSupplier) {
|
||||
return safeGetValue(valueSupplier, (Function<Throwable, T>) exception -> defaultValueSupplier.get());
|
||||
public static boolean safeDoOperation(VoidReturningThrowableOperation operation) {
|
||||
return safeDoOperation(operation, () -> {});
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(Supplier<T> valueSupplier, Function<Throwable, T> exceptionHandler) {
|
||||
public static boolean safeDoOperation(VoidReturningThrowableOperation operation, Runnable backupOperation) {
|
||||
|
||||
try {
|
||||
return valueSupplier.get();
|
||||
operation.run();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable cause) {
|
||||
backupOperation.run();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(ValueReturningThrowableOperation<T> operation) {
|
||||
return safeGetValue(operation, (T) null);
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(ValueReturningThrowableOperation<T> operation, T defaultValue) {
|
||||
return safeGetValue(operation, (Supplier<T>) () -> defaultValue);
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(ValueReturningThrowableOperation<T> operation, Supplier<T> defaultValueSupplier) {
|
||||
return safeGetValue(operation, (Function<Throwable, T>) exception -> defaultValueSupplier.get());
|
||||
}
|
||||
|
||||
public static <T> T safeGetValue(ValueReturningThrowableOperation<T> operation,
|
||||
Function<Throwable, T> exceptionHandler) {
|
||||
|
||||
try {
|
||||
return operation.get();
|
||||
}
|
||||
catch (Throwable cause) {
|
||||
return exceptionHandler.apply(cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static void safeRunOperation(VoidReturningThrowableOperation operation) {
|
||||
safeRunOperation(operation, cause -> new InvalidDataAccessApiUsageException("Failed to run operation", cause));
|
||||
}
|
||||
|
||||
public static void safeRunOperation(VoidReturningThrowableOperation operation,
|
||||
Function<Throwable, RuntimeException> exceptionConverter) {
|
||||
|
||||
try {
|
||||
operation.run();
|
||||
}
|
||||
catch (Throwable cause) {
|
||||
throw exceptionConverter.apply(cause);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DefaultOrderedBeanWrapper<T> implements OrderedBeanWrapper<T> {
|
||||
|
||||
private static <T> OrderedBeanWrapper<T> from(String beanName, T bean) {
|
||||
return from(beanName, bean, Ordered.LOWEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
private static <T> OrderedBeanWrapper<T> from(String beanName, T bean, int order) {
|
||||
return new DefaultOrderedBeanWrapper<>(beanName, bean, order);
|
||||
}
|
||||
|
||||
private final int order;
|
||||
|
||||
private final T bean;
|
||||
|
||||
private final String beanName;
|
||||
|
||||
private DefaultOrderedBeanWrapper(String beanName, T bean, int order) {
|
||||
|
||||
Assert.notNull(bean, "Bean must not be null");
|
||||
Assert.hasText(beanName, "Bean name is required");
|
||||
|
||||
this.bean = bean;
|
||||
this.beanName = beanName;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getBean() {
|
||||
return this.bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OrderedBeanWrapper<T> extends Ordered {
|
||||
|
||||
T getBean();
|
||||
|
||||
String getBeanName();
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ValueReturningThrowableOperation<T> {
|
||||
T get() throws Throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link VoidReturningThrowableOperation}.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface VoidReturningExceptionThrowingOperation extends VoidReturningThrowableOperation { }
|
||||
|
||||
@FunctionalInterface
|
||||
public interface VoidReturningThrowableOperation {
|
||||
void run() throws Throwable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -26,12 +25,16 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -39,20 +42,25 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
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.data.gemfire.test.model.Person;
|
||||
import org.springframework.data.gemfire.util.SpringUtils.ValueReturningThrowableOperation;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SpringUtils}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.function.Function
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
* @see org.springframework.data.gemfire.util.SpringUtils
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@@ -164,7 +172,6 @@ public class SpringUtilsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void setBeanDefinitionPropertyReference() {
|
||||
|
||||
BeanDefinition mockBeanDefinition = mock(BeanDefinition.class);
|
||||
@@ -186,7 +193,6 @@ public class SpringUtilsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void setBeanDefinitionPropertyValue() {
|
||||
|
||||
BeanDefinition mockBeanDefinition = mock(BeanDefinition.class);
|
||||
@@ -334,6 +340,96 @@ public class SpringUtilsUnitTests {
|
||||
assertThat(SpringUtils.nullSafeEquals("test", "mock")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeNameWithType() {
|
||||
|
||||
assertThat(SpringUtils.nullSafeName(Boolean.class)).isEqualTo(Boolean.class.getName());
|
||||
assertThat(SpringUtils.nullSafeName(Integer.class)).isEqualTo(Integer.class.getName());
|
||||
assertThat(SpringUtils.nullSafeName(Double.class)).isEqualTo(Double.class.getName());
|
||||
assertThat(SpringUtils.nullSafeName(String.class)).isEqualTo(String.class.getName());
|
||||
assertThat(SpringUtils.nullSafeName(Time.class)).isEqualTo(Time.class.getName());
|
||||
assertThat(SpringUtils.nullSafeName(Person.class)).isEqualTo(Person.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeNameWithNull() {
|
||||
assertThat(SpringUtils.nullSafeName(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeSimpleNameWithType() {
|
||||
|
||||
assertThat(SpringUtils.nullSafeSimpleName(Boolean.class)).isEqualTo(Boolean.class.getSimpleName());
|
||||
assertThat(SpringUtils.nullSafeSimpleName(Integer.class)).isEqualTo(Integer.class.getSimpleName());
|
||||
assertThat(SpringUtils.nullSafeSimpleName(Double.class)).isEqualTo(Double.class.getSimpleName());
|
||||
assertThat(SpringUtils.nullSafeSimpleName(String.class)).isEqualTo(String.class.getSimpleName());
|
||||
assertThat(SpringUtils.nullSafeSimpleName(Time.class)).isEqualTo(Time.class.getSimpleName());
|
||||
assertThat(SpringUtils.nullSafeSimpleName(Person.class)).isEqualTo(Person.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeSimpleNameWithNull() {
|
||||
assertThat(SpringUtils.nullSafeSimpleName(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeTypeWithObject() {
|
||||
assertThat(SpringUtils.nullSafeType(new Object())).isEqualTo(Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeTypeWithObjectAndDefaultType() {
|
||||
assertThat(SpringUtils.nullSafeType("test", Person.class)).isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeTypeWithNull() {
|
||||
assertThat(SpringUtils.nullSafeType(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeTypeWithNullAndDefaultType() {
|
||||
assertThat(SpringUtils.nullSafeType(null, Person.class)).isEqualTo(Person.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeDoOperationWithNonThrowingOperation() {
|
||||
|
||||
AtomicReference<Object> operationValue = new AtomicReference<>();
|
||||
|
||||
assertThat(SpringUtils.safeDoOperation(() -> operationValue.set("TEST"))).isTrue();
|
||||
assertThat(operationValue.get()).isEqualTo("TEST");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeDoOperationWithThrowingOperation() {
|
||||
assertThat(SpringUtils.safeDoOperation(() -> { throw new RuntimeException("TEST"); })).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeDoOperationWithNonThrowingOperationAndBackupOperation() {
|
||||
|
||||
AtomicReference<Object> operationValue = new AtomicReference<>();
|
||||
|
||||
Runnable mockRunnable = mock(Runnable.class);
|
||||
|
||||
assertThat(SpringUtils.safeDoOperation(() -> operationValue.set("MOCK"), mockRunnable)).isTrue();
|
||||
assertThat(operationValue.get()).isEqualTo("MOCK");
|
||||
|
||||
verifyNoInteractions(mockRunnable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeDoOperationWithThrowingOperationAndBackupOperation() {
|
||||
|
||||
Runnable mockRunnable = mock(Runnable.class);
|
||||
|
||||
assertThat(SpringUtils.safeDoOperation(() -> { throw new RuntimeException("TEST"); }, mockRunnable)).isFalse();
|
||||
|
||||
verify(mockRunnable, times(1)).run();
|
||||
verifyNoMoreInteractions(mockRunnable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeGetValueReturnsSuppliedValue() {
|
||||
assertThat(SpringUtils.safeGetValue(() -> "test")).isEqualTo("test");
|
||||
@@ -353,16 +449,19 @@ public class SpringUtilsUnitTests {
|
||||
@Test
|
||||
public void safeGetValueReturnsSuppliedDefaultValue() {
|
||||
|
||||
Supplier<String> exceptionThrowingSupplier = () -> { throw newRuntimeException("error"); };
|
||||
ValueReturningThrowableOperation<String> exceptionThrowingOperation =
|
||||
() -> { throw newRuntimeException("error"); };
|
||||
|
||||
Supplier<String> defaultValueSupplier = () -> "test";
|
||||
|
||||
assertThat(SpringUtils.safeGetValue(exceptionThrowingSupplier, defaultValueSupplier)).isEqualTo("test");
|
||||
assertThat(SpringUtils.safeGetValue(exceptionThrowingOperation, defaultValueSupplier)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeGetValueHandlesExceptionReturnsValue() {
|
||||
|
||||
Supplier<String> exceptionThrowingSupplier = () -> { throw newRuntimeException("error"); };
|
||||
ValueReturningThrowableOperation<String> exceptionThrowingOperation =
|
||||
() -> { throw newRuntimeException("error"); };
|
||||
|
||||
Function<Throwable, String> exceptionHandler = exception -> {
|
||||
|
||||
@@ -373,13 +472,14 @@ public class SpringUtilsUnitTests {
|
||||
return "test";
|
||||
};
|
||||
|
||||
assertThat(SpringUtils.safeGetValue(exceptionThrowingSupplier, exceptionHandler)).isEqualTo("test");
|
||||
assertThat(SpringUtils.safeGetValue(exceptionThrowingOperation, exceptionHandler)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void safeGetValueHandlesExceptionAndCanThrowException() {
|
||||
|
||||
Supplier<String> exceptionThrowingSupplier = () -> { throw newRuntimeException("error"); };
|
||||
ValueReturningThrowableOperation<String> exceptionThrowingOperation =
|
||||
() -> { throw newRuntimeException("error"); };
|
||||
|
||||
Function<Throwable, String> exceptionHandler = exception -> {
|
||||
|
||||
@@ -391,7 +491,7 @@ public class SpringUtilsUnitTests {
|
||||
};
|
||||
|
||||
try {
|
||||
SpringUtils.safeGetValue(exceptionThrowingSupplier, exceptionHandler);
|
||||
SpringUtils.safeGetValue(exceptionThrowingOperation, exceptionHandler);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user