Skip to content

Commit 60548aa

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 60548aa

File tree

2 files changed

+57
-18
lines changed

2 files changed

+57
-18
lines changed

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

+36-18
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,32 @@ 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(
232+
this.servletContextResourceClass = resolveClassName(SERVLET_CONTEXT_RESOURCE_CLASS_NAME,
229233
resourceLoader.getClass().getClassLoader());
234+
this.filteredReactiveWebContextResourceClass = resolveClassName(
235+
FILTERED_REACTIVE_WEB_CONTEXT_RESOURCE_CLASS_NAME, resourceLoader.getClass().getClassLoader());
230236
}
231237

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);
238+
@Override
239+
public ClassLoader getClassLoader() {
240+
return this.resourceLoader.getClassLoader();
237241
}
238242

239243
@Override
@@ -247,24 +251,38 @@ public Resource getResource(String location) {
247251
}
248252
}
249253
Resource resource = this.resourceLoader.getResource(location);
250-
if (this.preferFileResolution
251-
&& (isClassPathResourceByPath(location, resource) || isServletResource(resource))) {
252-
resource = new ApplicationResource(location);
254+
if (shouldUseFileResolution(location, resource)) {
255+
return new ApplicationResource(location);
253256
}
254257
return resource;
255258
}
256259

260+
private boolean shouldUseFileResolution(String location, Resource resource) {
261+
if (!this.preferFileResolution) {
262+
return false;
263+
}
264+
return isClassPathResourceByPath(location, resource) || isServletContextResource(resource)
265+
|| isFilteredReactiveWebContextResource(resource);
266+
}
267+
257268
private boolean isClassPathResourceByPath(String location, Resource resource) {
258269
return (resource instanceof ClassPathResource) && !location.startsWith(CLASSPATH_URL_PREFIX);
259270
}
260271

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

265-
@Override
266-
public ClassLoader getClassLoader() {
267-
return this.resourceLoader.getClassLoader();
276+
private boolean isFilteredReactiveWebContextResource(Resource resource) {
277+
return (this.filteredReactiveWebContextResourceClass != null)
278+
&& this.filteredReactiveWebContextResourceClass.isInstance(resource);
279+
}
280+
281+
private static Class<?> resolveClassName(String clazz, ClassLoader classLoader) {
282+
if (!ClassUtils.isPresent(clazz, classLoader)) {
283+
return null;
284+
}
285+
return ClassUtils.resolveClassName(clazz, classLoader);
268286
}
269287

270288
}

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)