Skip to content

Commit e0b9ebb

Browse files
committed
Update ApplicationResourceLoader to support FilteredReactiveWebContextResource
Prior to this update, FilteredReactiveWebContextResource was not considered when preferFileResolution was set to true. This commit updates the ApplicationResourceLoader to include support for FilteredReactiveWebContextResource. Signed-off-by: Dmytro Nosan <dimanosan@gmail.com>
1 parent d92551f commit e0b9ebb

File tree

2 files changed

+66
-19
lines changed

2 files changed

+66
-19
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ApplicationResourceLoader.java

+45-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -132,8 +132,8 @@ public static ResourceLoader get(ResourceLoader resourceLoader) {
132132
* class loader at the time this call is made.
133133
* @param resourceLoader the delegate resource loader
134134
* @param preferFileResolution if file based resolution is preferred over
135-
* {@code ServletContextResource} or {@link ClassPathResource} when no resource prefix
136-
* is provided.
135+
* {@code ServletContextResource}, {@code FilteredReactiveWebContextResource} or
136+
* {@link ClassPathResource} when no resource prefix is provided.
137137
* @return a {@link ResourceLoader} instance
138138
* @since 3.4.1
139139
*/
@@ -212,28 +212,31 @@ private static class ProtocolResolvingResourceLoader implements ResourceLoader {
212212

213213
private static final String SERVLET_CONTEXT_RESOURCE_CLASS_NAME = "org.springframework.web.context.support.ServletContextResource";
214214

215+
private static final String FILTERED_REACTIVE_WEB_CONTEXT_RESOURCE_CLASS_NAME = "org.springframework.boot.web.reactive.context.FilteredReactiveWebContextResource";
216+
215217
private final ResourceLoader resourceLoader;
216218

217219
private final List<ProtocolResolver> protocolResolvers;
218220

219221
private final boolean preferFileResolution;
220222

221-
private Class<?> servletContextResourceClass;
223+
private final Class<?> servletContextResourceClass;
224+
225+
private final Class<?> filteredReactiveWebContextResourceClass;
222226

223227
ProtocolResolvingResourceLoader(ResourceLoader resourceLoader, List<ProtocolResolver> protocolResolvers,
224228
boolean preferFileResolution) {
225229
this.resourceLoader = resourceLoader;
226230
this.protocolResolvers = protocolResolvers;
227231
this.preferFileResolution = preferFileResolution;
228-
this.servletContextResourceClass = resolveServletContextResourceClass(
229-
resourceLoader.getClass().getClassLoader());
232+
this.servletContextResourceClass = resolveServletContextResourceClass(resourceLoader);
233+
this.filteredReactiveWebContextResourceClass = resolveFilteredReactiveWebContextResourceClass(
234+
resourceLoader);
230235
}
231236

232-
private static Class<?> resolveServletContextResourceClass(ClassLoader classLoader) {
233-
if (!ClassUtils.isPresent(SERVLET_CONTEXT_RESOURCE_CLASS_NAME, classLoader)) {
234-
return null;
235-
}
236-
return ClassUtils.resolveClassName(SERVLET_CONTEXT_RESOURCE_CLASS_NAME, classLoader);
237+
@Override
238+
public ClassLoader getClassLoader() {
239+
return this.resourceLoader.getClassLoader();
237240
}
238241

239242
@Override
@@ -247,24 +250,47 @@ public Resource getResource(String location) {
247250
}
248251
}
249252
Resource resource = this.resourceLoader.getResource(location);
250-
if (this.preferFileResolution
251-
&& (isClassPathResourceByPath(location, resource) || isServletResource(resource))) {
252-
resource = new ApplicationResource(location);
253+
if (shouldUseFileResolution(location, resource)) {
254+
return new ApplicationResource(location);
253255
}
254256
return resource;
255257
}
256258

259+
private boolean shouldUseFileResolution(String location, Resource resource) {
260+
if (!this.preferFileResolution) {
261+
return false;
262+
}
263+
return isClassPathResourceByPath(location, resource) || isServletContextResource(resource)
264+
|| isFilteredReactiveWebContextResource(resource);
265+
}
266+
257267
private boolean isClassPathResourceByPath(String location, Resource resource) {
258268
return (resource instanceof ClassPathResource) && !location.startsWith(CLASSPATH_URL_PREFIX);
259269
}
260270

261-
private boolean isServletResource(Resource resource) {
262-
return this.servletContextResourceClass != null && this.servletContextResourceClass.isInstance(resource);
271+
private boolean isServletContextResource(Resource resource) {
272+
return (this.servletContextResourceClass != null) && this.servletContextResourceClass.isInstance(resource);
263273
}
264274

265-
@Override
266-
public ClassLoader getClassLoader() {
267-
return this.resourceLoader.getClassLoader();
275+
private boolean isFilteredReactiveWebContextResource(Resource resource) {
276+
return (this.filteredReactiveWebContextResourceClass != null)
277+
&& this.filteredReactiveWebContextResourceClass.isInstance(resource);
278+
}
279+
280+
private static Class<?> resolveServletContextResourceClass(ResourceLoader resourceLoader) {
281+
return resolveClassName(SERVLET_CONTEXT_RESOURCE_CLASS_NAME, resourceLoader.getClass().getClassLoader());
282+
}
283+
284+
private static Class<?> resolveFilteredReactiveWebContextResourceClass(ResourceLoader resourceLoader) {
285+
return resolveClassName(FILTERED_REACTIVE_WEB_CONTEXT_RESOURCE_CLASS_NAME,
286+
resourceLoader.getClass().getClassLoader());
287+
}
288+
289+
private static Class<?> resolveClassName(String clazz, ClassLoader classLoader) {
290+
if (!ClassUtils.isPresent(clazz, classLoader)) {
291+
return null;
292+
}
293+
return ClassUtils.resolveClassName(clazz, classLoader);
268294
}
269295

270296
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/io/ApplicationResourceLoaderTests.java

+21
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
3131
import org.springframework.boot.testsupport.classpath.resources.WithResource;
32+
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
3233
import org.springframework.core.io.ByteArrayResource;
3334
import org.springframework.core.io.ClassPathResource;
3435
import org.springframework.core.io.DefaultResourceLoader;
@@ -37,6 +38,7 @@
3738
import org.springframework.core.io.ResourceLoader;
3839
import org.springframework.core.io.support.SpringFactoriesLoader;
3940
import org.springframework.mock.web.MockServletContext;
41+
import org.springframework.util.ClassUtils;
4042
import org.springframework.web.context.support.ServletContextResource;
4143
import org.springframework.web.context.support.ServletContextResourceLoader;
4244

@@ -209,6 +211,25 @@ void getResourceWithPreferFileResolutionWhenPathWithServletContextResource() thr
209211
assertThat(regularLoader.getResource("src/main/resources/a-file")).isInstanceOf(ServletContextResource.class);
210212
}
211213

214+
@Test
215+
void getResourceWhenFilteredReactiveWebContextResourceWithPreferFileResolution() throws Exception {
216+
ResourceLoader resourceLoader = ApplicationResourceLoader
217+
.get(new AnnotationConfigReactiveWebApplicationContext(), true);
218+
Resource resource = resourceLoader.getResource("src/main/resources/a-file");
219+
assertThat(resource).isInstanceOf(FileSystemResource.class);
220+
assertThat(resource.getFile().getAbsoluteFile())
221+
.isEqualTo(new File("src/main/resources/a-file").getAbsoluteFile());
222+
}
223+
224+
@Test
225+
void getResourceWhenFilteredReactiveWebContextResource() {
226+
ResourceLoader resourceLoader = ApplicationResourceLoader
227+
.get(new AnnotationConfigReactiveWebApplicationContext(), false);
228+
Resource resource = resourceLoader.getResource("src/main/resources/a-file");
229+
assertThat(resource).isInstanceOf(ClassUtils.resolveClassName(
230+
"org.springframework.boot.web.reactive.context.FilteredReactiveWebContextResource", null));
231+
}
232+
212233
@Test
213234
void getClassLoaderReturnsDelegateClassLoader() {
214235
ClassLoader classLoader = new TestClassLoader(this::useTestProtocolResolversFactories);

0 commit comments

Comments
 (0)