I am not sure this is more suited for Spring-Boot or Spring Core, but I think it would be beneficial to allow resources to be defined as plain strings.
The idea of Resource is abstracting a resource, whether it comes from a file, an url, etc.. so why not plain text? That way we allow the user passing a file with "foobar" but also the content itself, which would be impossible now
Perhaps something like
my-resource-binded-property: "raw:file_content"
(where "raw" could be a keyword prefix like "classpath:", or "bare:" or "string:")
Comment From: wilkinsona
Thanks for the suggestion, @nightswimmings. You can achieve this today without too much code by plugging in your own ProtocolResolver. Here's an example that shows a configuration properties bound Resource that's configured using a string with a custom prefix:
package com.example.demo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StreamUtils;
@SpringBootApplication
@ConfigurationProperties("example")
public class Gh28714Application {
private Resource resource;
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
public static void main(String[] args) throws IOException {
SpringApplication app = new SpringApplication(Gh28714Application.class);
app.addInitializers((context) -> context.addProtocolResolver(new StringProtocolResolver()));
Resource resource = app.run("--example.resource=string:a resource configured via a string").getBean(Gh28714Application.class).getResource();
System.out.println(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8));
}
static class StringProtocolResolver implements ProtocolResolver {
private static final String STRING_PROTOCOL_PREFIX = "string:";
@Override
public Resource resolve(String location, ResourceLoader resourceLoader) {
if (location.startsWith(STRING_PROTOCOL_PREFIX)) {
return new ByteArrayResource(
location.substring(STRING_PROTOCOL_PREFIX.length()).getBytes(StandardCharsets.UTF_8));
}
return null;
}
}
}
An ApplicationContextInitializer can be registered via spring.factories so this could be implemented in a way that's largely transparent to the application. We'll keep this open to consider adding something like this to Boot itself. In the meantime, hopefully the above will be of use.
Comment From: nightswimmings
Amazing, thanks @wilkinsona !
Comment From: sysmat
It is amazing