DATAGEODE-16 - Add support for Geode JCA ResourceAdapter.
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright 2017 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.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionAcquiringAspect;
|
||||
import org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionClosingAspect;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GemFireAsLastResourceConfiguration}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @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.data.gemfire.config.annotation.GemFireAsLastResourceConfiguration
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GemFireAsLastResourceConfigurationUnitTests {
|
||||
|
||||
@Mock
|
||||
private AnnotationMetadata mockImportMetadata;
|
||||
|
||||
private GemFireAsLastResourceConfiguration configuration;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
configuration = new GemFireAsLastResourceConfiguration();
|
||||
}
|
||||
|
||||
private AnnotationMetadata mockEnableTransactionManagementWithOrder(Integer order) {
|
||||
|
||||
Map<String, Object> enableTransactionManagementAttributes = Collections.singletonMap("order", order);
|
||||
|
||||
when(mockImportMetadata.getAnnotationAttributes(eq(EnableTransactionManagement.class.getName())))
|
||||
.thenReturn(enableTransactionManagementAttributes);
|
||||
|
||||
return mockImportMetadata;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEnableTransactionManagementAttributes() {
|
||||
|
||||
Map<String, Object> enableTransactionManagementAttributesMap = new HashMap<>();
|
||||
|
||||
enableTransactionManagementAttributesMap.put("mode", AdviceMode.ASPECTJ);
|
||||
enableTransactionManagementAttributesMap.put("order", 1);
|
||||
enableTransactionManagementAttributesMap.put("proxyTargetClass", true);
|
||||
|
||||
when(mockImportMetadata.getAnnotationAttributes(eq(EnableTransactionManagement.class.getName())))
|
||||
.thenReturn(enableTransactionManagementAttributesMap);
|
||||
|
||||
AnnotationAttributes enableTransactionManagementAttributes =
|
||||
configuration.resolveEnableTransactionManagementAttributes(mockImportMetadata);
|
||||
|
||||
assertThat(enableTransactionManagementAttributes).isNotNull();
|
||||
assertThat(enableTransactionManagementAttributes.<AdviceMode>getEnum("mode"))
|
||||
.isEqualTo(AdviceMode.ASPECTJ);
|
||||
assertThat(enableTransactionManagementAttributes.getBoolean("proxyTargetClass")).isTrue();
|
||||
|
||||
verify(mockImportMetadata, times(1))
|
||||
.getAnnotationAttributes(eq(EnableTransactionManagement.class.getName()));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void resolveEnableTransactionManagementAttributesThrowsIllegalStateException() {
|
||||
try {
|
||||
when(mockImportMetadata.getAnnotationAttributes(anyString())).thenReturn(null);
|
||||
|
||||
configuration.resolveEnableTransactionManagementAttributes(mockImportMetadata);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(String.format(
|
||||
"The @%1$s annotation may only be used on a Spring application @%2$s class"
|
||||
+ " that is also annotated with @%3$s having an explicit [order] set",
|
||||
EnableGemFireAsLastResource.class.getSimpleName(), Configuration.class.getSimpleName(),
|
||||
EnableTransactionManagement.class.getSimpleName()));
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEnableTransactionManagementOrderEqualsOne() {
|
||||
assertThat(configuration.resolveEnableTransactionManagementOrder(
|
||||
mockEnableTransactionManagementWithOrder(1))).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void resolveEnableTransactionManagementOrderThrowsIllegalArgumentExceptionForIntegerMaxValue() {
|
||||
try {
|
||||
configuration.resolveEnableTransactionManagementOrder(
|
||||
mockEnableTransactionManagementWithOrder(Integer.MAX_VALUE));
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(String.format(
|
||||
"The @%1$s(order) attribute value [%2$d] must be explicitly set to a value other than"
|
||||
+ " Integer.MAX_VALUE or Integer.MIN_VALUE",
|
||||
EnableTransactionManagement.class.getSimpleName(), Integer.MAX_VALUE));
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void resolveEnableTransactionManagementOrderThrowsIllegalArgumentExceptionForIntegerMinValue() {
|
||||
try {
|
||||
configuration.resolveEnableTransactionManagementOrder(
|
||||
mockEnableTransactionManagementWithOrder(Integer.MIN_VALUE));
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(String.format(
|
||||
"The @%1$s(order) attribute value [%2$d] must be explicitly set to a value other than"
|
||||
+ " Integer.MAX_VALUE or Integer.MIN_VALUE",
|
||||
EnableTransactionManagement.class.getSimpleName(), Integer.MIN_VALUE));
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEnableTransactionManagementOrderReturnsValue() {
|
||||
|
||||
configuration.setImportMetadata(mockEnableTransactionManagementWithOrder(101));
|
||||
|
||||
assertThat(configuration.getEnableTransactionManagementOrder()).isEqualTo(101);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getEnableTransactionManagementOrderThrowsIllegalStateException() {
|
||||
try {
|
||||
configuration.getEnableTransactionManagementOrder();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(String.format("The @%1$s(order) attribute was not properly set [null];"
|
||||
+ " Also, please make your Spring application @%2$s annotated class is annotated with both @%3$s and @%1$s",
|
||||
EnableTransactionManagement.class.getSimpleName(), Configuration.class.getSimpleName(),
|
||||
EnableGemFireAsLastResource.class.getSimpleName()));
|
||||
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gemfireCachePostProcessorSetsCopyOnReadToTrue() {
|
||||
|
||||
GemFireCache mockGemFireCache = mock(GemFireCache.class);
|
||||
|
||||
assertThat(configuration.gemfireCachePostProcessor(mockGemFireCache)).isNull();
|
||||
|
||||
verify(mockGemFireCache, times(1)).setCopyOnRead(eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gemfireCachePostProcessorHandlesNull() {
|
||||
assertThat(configuration.gemfireCachePostProcessor(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gemfireJcaConnectionAcquiringAspectIsOrderPlusOne() {
|
||||
|
||||
configuration.setImportMetadata(mockEnableTransactionManagementWithOrder(0));
|
||||
|
||||
GemFireAsLastResourceConnectionAcquiringAspect aspect = configuration.gemfireJcaConnectionAcquiringAspect();
|
||||
|
||||
assertThat(aspect).isNotNull();
|
||||
assertThat(aspect.getOrder()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gemfireJcaConnectionClosingAspectIsOrderMinusOne() {
|
||||
|
||||
configuration.setImportMetadata(mockEnableTransactionManagementWithOrder(0));
|
||||
|
||||
GemFireAsLastResourceConnectionClosingAspect aspect = configuration.gemfireJcaConnectionClosingAspect();
|
||||
|
||||
assertThat(aspect).isNotNull();
|
||||
assertThat(aspect.getOrder()).isEqualTo(-1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright 2017 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.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.internal.matchers.VarargMatcher;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractGemFireAsLastResourceAspectSupport}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see javax.naming.Context
|
||||
* @see javax.naming.InitialContext
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.AbstractGemFireAsLastResourceAspectSupport
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractGemFireAsLastResourceAspectSupportUnitTests {
|
||||
|
||||
@Mock
|
||||
private Logger mockLogger;
|
||||
|
||||
@Spy
|
||||
private AbstractGemFireAsLastResourceAspectSupport aspectSupport;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("all")
|
||||
public void setup() {
|
||||
doReturn(mockLogger).when(aspectSupport).getLogger();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetOrder() {
|
||||
|
||||
assertThat(aspectSupport.getOrder()).isEqualTo(AbstractGemFireAsLastResourceAspectSupport.DEFAULT_ORDER);
|
||||
|
||||
aspectSupport.setOrder(1);
|
||||
|
||||
assertThat(aspectSupport.getOrder()).isEqualTo(1);
|
||||
|
||||
aspectSupport.setOrder(-2);
|
||||
|
||||
assertThat(aspectSupport.getOrder()).isEqualTo(-2);
|
||||
|
||||
aspectSupport.setOrder(Integer.MAX_VALUE);
|
||||
|
||||
assertThat(aspectSupport.getOrder()).isEqualTo(AbstractGemFireAsLastResourceAspectSupport.DEFAULT_ORDER);
|
||||
|
||||
aspectSupport.setOrder(Integer.MIN_VALUE);
|
||||
|
||||
assertThat(aspectSupport.getOrder()).isEqualTo(AbstractGemFireAsLastResourceAspectSupport.DEFAULT_ORDER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logDebugInfoWhenDebuggingIsDisabled() {
|
||||
|
||||
when(mockLogger.isDebugEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logDebugInfo("message", "arg"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isDebugEnabled();
|
||||
verify(mockLogger, never()).debug(anyString());
|
||||
verify(mockLogger, never()).debug(anyString(), any(Object.class));
|
||||
verify(mockLogger, never()).debug(anyString(), any(Object.class), any(Object.class));
|
||||
verify(mockLogger, never()).debug(anyString(), any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logDebugInfoWhenDebuggingIsEnabled() {
|
||||
|
||||
when(mockLogger.isDebugEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logDebugInfo("test %s message",
|
||||
"debug", "test")) .isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isDebugEnabled();
|
||||
// TODO why the f#&k does this not work Mockito?!
|
||||
//verify(mockLogger, times(1))
|
||||
// .debug(eq("test debug message"), eq("debug"), eq("test"));
|
||||
// TODO this ridiculous sh!t works
|
||||
//verify(mockLogger, times(1)).debug(eq("test debug message"),
|
||||
// ArgumentMatchers.<Object[]>any());
|
||||
// TODO and so does this, but what a hack!
|
||||
verify(mockLogger, times(1)).debug(eq("test debug message"),
|
||||
VariableArgumentMatcher.varArgThat("debug", "test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logInfoWhenInfoIsDisabled() {
|
||||
|
||||
when(mockLogger.isInfoEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logInfo("message", "arg"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isInfoEnabled();
|
||||
verify(mockLogger, never()).info(anyString(), any(Object.class));
|
||||
verify(mockLogger, never()).info(anyString(), any(Object.class), any(Object.class));
|
||||
verify(mockLogger, never()).info(anyString(), any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logInfoWhenInfoIsEnabled() {
|
||||
|
||||
when(mockLogger.isInfoEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logInfo("test %s message", "info"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isInfoEnabled();
|
||||
verify(mockLogger, times(1)).info(eq("test info message"),
|
||||
VariableArgumentMatcher.varArgThat("info"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logTraceInfoWhenTracingIsDisabled() {
|
||||
|
||||
when(mockLogger.isTraceEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logTraceInfo("message", "arg"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isTraceEnabled();
|
||||
verify(mockLogger, never()).trace(anyString());
|
||||
verify(mockLogger, never()).trace(anyString(), any(Object.class));
|
||||
verify(mockLogger, never()).trace(anyString(), any(Object.class), any(Object.class));
|
||||
verify(mockLogger, never()).trace(anyString(), any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logTraceInfoWhenTracingIsEnabled() {
|
||||
|
||||
when(mockLogger.isTraceEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logTraceInfo("test %s message", "trace"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isTraceEnabled();
|
||||
verify(mockLogger, times(1)).trace(eq("test trace message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logTraceInfoUsingMessageSupplierWhenTracingIsEnabled() {
|
||||
|
||||
when(mockLogger.isTraceEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logTraceInfo(
|
||||
() -> "trace test message with Supplier")).isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isTraceEnabled();
|
||||
verify(mockLogger, times(1)).trace(eq("trace test message with Supplier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logWarningWhenWarningsAreDisabled() {
|
||||
|
||||
when(mockLogger.isWarnEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logWarning("message", "arg"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isWarnEnabled();
|
||||
verify(mockLogger, never()).warn(anyString());
|
||||
verify(mockLogger, never()).warn(anyString(), any(Object.class));
|
||||
verify(mockLogger, never()).warn(anyString(), any(Object.class), any(Object.class));
|
||||
verify(mockLogger, never()).warn(anyString(), any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logWarningWhenWarningsAreEnabled() {
|
||||
|
||||
when(mockLogger.isWarnEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logWarning("test %s message", "warning"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isWarnEnabled();
|
||||
verify(mockLogger, times(1)).warn(eq("test warning message"),
|
||||
VariableArgumentMatcher.varArgThat("warning"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logErrorWhenErrorsAreDisabled() {
|
||||
|
||||
when(mockLogger.isErrorEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logError("message", "arg"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isErrorEnabled();
|
||||
verify(mockLogger, never()).error(anyString());
|
||||
verify(mockLogger, never()).error(anyString(), any(Object.class));
|
||||
verify(mockLogger, never()).error(anyString(), any(Object.class), any(Object.class));
|
||||
verify(mockLogger, never()).error(anyString(), any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logErrorWhenErrorsAreEnabled() {
|
||||
|
||||
when(mockLogger.isErrorEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>logError("test %s message", "error"))
|
||||
.isSameAs(aspectSupport);
|
||||
|
||||
verify(mockLogger, times(1)).isErrorEnabled();
|
||||
verify(mockLogger, times(1)).error(eq("test error message"),
|
||||
VariableArgumentMatcher.varArgThat("error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveContextReturnsConfiguredContext() throws NamingException {
|
||||
|
||||
Context mockContext = mock(Context.class);
|
||||
|
||||
doReturn(mockContext).when(aspectSupport).getContext();
|
||||
|
||||
assertThat(aspectSupport.resolveContext()).isSameAs(mockContext);
|
||||
|
||||
verify(aspectSupport, never()).newInitialContext(any(Hashtable.class));
|
||||
verifyZeroInteractions(mockContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveContextReturnsNewInitialContext() throws NamingException {
|
||||
|
||||
Hashtable<String, Object> mockEnvironment = new Hashtable<>();
|
||||
|
||||
InitialContext mockContext = mock(InitialContext.class);
|
||||
|
||||
doReturn(mockContext).when(aspectSupport).newInitialContext(any(Hashtable.class));
|
||||
doReturn(mockEnvironment).when(aspectSupport).resolveEnvironment();
|
||||
|
||||
assertThat(aspectSupport.resolveContext()).isEqualTo(mockContext);
|
||||
|
||||
verify(aspectSupport, times(1)).getContext();
|
||||
verify(aspectSupport, times(1)).newInitialContext(eq(mockEnvironment));
|
||||
verifyZeroInteractions(mockContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveContextHandlesNamingExceptionAndReturnsGemFireJndiContext() throws NamingException {
|
||||
|
||||
Context mockContext = mock(Context.class);
|
||||
|
||||
GemFireCache mockGemFireCache = mock(GemFireCache.class);
|
||||
|
||||
Hashtable<String, Object> mockEnvironment = new Hashtable<>();
|
||||
|
||||
doThrow(new NamingException("TEST")).when(aspectSupport).newInitialContext(any(Hashtable.class));
|
||||
doReturn(mockEnvironment).when(aspectSupport).resolveEnvironment();
|
||||
doReturn(mockGemFireCache).when(aspectSupport).resolveGemFireCache();
|
||||
doReturn(mockContext).when(mockGemFireCache).getJNDIContext();
|
||||
|
||||
assertThat(aspectSupport.resolveContext()).isEqualTo(mockContext);
|
||||
|
||||
verify(aspectSupport, times(1)).getContext();
|
||||
verify(aspectSupport, times(1)).resolveEnvironment();
|
||||
verify(aspectSupport, times(1)).newInitialContext(eq(mockEnvironment));
|
||||
verify(aspectSupport, times(1)).resolveGemFireCache();
|
||||
verify(mockGemFireCache, times(1)).getJNDIContext();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void resolveContextHandlesNamingExceptionAndThrowsIllegalStateException() throws NamingException {
|
||||
|
||||
Hashtable<String, Object> testEnvironment = new Hashtable<>();
|
||||
|
||||
testEnvironment.put("key", "test");
|
||||
|
||||
doThrow(new NamingException("TEST")).when(aspectSupport).newInitialContext(any(Hashtable.class));
|
||||
doReturn(testEnvironment).when(aspectSupport).resolveEnvironment();
|
||||
doReturn(null).when(aspectSupport).resolveGemFireCache();
|
||||
|
||||
try {
|
||||
aspectSupport.resolveContext();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(
|
||||
"Failed to initialize an %1$s with the provided Environment configuration [%2$s]",
|
||||
InitialContext.class.getName(), testEnvironment.toString());
|
||||
|
||||
assertThat(expected).hasCauseInstanceOf(NamingException.class);
|
||||
assertThat(expected.getCause()).hasMessage("TEST");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(aspectSupport, times(1)).getContext();
|
||||
verify(aspectSupport, times(1)).resolveEnvironment();
|
||||
verify(aspectSupport, times(1)).newInitialContext(eq(testEnvironment));
|
||||
verify(aspectSupport, times(1)).resolveGemFireCache();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEnvironmentContainsInitialContextFactoryAndProviderUrl() {
|
||||
|
||||
doReturn("org.example.test.naming.AppServerContextFactory").when(aspectSupport)
|
||||
.getInitialContextFactory();
|
||||
|
||||
doReturn("jndi:rmi://java/comp:jndi/context").when(aspectSupport).getProviderUrl();
|
||||
|
||||
Hashtable<?, ?> resolvedEnvironment = aspectSupport.resolveEnvironment();
|
||||
|
||||
assertThat(resolvedEnvironment).isNotNull();
|
||||
assertThat(resolvedEnvironment).hasSize(2);
|
||||
assertThat(resolvedEnvironment.containsKey(Context.INITIAL_CONTEXT_FACTORY)).isTrue();
|
||||
assertThat(resolvedEnvironment.get(Context.INITIAL_CONTEXT_FACTORY))
|
||||
.isEqualTo("org.example.test.naming.AppServerContextFactory");
|
||||
assertThat(resolvedEnvironment.containsKey(Context.PROVIDER_URL)).isTrue();
|
||||
assertThat(resolvedEnvironment.get(Context.PROVIDER_URL)).isEqualTo("jndi:rmi://java/comp:jndi/context");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveGemFireCacheReturnsConfiguredGemFireCache() {
|
||||
|
||||
GemFireCache mockGemFireCache = mock(GemFireCache.class);
|
||||
|
||||
doReturn(mockGemFireCache).when(aspectSupport).getGemFireCache();
|
||||
|
||||
assertThat(aspectSupport.resolveGemFireCache()).isSameAs(mockGemFireCache);
|
||||
|
||||
verify(aspectSupport, times(1)).getGemFireCache();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveGemFireCacheReturnsNull() {
|
||||
|
||||
assertThat(aspectSupport.resolveGemFireCache()).isNull();
|
||||
|
||||
verify(aspectSupport, times(1)).getGemFireCache();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveGemFireJcaResourceAdapterJndiNameReturnsConfiguredJndiName() {
|
||||
|
||||
doReturn("java/comp:gemfire/jca/resourceAdapter").when(aspectSupport)
|
||||
.getGemFireJcaResourceAdapterJndiName();
|
||||
|
||||
assertThat(aspectSupport.resolveGemFireJcaResourceAdapterJndiName())
|
||||
.isEqualTo("java/comp:gemfire/jca/resourceAdapter");
|
||||
|
||||
verify(aspectSupport, times(1)).getGemFireJcaResourceAdapterJndiName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveGemFireJcaResourceAdapterJndiNameReturnsDefaultJndiName() {
|
||||
assertThat(aspectSupport.getGemFireJcaResourceAdapterJndiName()).isNull();
|
||||
assertThat(aspectSupport.resolveGemFireJcaResourceAdapterJndiName())
|
||||
.isEqualTo(AbstractGemFireAsLastResourceAspectSupport.DEFAULT_GEMFIRE_JCA_RESOURCE_ADAPTER_JNDI_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withThrowOnErrorAndIsThrowOnError() {
|
||||
assertThat(aspectSupport.isThrowOnError()).isFalse();
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>withThrowOnError(true)).isSameAs(aspectSupport);
|
||||
assertThat(aspectSupport.isThrowOnError()).isTrue();
|
||||
assertThat(aspectSupport.<AbstractGemFireAsLastResourceAspectSupport>withThrowOnError(false)).isSameAs(aspectSupport);
|
||||
assertThat(aspectSupport.isThrowOnError()).isFalse();
|
||||
}
|
||||
|
||||
// TODO refactor this BS; damn you Mockito for your inability to match Varargs completely/reliably; WTF!
|
||||
protected static final class VariableArgumentMatcher<T> implements ArgumentMatcher<T>, VarargMatcher {
|
||||
|
||||
protected static Object[] varArgThat(Object... expectedArguments) {
|
||||
return argThat(new VariableArgumentMatcher<>(expectedArguments));
|
||||
}
|
||||
|
||||
private Object[] expectedArguments;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected VariableArgumentMatcher(Object... expectedArguments) {
|
||||
this.expectedArguments = Optional.ofNullable(expectedArguments)
|
||||
.orElseThrow(() -> newIllegalArgumentException("Expected arguments must not be null"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean matches(T actualArgument) {
|
||||
return asList(this.expectedArguments).containsAll(asList(actualArgument));
|
||||
}
|
||||
|
||||
private List<Object> asList(Object argument) {
|
||||
return Arrays.asList(toArray(argument));
|
||||
}
|
||||
|
||||
private Object[] toArray(Object argument) {
|
||||
return (argument instanceof Object[] ? (Object[]) argument : new Object[] { argument });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright 2017 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.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.ra.GFConnection;
|
||||
import org.apache.geode.ra.GFConnectionFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableGemFireAsLastResource;
|
||||
import org.springframework.data.gemfire.config.annotation.GemFireAsLastResourceConfiguration;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link EnableGemFireAsLastResource}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.ra.GFConnection
|
||||
* @see org.apache.geode.ra.GFConnectionFactory
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableGemFireAsLastResource
|
||||
* @see org.springframework.data.gemfire.config.annotation.GemFireAsLastResourceConfiguration
|
||||
* @see org.springframework.transaction.PlatformTransactionManager
|
||||
* @see org.springframework.transaction.annotation.EnableTransactionManagement
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class EnableGemFireAsLastResourceIntegrationTests {
|
||||
|
||||
private static List<SpringGemFireTransactionEvents> transactionEvents = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
transactionEvents.clear();
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext newApplicationContext(Class<?>... annotatedClasses) {
|
||||
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
applicationContext.registerShutdownHook();
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationIsCorrect() {
|
||||
|
||||
ConfigurableApplicationContext applicationContext =
|
||||
newApplicationContext(TestGemFireAsLastResourceConfiguration.class);
|
||||
|
||||
assertThat(applicationContext).isNotNull();
|
||||
|
||||
GemFireCache gemfireCache = applicationContext.getBean("gemfireCache", GemFireCache.class);
|
||||
|
||||
assertThat(gemfireCache).isNotNull();
|
||||
assertThat(gemfireCache.getCopyOnRead()).isTrue();
|
||||
|
||||
GemFireAsLastResourceConnectionAcquiringAspect connectionAcquiringAspect =
|
||||
applicationContext.getBean(GemFireAsLastResourceConnectionAcquiringAspect.class);
|
||||
|
||||
assertThat(connectionAcquiringAspect).isNotNull();
|
||||
assertThat(connectionAcquiringAspect.getOrder()).isEqualTo(3);
|
||||
|
||||
GemFireAsLastResourceConnectionClosingAspect connectionClosingAspect =
|
||||
applicationContext.getBean(GemFireAsLastResourceConnectionClosingAspect.class);
|
||||
|
||||
assertThat(connectionClosingAspect).isNotNull();
|
||||
assertThat(connectionClosingAspect.getOrder()).isEqualTo(1);
|
||||
}
|
||||
|
||||
private void transactionEventsForTransactionalServiceAreCorrect(
|
||||
Class<? extends TestTransactionalService> transactionalServiceType) {
|
||||
|
||||
ConfigurableApplicationContext applicationContext =
|
||||
newApplicationContext(TestSpringApplicationConfiguration.class);
|
||||
|
||||
assertThat(applicationContext).isNotNull();
|
||||
assertThat(applicationContext.containsBean(transactionalServiceType.getSimpleName())).isTrue();
|
||||
assertThat(transactionEvents).isEmpty();
|
||||
|
||||
GFConnectionFactory gemfireConnectionFactory = applicationContext.getBean(GFConnectionFactory.class);
|
||||
|
||||
assertThat(gemfireConnectionFactory).isNotNull();
|
||||
|
||||
GemFireAsLastResourceConnectionAcquiringAspect connectionAcquiringAspect =
|
||||
applicationContext.getBean(GemFireAsLastResourceConnectionAcquiringAspect.class);
|
||||
|
||||
assertThat(connectionAcquiringAspect).isNotNull();
|
||||
assertThat(connectionAcquiringAspect.getGemFireConnectionFactory()).isSameAs(gemfireConnectionFactory);
|
||||
|
||||
TestTransactionalService service =
|
||||
applicationContext.getBean(transactionalServiceType.getSimpleName(), transactionalServiceType);
|
||||
|
||||
assertThat(service).isNotNull();
|
||||
|
||||
service.doInTransactionCommits();
|
||||
|
||||
assertThat(transactionEvents).containsExactly(SpringGemFireTransactionEvents.BEGIN,
|
||||
SpringGemFireTransactionEvents.GET_CONNECTION,
|
||||
SpringGemFireTransactionEvents.TRANSACTION,
|
||||
SpringGemFireTransactionEvents.COMMIT,
|
||||
SpringGemFireTransactionEvents.CLOSE_CONNECTION);
|
||||
|
||||
transactionEvents.clear();
|
||||
|
||||
assertThat(transactionEvents).isEmpty();
|
||||
|
||||
try {
|
||||
service.doInTransactionRollsback();
|
||||
}
|
||||
catch (RuntimeException expected) {
|
||||
assertThat(expected).hasMessage("TEST");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
assertThat(transactionEvents).containsExactly(SpringGemFireTransactionEvents.BEGIN,
|
||||
SpringGemFireTransactionEvents.GET_CONNECTION,
|
||||
SpringGemFireTransactionEvents.TRANSACTION,
|
||||
SpringGemFireTransactionEvents.ROLLBACK,
|
||||
SpringGemFireTransactionEvents.CLOSE_CONNECTION);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void transactionEventsForTransactionalServiceClassAreCorrect() {
|
||||
transactionEventsForTransactionalServiceAreCorrect(TestTransactionalServiceClass.class);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void transactionEventsForTransactionalServiceMethodsAreCorrect() {
|
||||
transactionEventsForTransactionalServiceAreCorrect(TestTransactionalServiceMethods.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void missingEnableTransactionManagerAnnotationThrowsIllegalStateException() {
|
||||
try {
|
||||
newApplicationContext(TestMissingEnableTransactionManagementAnnotationConfiguration.class);
|
||||
}
|
||||
catch (BeanCreationException expected) {
|
||||
|
||||
assertThat(expected).hasMessageStartingWith(String.format("Error creating bean with name '%s'",
|
||||
GemFireAsLastResourceConfiguration.class.getName()));
|
||||
|
||||
assertThat(expected).hasCauseInstanceOf(IllegalStateException.class);
|
||||
|
||||
assertThat(expected.getCause()).hasMessage("The @EnableGemFireAsLastResource annotation may only be used"
|
||||
+ " on a Spring application @Configuration class that is also annotated with"
|
||||
+ " @EnableTransactionManagement having an explicit [order] set");
|
||||
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw (IllegalStateException) expected.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void missingEnableTransactionManagementOrderAttributeConfigurationThrowsIllegalArgumentException() {
|
||||
try {
|
||||
newApplicationContext(TestMissingEnableTransactionManagementOrderAttributeConfiguration.class);
|
||||
}
|
||||
catch (BeanCreationException expected) {
|
||||
|
||||
assertThat(expected).hasMessageStartingWith(String.format("Error creating bean with name '%s'",
|
||||
GemFireAsLastResourceConfiguration.class.getName()));
|
||||
|
||||
assertThat(expected).hasCauseInstanceOf(IllegalArgumentException.class);
|
||||
|
||||
assertThat(expected.getCause()).hasMessage("The @EnableTransactionManagement(order) attribute value"
|
||||
+ " [2147483647] must be explicitly set to a value other than Integer.MAX_VALUE or Integer.MIN_VALUE");
|
||||
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw (IllegalArgumentException) expected.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGemFireAsLastResource
|
||||
@EnableTransactionManagement(order = 2)
|
||||
static class TestGemFireAsLastResourceConfiguration {
|
||||
|
||||
@Bean("gemfireCache")
|
||||
GemFireCache mockGemFireCache() {
|
||||
|
||||
AtomicBoolean copyOnRead = new AtomicBoolean(false);
|
||||
|
||||
GemFireCache mockGemFireCache = mock(GemFireCache.class);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
copyOnRead.set(invocation.getArgument(0));
|
||||
return null;
|
||||
}).when(mockGemFireCache).setCopyOnRead(anyBoolean());
|
||||
|
||||
when(mockGemFireCache.getCopyOnRead()).thenAnswer(invocation -> copyOnRead.get());
|
||||
|
||||
return mockGemFireCache;
|
||||
}
|
||||
|
||||
@Bean
|
||||
GFConnectionFactory mockGemFireConnectionFactory() throws ResourceException {
|
||||
|
||||
GFConnectionFactory mockGemFireConnectionFactory = mock(GFConnectionFactory.class);
|
||||
|
||||
GFConnection mockGemFireConnection = mock(GFConnection.class);
|
||||
|
||||
when(mockGemFireConnectionFactory.getConnection()).thenAnswer(invocation -> {
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.GET_CONNECTION);
|
||||
return mockGemFireConnection;
|
||||
});
|
||||
|
||||
doAnswer(invocation -> transactionEvents.add(SpringGemFireTransactionEvents.CLOSE_CONNECTION))
|
||||
.when(mockGemFireConnection).close();
|
||||
|
||||
return mockGemFireConnectionFactory;
|
||||
}
|
||||
|
||||
@Bean("transactionManager")
|
||||
PlatformTransactionManager mockTransactionManager() {
|
||||
|
||||
PlatformTransactionManager mockTransactionManager = mock(PlatformTransactionManager.class);
|
||||
|
||||
when(mockTransactionManager.getTransaction(any(TransactionDefinition.class))).thenAnswer(invocation -> {
|
||||
|
||||
TransactionStatus mockTransactionStatus = mock(TransactionStatus.class);
|
||||
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.BEGIN);
|
||||
|
||||
return mockTransactionStatus;
|
||||
});
|
||||
|
||||
doAnswer(invocation -> transactionEvents.add(SpringGemFireTransactionEvents.COMMIT))
|
||||
.when(mockTransactionManager).commit(any(TransactionStatus.class));
|
||||
|
||||
doAnswer(invocation -> transactionEvents.add(SpringGemFireTransactionEvents.ROLLBACK))
|
||||
.when(mockTransactionManager).rollback(any(TransactionStatus.class));
|
||||
|
||||
return mockTransactionManager;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGemFireAsLastResource
|
||||
static class TestMissingEnableTransactionManagementAnnotationConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGemFireAsLastResource
|
||||
@EnableTransactionManagement
|
||||
static class TestMissingEnableTransactionManagementOrderAttributeConfiguration {
|
||||
|
||||
@Bean("transactionManager")
|
||||
PlatformTransactionManager mockTransactionManager() {
|
||||
return mock(PlatformTransactionManager.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(TestGemFireAsLastResourceConfiguration.class)
|
||||
static class TestSpringApplicationConfiguration {
|
||||
|
||||
@Bean("TestTransactionalServiceClass")
|
||||
TestTransactionalServiceClass testTransactionalServiceClass() {
|
||||
return new TestTransactionalServiceClass();
|
||||
}
|
||||
|
||||
@Bean("TestTransactionalServiceMethods")
|
||||
TestTransactionalServiceMethods testTransactionalServiceMethods() {
|
||||
return new TestTransactionalServiceMethods();
|
||||
}
|
||||
}
|
||||
|
||||
enum SpringGemFireTransactionEvents {
|
||||
|
||||
BEGIN,
|
||||
CLOSE_CONNECTION,
|
||||
COMMIT,
|
||||
GET_CONNECTION,
|
||||
ROLLBACK,
|
||||
TRANSACTION,
|
||||
|
||||
}
|
||||
|
||||
interface TestTransactionalService {
|
||||
|
||||
void doInTransactionCommits();
|
||||
|
||||
void doInTransactionRollsback();
|
||||
|
||||
}
|
||||
|
||||
@Service("TestTransactionalServiceClass")
|
||||
@Transactional
|
||||
static class TestTransactionalServiceClass implements TestTransactionalService {
|
||||
|
||||
public void doInTransactionCommits() {
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.TRANSACTION);
|
||||
}
|
||||
|
||||
public void doInTransactionRollsback() {
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.TRANSACTION);
|
||||
throw new RuntimeException("TEST");
|
||||
}
|
||||
}
|
||||
|
||||
@Service("TestTransactionalServiceMethods")
|
||||
static class TestTransactionalServiceMethods implements TestTransactionalService {
|
||||
|
||||
@Transactional
|
||||
public void doInTransactionCommits() {
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.TRANSACTION);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void doInTransactionRollsback() {
|
||||
transactionEvents.add(SpringGemFireTransactionEvents.TRANSACTION);
|
||||
throw new RuntimeException("TEST");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2017 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.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
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.when;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.apache.geode.ra.GFConnection;
|
||||
import org.apache.geode.ra.GFConnectionFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GemFireAsLastResourceConnectionAcquiringAspect}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionAcquiringAspect
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GemFireAsLastResourceConnectionAcquiringAspectUnitTests {
|
||||
|
||||
@Mock
|
||||
private Context mockContext;
|
||||
|
||||
@Mock
|
||||
private GFConnection mockGemFireConnection;
|
||||
|
||||
@Mock
|
||||
private GFConnectionFactory mockGemFireConnectionFactory;
|
||||
|
||||
@Mock
|
||||
private Logger mockLogger;
|
||||
|
||||
private GemFireAsLastResourceConnectionAcquiringAspect aspect;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
aspect = spy(new GemFireAsLastResourceConnectionAcquiringAspect());
|
||||
when(aspect.getLogger()).thenReturn(mockLogger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionAcquiringAspectHasLowerPriorityThanConnectionClosingAspect() {
|
||||
assertThat(aspect.getOrder()).isGreaterThan(new GemFireAsLastResourceConnectionClosingAspect().getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doConnectionFactoryGetConnectionReturnsConnection() throws ResourceException {
|
||||
|
||||
when(mockLogger.isTraceEnabled()).thenReturn(true);
|
||||
doReturn(mockGemFireConnectionFactory).when(aspect).resolveGemFireConnectionFactory();
|
||||
when(mockGemFireConnectionFactory.getConnection()).thenReturn(mockGemFireConnection);
|
||||
|
||||
aspect.doGemFireConnectionFactoryGetConnection();
|
||||
|
||||
assertThat(AbstractGemFireAsLastResourceAspectSupport.GemFireConnectionHolder.get().orElse(null))
|
||||
.isEqualTo(mockGemFireConnection);
|
||||
|
||||
verify(aspect, times(1)).resolveGemFireConnectionFactory();
|
||||
verify(aspect, times(1)).resolveGemFireJcaResourceAdapterJndiName();
|
||||
verify(mockGemFireConnectionFactory, times(1)).getConnection();
|
||||
verify(mockLogger, times(1))
|
||||
.trace(eq(String.format("Acquiring GemFire Connection from GemFire JCA ResourceAdapter registered at [%s]...",
|
||||
GemFireAsLastResourceConnectionAcquiringAspect.DEFAULT_GEMFIRE_JCA_RESOURCE_ADAPTER_JNDI_NAME)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveGemFireConnectionFactoryFromAutowiring() {
|
||||
|
||||
when(aspect.getGemFireConnectionFactory()).thenReturn(mockGemFireConnectionFactory);
|
||||
|
||||
assertThat(aspect.resolveGemFireConnectionFactory()).isSameAs(mockGemFireConnectionFactory);
|
||||
|
||||
verify(aspect, times(1)).getGemFireConnectionFactory();
|
||||
verify(aspect, never()).resolveGemFireJcaResourceAdapterJndiName();
|
||||
verify(aspect, never()).resolveContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveGemFireConnectionFactoryFromJndiContext() throws NamingException {
|
||||
|
||||
when(aspect.getGemFireConnectionFactory()).thenReturn(null);
|
||||
doReturn(mockContext).when(aspect).resolveContext();
|
||||
when(mockContext.lookup(anyString())).thenReturn(mockGemFireConnectionFactory);
|
||||
|
||||
assertThat(aspect.resolveGemFireConnectionFactory()).isEqualTo(mockGemFireConnectionFactory);
|
||||
|
||||
verify(aspect, times(1)).getGemFireConnectionFactory();
|
||||
verify(aspect, times(1)).resolveGemFireJcaResourceAdapterJndiName();
|
||||
verify(aspect, times(1)).resolveContext();
|
||||
verify(mockContext, times(1))
|
||||
.lookup(eq(GemFireAsLastResourceConnectionAcquiringAspect.DEFAULT_GEMFIRE_JCA_RESOURCE_ADAPTER_JNDI_NAME));
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void resolveGemFireConnectionFactoryFromJndiContextThrowsNamingException() throws NamingException {
|
||||
|
||||
when(aspect.getGemFireConnectionFactory()).thenReturn(null);
|
||||
when(aspect.getGemFireJcaResourceAdapterJndiName()).thenReturn("java:comp/gemfire/jca");
|
||||
doReturn(mockContext).when(aspect).resolveContext();
|
||||
when(mockContext.lookup(anyString())).thenThrow(new NamingException("TEST"));
|
||||
|
||||
try {
|
||||
aspect.resolveGemFireConnectionFactory();
|
||||
}
|
||||
catch (RuntimeException expected) {
|
||||
|
||||
assertThat(expected).hasMessage(
|
||||
"Failed to resolve a GFConnectionFactory from the configured JNDI context name [java:comp/gemfire/jca]");
|
||||
|
||||
assertThat(expected).hasCauseInstanceOf(NamingException.class);
|
||||
assertThat(expected.getCause()).hasMessage("TEST");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(aspect, times(1)).getGemFireConnectionFactory();
|
||||
verify(aspect, times(1)).resolveGemFireJcaResourceAdapterJndiName();
|
||||
verify(aspect, times(1)).resolveContext();
|
||||
verify(mockContext, times(1)).lookup(eq("java:comp/gemfire/jca"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2017 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.data.gemfire.config.annotation.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.apache.geode.ra.GFConnection;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GemFireAsLastResourceConnectionClosingAspect}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionClosingAspect
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GemFireAsLastResourceConnectionClosingAspectUnitTests {
|
||||
|
||||
private GemFireAsLastResourceConnectionClosingAspect aspect;
|
||||
|
||||
@Mock
|
||||
private GFConnection mockGemFireConnection;
|
||||
|
||||
@Mock
|
||||
private Logger mockLogger;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
aspect = spy(new GemFireAsLastResourceConnectionClosingAspect());
|
||||
when(aspect.getLogger()).thenReturn(mockLogger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionClosingAspectHasHigherPriorityThanConnectionAcquiringAspect() {
|
||||
assertThat(aspect.getOrder()).isLessThan(new GemFireAsLastResourceConnectionAcquiringAspect().getOrder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doGemFireConnectionCloseIsSuccessful() throws ResourceException {
|
||||
|
||||
AbstractGemFireAsLastResourceAspectSupport.GemFireConnectionHolder.of(mockGemFireConnection);
|
||||
|
||||
when(mockLogger.isTraceEnabled()).thenReturn(true);
|
||||
|
||||
aspect.doGemFireConnectionClose();;
|
||||
|
||||
verify(mockGemFireConnection, times(1)).close();
|
||||
verify(mockLogger, times(1)).trace(eq("Closing GemFire Connection..."));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user