Refactor ResourceCapableCacheDataImporterExporter to not fail on missing Resources for import and rather log a warning.
It is valid that a Resource may not exist for a Region on import since the user may not want to import any data into the Region. Resolves gh-92.
This commit is contained in:
@@ -80,6 +80,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.context.ResourceLoaderAware
|
||||
* @see org.springframework.expression.Expression
|
||||
@@ -611,7 +612,7 @@ public abstract class ResourceCapableCacheDataImporterExporter extends AbstractC
|
||||
boolean writable = resource.filter(ResourceUtils::isWritable).isPresent();
|
||||
|
||||
if (!writable) {
|
||||
getLogger().warn("WARNING! Resource [{}] for Region [{}] is not writable",
|
||||
getLogger().warn("Resource [{}] for Region [{}] is not writable",
|
||||
resourceLocation, region.getFullPath());
|
||||
}
|
||||
|
||||
@@ -624,7 +625,7 @@ public abstract class ResourceCapableCacheDataImporterExporter extends AbstractC
|
||||
@Override
|
||||
protected @Nullable Resource onMissingResource(@Nullable Resource resource, @NonNull String location) {
|
||||
|
||||
getLogger().warn("WARNING! Resource [{}] at location [{}] does not exist; will try to create it on export",
|
||||
getLogger().warn("Resource [{}] at location [{}] does not exist; will try to create it on export",
|
||||
ResourceUtils.nullSafeGetDescription(resource), location);
|
||||
|
||||
return resource;
|
||||
@@ -674,16 +675,29 @@ public abstract class ResourceCapableCacheDataImporterExporter extends AbstractC
|
||||
|
||||
Optional<Resource> resource = resolve(resourceLocation);
|
||||
|
||||
Assert.state(resource.isPresent(), () -> String.format("Resource [%1$s] for Region [%2$s] does not exist",
|
||||
resourceLocation, region.getFullPath()));
|
||||
boolean exists = resource.isPresent();
|
||||
boolean readable = exists && resource.filter(Resource::isReadable).isPresent();
|
||||
|
||||
boolean readable = resource.filter(Resource::isReadable).isPresent();
|
||||
|
||||
Assert.state(readable, () -> String.format("Resource [%1$s] for Region [%2$s] is not readable",
|
||||
resourceLocation, region.getFullPath()));
|
||||
if (!exists) {
|
||||
getLogger().warn("Resource [{}] for Region [{}] could not be found; skipping import for Region",
|
||||
resourceLocation, region.getFullPath());
|
||||
}
|
||||
else {
|
||||
Assert.state(readable, () -> String.format("Resource [%1$s] for Region [%2$s] is not readable",
|
||||
resourceLocation, region.getFullPath()));
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Nullable @Override
|
||||
protected Resource onMissingResource(@Nullable Resource resource, @NonNull String location) {
|
||||
|
||||
getLogger().warn("Resource [{}] at location [{}] does not exist; skipping import",
|
||||
ResourceUtils.nullSafeGetDescription(resource), location);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.slf4j.Logger;
|
||||
* Unit Tests for {@link ResourceCapableCacheDataImporterExporter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.io.File
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.Region
|
||||
@@ -76,7 +77,9 @@ import org.slf4j.Logger;
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see org.springframework.core.io.WritableResource
|
||||
* @see org.springframework.expression.spel.standard.SpelExpressionParser
|
||||
* @see org.springframework.geode.core.io.ResourceReader
|
||||
* @see org.springframework.geode.core.io.ResourceResolver
|
||||
* @see org.springframework.geode.core.io.ResourceWriter
|
||||
* @see org.springframework.geode.data.support.ResourceCapableCacheDataImporterExporter
|
||||
* @since 1.3.1
|
||||
@@ -659,10 +662,10 @@ public class ResourceCapableCacheDataImporterExporterUnitTests {
|
||||
verify(mockResource, times(1)).isWritable();
|
||||
verify(mockResource, times(1)).getDescription();
|
||||
verify(mockLogger, times(1))
|
||||
.warn(eq("WARNING! Resource [{}] at location [{}] does not exist; will try to create it on export"),
|
||||
.warn(eq("Resource [{}] at location [{}] does not exist; will try to create it on export"),
|
||||
eq("MOCK"), eq("/path/to/resource.xml"));
|
||||
verify(mockLogger, times(1))
|
||||
.warn(eq("WARNING! Resource [{}] for Region [{}] is not writable"), eq("/path/to/resource.xml"),
|
||||
.warn(eq("Resource [{}] for Region [{}] is not writable"), eq("/path/to/resource.xml"),
|
||||
eq("/Example"));
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
verifyNoMoreInteractions(mockLogger, mockRegion, mockResource, mockResourceLoader);
|
||||
@@ -683,6 +686,9 @@ public class ResourceCapableCacheDataImporterExporterUnitTests {
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(exportResourceResolver, never()).resolve(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -717,56 +723,68 @@ public class ResourceCapableCacheDataImporterExporterUnitTests {
|
||||
eq(ResourceCapableCacheDataImporterExporter.CACHE_DATA_IMPORT_RESOURCE_LOCATION_PROPERTY_NAME));
|
||||
verify(importResourceResolver, times(1)).resolve(eq("/path/to/resource.json"));
|
||||
verify(mockResource, times(1)).isReadable();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
verifyNoMoreInteractions(mockResource);
|
||||
verifyNoInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void resolveImportResourceWhenResourceIsNotPresentThrowsIllegalStateException() {
|
||||
@Test
|
||||
public void resolveImportResourceWhenResourceIsMissingLogsWarningsReturnsEmptyOptional() {
|
||||
|
||||
Logger mockLogger = mock(Logger.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn("/Example").when(mockRegion).getFullPath();
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
ResourceLoader mockResourceLoader = mock(ResourceLoader.class);
|
||||
|
||||
AbstractImportResourceResolver importResourceResolver = spy(new TestImportResourceResolver());
|
||||
|
||||
importResourceResolver.setResourceLoader(mockResourceLoader);
|
||||
|
||||
doReturn("/Example").when(mockRegion).getFullPath();
|
||||
doReturn(false).when(mockResource).exists();
|
||||
doReturn("MOCK").when(mockResource).getDescription();
|
||||
doReturn(mockResource).when(mockResourceLoader).getResource(eq("/path/to/resource.json"));
|
||||
doReturn(mockLogger).when(importResourceResolver).getLogger();
|
||||
doReturn("/path/to/resource.json")
|
||||
.when(importResourceResolver).getResourceLocation(eq(mockRegion),
|
||||
eq(ResourceCapableCacheDataImporterExporter.CACHE_DATA_IMPORT_RESOURCE_LOCATION_PROPERTY_NAME));
|
||||
|
||||
doReturn(Optional.empty()).when(importResourceResolver).resolve(eq("/path/to/resource.json"));
|
||||
assertThat(importResourceResolver.resolve(mockRegion).orElse(null)).isNull();
|
||||
|
||||
try {
|
||||
importResourceResolver.resolve(mockRegion);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Resource [/path/to/resource.json] for Region [/Example] does not exist");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(importResourceResolver, times(1)).getResourceLocation(eq(mockRegion),
|
||||
eq(ResourceCapableCacheDataImporterExporter.CACHE_DATA_IMPORT_RESOURCE_LOCATION_PROPERTY_NAME));
|
||||
verify(importResourceResolver, times(1)).resolve(eq("/path/to/resource.json"));
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
verify(importResourceResolver, times(1)).getResourceLocation(eq(mockRegion),
|
||||
eq(ResourceCapableCacheDataImporterExporter.CACHE_DATA_IMPORT_RESOURCE_LOCATION_PROPERTY_NAME));
|
||||
verify(importResourceResolver, times(1)).resolve(eq("/path/to/resource.json"));
|
||||
verify(mockResourceLoader, times(1)).getResource(eq("/path/to/resource.json"));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verify(mockResource, times(1)).getDescription();
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
verify(mockLogger, times(1))
|
||||
.warn(eq("Resource [{}] at location [{}] does not exist; skipping import"),
|
||||
eq("MOCK"), eq("/path/to/resource.json"));
|
||||
verify(mockLogger, times(1))
|
||||
.warn(eq("Resource [{}] for Region [{}] could not be found; skipping import for Region"),
|
||||
eq("/path/to/resource.json"), eq("/Example"));
|
||||
verifyNoMoreInteractions(mockLogger, mockRegion, mockResource, mockResourceLoader);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void resolveImportResourceWhenResourceIsNotReadableThrowsIllegalStateException() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
Logger mockLogger = mock(Logger.class);
|
||||
|
||||
doReturn("/Example").when(mockRegion).getFullPath();
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
AbstractImportResourceResolver importResourceResolver = spy(new TestImportResourceResolver());
|
||||
|
||||
doReturn("/Example").when(mockRegion).getFullPath();
|
||||
|
||||
doReturn(false).when(mockResource).isReadable();
|
||||
|
||||
AbstractImportResourceResolver importResourceResolver = spy(new TestImportResourceResolver());
|
||||
doReturn(mockLogger).when(importResourceResolver).getLogger();
|
||||
|
||||
doReturn("/path/to/resource.json")
|
||||
.when(importResourceResolver).getResourceLocation(eq(mockRegion),
|
||||
@@ -791,13 +809,14 @@ public class ResourceCapableCacheDataImporterExporterUnitTests {
|
||||
verify(mockResource, times(1)).isReadable();
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
verifyNoMoreInteractions(mockRegion, mockResource);
|
||||
verifyNoInteractions(mockLogger);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void resolveImportResourceWithNullRegionThrowsIllegalArgumentException() {
|
||||
|
||||
AbstractImportResourceResolver importResourceResolver = new TestImportResourceResolver();
|
||||
AbstractImportResourceResolver importResourceResolver = spy(new TestImportResourceResolver());
|
||||
|
||||
try {
|
||||
importResourceResolver.resolve((Region<?, ?>) null);
|
||||
@@ -809,6 +828,9 @@ public class ResourceCapableCacheDataImporterExporterUnitTests {
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(importResourceResolver, never()).resolve(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user