Serving static resources from graalvm native-image
See original GitHub issueI put my index.html
into resources/public
folder, and when running the application (from IDE, or as a fatJAR), everything works as expected when I go to http://localhost:8080/
-> the index.html
gets served to the browser.
The problem arises when I want to use these resources from inside native-image packed .exe file on my Windows machine (using spring-native).
I packed the file properly using declaration inside resource-config.json
as:
{
"resources": [
{
"pattern": "\\Qpublic/index.html\\E"
}
],
"bundles": []
}
But the http://localhost:8080/
page is not serving index.html
out of the box.
The only way, how I currently hardcoded this to show-up is using this code:
@Configuration
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class Config implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
ResourceResolver resolver = new StreamResResolver();
registry
.addResourceHandler("/**")
.addResourceLocations(
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/")
.resourceChain(false)
.addResolver(resolver);
}
public class StreamResResolver implements ResourceResolver {
@Override
public Resource resolveResource(
HttpServletRequest request,
String requestPath,
List<? extends Resource> locations,
ResourceResolverChain chain) {
Resource resource = resolve(requestPath, locations);
if (resource != null) {
return resource;
}
// try next in chain
resource = chain.resolveResource(request, requestPath, locations);
return resource;
}
@Override
public String resolveUrlPath(
String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain) {
return resourcePath;
}
private Resource resolve(String requestPath, List<? extends Resource> locations) {
try {
URI uri = new URI("static/" + requestPath);
return new ByteArrayResource2(
WebMvcConfig.class
.getClassLoader()
.getResourceAsStream(uri.getPath())
.readAllBytes(),
requestPath);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}
public class ByteArrayResource2 extends ByteArrayResource {
private String filename;
public ByteArrayResource2(byte[] byteArray, String filename) {
super(byteArray);
this.filename = filename;
}
@Override
public String getFilename() {
return this.filename;
}
@Override
public long lastModified() {
return 0;
}
}
}
Is there something similar to the code above already included in the Spring? I basically have to load the resources using getResourceAsStream
in order to be able to read that stuff from native-image binary.
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (4 by maintainers)
@bojanv55 @sdeleuze
Interestingly, my repro project failed with GraalVM
21.2.0
but passed with21.3.0
.So, the combination it works is:
2.6.0-SNAPSHOT
0.11.0-SNAPSHOT
(customresource-config.json
is no longer required.)21.3.0
I have refined the native configuration and added related tests via https://github.com/spring-projects-experimental/spring-native/commit/84bdde3c17608e2302a2a1e2daaaf4af771a4e8d to catch such breakage as part of https://github.com/spring-projects-experimental/spring-native/issues/1128, but I can’t reproduce the issue with Spring Boot latest snapshots.
I will close that issue, please comment on https://github.com/spring-projects-experimental/spring-native/issues/1128 if you still see errors with Boot
2.6.0-SNAPSHOT
with a repro.