Normally it's safe to change type from array to list, but it's not for Resource
.
@Value("${resources:file:/tmp/*.text}")
Resource[] resourceArray; // multiple FileSystemResource
@Value("${resources:file:/tmp/*.text}")
List<Resource> resourceList; // only one FileUrlResource
here is the full test
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import test.ResourceInjectionTest.TestConfiguration;
@RunWith(SpringRunner.class)
@TestPropertySource(properties = { "resources=file:/tmp/*.text" })
@ContextConfiguration(classes = TestConfiguration.class)
public class ResourceInjectionTest {
private static File[] files;
@Autowired
private TestConfiguration testConfiguration;
@BeforeClass
public static void setup() throws IOException {
files = new File[2];
files[0] = new File("/tmp", "a.text");
files[1] = new File("/tmp", "b.text");
for (File f : files)
f.createNewFile();
}
@AfterClass
public static void cleanup() {
for (File f : files)
f.delete();
}
@Test
public void testInjection() {
assertEquals(2, testConfiguration.resourceArray.length); // two FileSystemResource
assertEquals(2, testConfiguration.resourceList.size()); // one FileUrlResource
}
static class TestConfiguration {
@Value("${resources}")
Resource[] resourceArray;
@Value("${resources}")
List<Resource> resourceList;
}
}
Comment From: sbrannen
Thanks for raising the issue.
I've been able to reproduce this against master
using the following simplified test case.
package org.springframework.test;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig
class ResourceInjectionTests {
@BeforeAll
static void setup() throws IOException {
List<File> files = Arrays.asList(new File("/tmp", "a.text"), new File("/tmp", "b.text"));
for (File file : files) {
file.createNewFile();
file.deleteOnExit();
}
}
@Value("file:/tmp/*.text")
Resource[] resourceArray;
@Value("file:/tmp/*.text")
List<Resource> resourceList;
@Test
void testInjection() {
assertThat(resourceArray).as("array").hasSize(2); // two FileSystemResource
assertThat(resourceList).as("list").hasSize(2); // one FileUrlResource
}
@Configuration
static class Config {
}
}
I assume it has something to do with the fact that a ResourceArrayPropertyEditor
is probably used to handle the array; whereas, the list is likely handled using a mechanism that does not treat the string as a resource pattern.
Comment From: sbrannen
Indeed, the difference is that a ResourceArrayPropertyEditor
is used to handle the array case; whereas, a CustomCollectionEditor
is used to handle the list case.
The former internally uses a ResourcePatternResolver
to expand the pattern into the 2 files in the filesystem; whereas, the latter simply treats the pattern as a simple string without expansion.
Comment From: encircled
This reminds me that CustomCollectionEditor
does not support parsing of multiple values either (like @Value("1,2,3") List<Integer> ints
).
Is that intentional?
Comment From: sbrannen
This reminds me that
CustomCollectionEditor
does not support parsing of multiple values either (like@Value("1,2,3") List<Integer> ints
).Is that intentional?
@encircled, That is currently not supported, but feel free to open a new issue to start a discussion on the topic.
Comment From: encircled
Nevermind my prev comment, I just realized it is actually possible to do so by adding the ConversionService
bean to the context.
I can fix the initial issue if needed.
Comment From: sbrannen
Team Decision: Assigned to 5.x backlog as a potential enhancement.