question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Serving static resources from graalvm native-image

See original GitHub issue

I 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:closed
  • Created 2 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ttddyycommented, Oct 20, 2021

@bojanv55 @sdeleuze

Interestingly, my repro project failed with GraalVM 21.2.0 but passed with 21.3.0.

So, the combination it works is:

  • Spring Boot 2.6.0-SNAPSHOT
  • Spring Native 0.11.0-SNAPSHOT (custom resource-config.json is no longer required.)
  • Graalvm 21.3.0
0reactions
sdeleuzecommented, Oct 20, 2021

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Native Image Options - GraalVM
The native-image builder needs to provide the classpath for all classes using ... -cp is followed by a list of directories or JAR...
Read more >
Static and Mostly Static Images - GraalVM
With GraalVM Native Image you can create static or mostly static images, depending on the purposes. Static native images are statically linked binaries...
Read more >
Native Image Options - GraalVM
Run native-image --help to get the options overview. Depending on the GraalVM edition, the commands to the native-image builder may differ. @argument files...
Read more >
Native Image - GraalVM
This executable includes the application classes, classes from its dependencies, runtime library classes, and statically linked native code from JDK.
Read more >
Accessing Resources in Native Images - GraalVM
By default, the native-image tool will not integrate any of the resources that are ... Scanner; public class Fortune { private static final...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found