1

I have spring boot application, it consists of 2 modules: frontend and spring boot app project (frontend is gradle dependency of spring boot app).

If I run gradle bootRun app starts and works correctly, then I change something, gradle rebuilds project and replaces frontend.jar. Frontend contains static resources only. They are added in classpath and spring can serve requests for those static files. After replacing frontend.jar by build and auto restart spring app resources cannot be load, zip errors occured, they described in my previous question.

I debug app, deep inside java internal classes, and found that frontend.jar cached in JarFileFactory:

private JarFile getCachedJarFile(URL url) {
    assert Thread.holdsLock(instance);
    JarFile result = fileCache.get(urlKey(url)); // <- fileCache contains my frontend.jar
    ...
}

fileCache contains my jar. In debug I try to disable caching for this file in URLConnection:

   protected URLConnection(URL url) {
    this.url = url;
    if (url == null) {
        this.useCaches = defaultUseCaches;
    } else {
        this.useCaches = getDefaultUseCaches(url.getProtocol()); // <- here I change this.useCaches to false in debugger
    }
}

After disabling caching for this file current request works fine. Next request (if I do not change useCaches in debugger) will fail with same error.

But I don't find way to disable cache for my jars from my app (or make one-time remove from cache when app reloaded).

How to clean jar cache for app properly? Or force not to use cache for my jars? Or configure gradle when develop use files on disk directly, not in jar?

Alex T
  • 2,067
  • 4
  • 20
  • 27

1 Answers1

0

I found this solution:

@Component
class StaticResourcesPathProviderComponent {
    @Bean
    @Profile("dev")
    fun getResourcesPathProviderDev() : StaticResourcesPathProvider {
        return object : StaticResourcesPathProvider {
            override fun GetStaticResourcesPath(): String {
                var springAppPath = File(".").getAbsolutePath()

                return "file:///$springAppPath/../frontend-react-components/build/";
        }
    }
}

    @Bean
    @Profile("!dev")
    fun getResourcesPathProvider() : StaticResourcesPathProvider {
        return object : StaticResourcesPathProvider {
            override fun GetStaticResourcesPath(): String {
                return "classpath:/static/";
            }
        }
    }
}

Next, I use provided bean via @Autowired attribute in WebmvcConfigurer:

override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
    super.addResourceHandlers(registry)

    var path = staticResourcesPathProvider?.GetStaticResourcesPath()

    registry.addResourceHandler("/static/**")
            .addResourceLocations(path)
}

So, in dev environment simple use files directly. If you knows how to reload jar, or more friendly solution - welcome :)

Alex T
  • 2,067
  • 4
  • 20
  • 27