Merge branch '5.3.x' into main
This commit is contained in:
		
						commit
						28a497f3b3
					
				| 
						 | 
					@ -65,7 +65,7 @@ configure(allprojects) { project ->
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			dependency "io.reactivex.rxjava3:rxjava:3.1.1"
 | 
								dependency "io.reactivex.rxjava3:rxjava:3.1.1"
 | 
				
			||||||
			dependency "io.smallrye.reactive:mutiny:1.0.0"
 | 
								dependency "io.smallrye.reactive:mutiny:1.1.1"
 | 
				
			||||||
			dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
 | 
								dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			dependency "com.fasterxml:aalto-xml:1.3.0"
 | 
								dependency "com.fasterxml:aalto-xml:1.3.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2020 the original author or authors.
 | 
					 * Copyright 2002-2021 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -96,7 +96,9 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<String> locationValues = new ArrayList<>(4);
 | 
						private final List<String> locationValues = new ArrayList<>(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<Resource> locations = new ArrayList<>(4);
 | 
						private final List<Resource> locationResources = new ArrayList<>(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final List<Resource> locationsToUse = new ArrayList<>(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<ResourceResolver> resourceResolvers = new ArrayList<>(4);
 | 
						private final List<ResourceResolver> resourceResolvers = new ArrayList<>(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,9 +149,9 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
	 * for serving static resources.
 | 
						 * for serving static resources.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void setLocations(@Nullable List<Resource> locations) {
 | 
						public void setLocations(@Nullable List<Resource> locations) {
 | 
				
			||||||
		this.locations.clear();
 | 
							this.locationResources.clear();
 | 
				
			||||||
		if (locations != null) {
 | 
							if (locations != null) {
 | 
				
			||||||
			this.locations.addAll(locations);
 | 
								this.locationResources.addAll(locations);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,11 +161,18 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
	 * <p>Note that if {@link #setLocationValues(List) locationValues} are provided,
 | 
						 * <p>Note that if {@link #setLocationValues(List) locationValues} are provided,
 | 
				
			||||||
	 * instead of loaded Resource-based locations, this method will return
 | 
						 * instead of loaded Resource-based locations, this method will return
 | 
				
			||||||
	 * empty until after initialization via {@link #afterPropertiesSet()}.
 | 
						 * empty until after initialization via {@link #afterPropertiesSet()}.
 | 
				
			||||||
 | 
						 * <p><strong>Note:</strong> As of 5.3.11 the list of locations is filtered
 | 
				
			||||||
 | 
						 * to exclude those that don't actually exist and therefore the list returned
 | 
				
			||||||
 | 
						 * from this method may be a subset of all given locations.
 | 
				
			||||||
	 * @see #setLocationValues
 | 
						 * @see #setLocationValues
 | 
				
			||||||
	 * @see #setLocations
 | 
						 * @see #setLocations
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public List<Resource> getLocations() {
 | 
						public List<Resource> getLocations() {
 | 
				
			||||||
		return this.locations;
 | 
							if (this.locationsToUse.isEmpty()) {
 | 
				
			||||||
 | 
								// Possibly not yet initialized, return only what we have so far
 | 
				
			||||||
 | 
								return this.locationResources;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this.locationsToUse;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -295,7 +304,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
	public void afterPropertiesSet() throws Exception {
 | 
						public void afterPropertiesSet() throws Exception {
 | 
				
			||||||
		resolveResourceLocations();
 | 
							resolveResourceLocations();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) {
 | 
							if (logger.isWarnEnabled() && CollectionUtils.isEmpty(getLocations())) {
 | 
				
			||||||
			logger.warn("Locations list is empty. No resources will be served unless a " +
 | 
								logger.warn("Locations list is empty. No resources will be served unless a " +
 | 
				
			||||||
					"custom ResourceResolver is configured as an alternative to PathResourceResolver.");
 | 
										"custom ResourceResolver is configured as an alternative to PathResourceResolver.");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -316,21 +325,22 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void resolveResourceLocations() {
 | 
						private void resolveResourceLocations() {
 | 
				
			||||||
		if (CollectionUtils.isEmpty(this.locationValues)) {
 | 
							List<Resource> result = new ArrayList<>(this.locationResources);
 | 
				
			||||||
			return;
 | 
					
 | 
				
			||||||
		}
 | 
							if (!this.locationValues.isEmpty()) {
 | 
				
			||||||
		else if (!CollectionUtils.isEmpty(this.locations)) {
 | 
								Assert.notNull(this.resourceLoader,
 | 
				
			||||||
			throw new IllegalArgumentException("Please set either Resource-based \"locations\" or " +
 | 
										"ResourceLoader is required when \"locationValues\" are configured.");
 | 
				
			||||||
					"String-based \"locationValues\", but not both.");
 | 
								Assert.isTrue(CollectionUtils.isEmpty(this.locationResources), "Please set " +
 | 
				
			||||||
 | 
										"either Resource-based \"locations\" or String-based \"locationValues\", but not both.");
 | 
				
			||||||
 | 
								for (String location : this.locationValues) {
 | 
				
			||||||
 | 
									result.add(this.resourceLoader.getResource(location));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Assert.notNull(this.resourceLoader,
 | 
							result = result.stream().filter(Resource::exists).collect(Collectors.toList());
 | 
				
			||||||
				"ResourceLoader is required when \"locationValues\" are configured.");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (String location : this.locationValues) {
 | 
							this.locationsToUse.clear();
 | 
				
			||||||
			Resource resource = this.resourceLoader.getResource(location);
 | 
							this.locationsToUse.addAll(result);
 | 
				
			||||||
			this.locations.add(resource);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -339,7 +349,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
	 * match the {@link #setLocations locations} configured on this class.
 | 
						 * match the {@link #setLocations locations} configured on this class.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected void initAllowedLocations() {
 | 
						protected void initAllowedLocations() {
 | 
				
			||||||
		if (CollectionUtils.isEmpty(this.locations)) {
 | 
							if (CollectionUtils.isEmpty(getLocations())) {
 | 
				
			||||||
			if (logger.isInfoEnabled()) {
 | 
								if (logger.isInfoEnabled()) {
 | 
				
			||||||
				logger.info("Locations list is empty. No resources will be served unless a " +
 | 
									logger.info("Locations list is empty. No resources will be served unless a " +
 | 
				
			||||||
						"custom ResourceResolver is configured as an alternative to PathResourceResolver.");
 | 
											"custom ResourceResolver is configured as an alternative to PathResourceResolver.");
 | 
				
			||||||
| 
						 | 
					@ -618,8 +628,8 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
 | 
				
			||||||
		if (!this.locationValues.isEmpty()) {
 | 
							if (!this.locationValues.isEmpty()) {
 | 
				
			||||||
			return this.locationValues.stream().collect(Collectors.joining("\", \"", "[\"", "\"]"));
 | 
								return this.locationValues.stream().collect(Collectors.joining("\", \"", "[\"", "\"]"));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (!this.locations.isEmpty()) {
 | 
							if (!getLocations().isEmpty()) {
 | 
				
			||||||
			return "[" + this.locations.toString()
 | 
								return "[" + getLocations().toString()
 | 
				
			||||||
					.replaceAll("class path resource", "Classpath")
 | 
										.replaceAll("class path resource", "Classpath")
 | 
				
			||||||
					.replaceAll("ServletContext resource", "ServletContext") + "]";
 | 
										.replaceAll("ServletContext resource", "ServletContext") + "]";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,7 @@ import org.springframework.web.server.ServerWebExchange;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class AbstractMessageWriterResultHandler extends HandlerResultHandlerSupport {
 | 
					public abstract class AbstractMessageWriterResultHandler extends HandlerResultHandlerSupport {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";
 | 
						protected static final String COROUTINES_FLOW_CLASS_NAME = "kotlinx.coroutines.flow.Flow";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<HttpMessageWriter<?>> messageWriters;
 | 
						private final List<HttpMessageWriter<?>> messageWriters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2020 the original author or authors.
 | 
					 * Copyright 2002-2021 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import reactor.core.publisher.Mono;
 | 
					import reactor.core.publisher.Mono;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.core.KotlinDetector;
 | 
				
			||||||
import org.springframework.core.MethodParameter;
 | 
					import org.springframework.core.MethodParameter;
 | 
				
			||||||
import org.springframework.core.ReactiveAdapter;
 | 
					import org.springframework.core.ReactiveAdapter;
 | 
				
			||||||
import org.springframework.core.ReactiveAdapterRegistry;
 | 
					import org.springframework.core.ReactiveAdapterRegistry;
 | 
				
			||||||
| 
						 | 
					@ -108,6 +109,7 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@SuppressWarnings("ConstantConditions")
 | 
				
			||||||
	public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
 | 
						public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Mono<?> returnValueMono;
 | 
							Mono<?> returnValueMono;
 | 
				
			||||||
| 
						 | 
					@ -118,7 +120,9 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand
 | 
				
			||||||
		if (adapter != null) {
 | 
							if (adapter != null) {
 | 
				
			||||||
			Assert.isTrue(!adapter.isMultiValue(), "Only a single ResponseEntity supported");
 | 
								Assert.isTrue(!adapter.isMultiValue(), "Only a single ResponseEntity supported");
 | 
				
			||||||
			returnValueMono = Mono.from(adapter.toPublisher(result.getReturnValue()));
 | 
								returnValueMono = Mono.from(adapter.toPublisher(result.getReturnValue()));
 | 
				
			||||||
			bodyParameter = actualParameter.nested().nested();
 | 
								boolean isContinuation = (KotlinDetector.isSuspendingFunction(actualParameter.getMethod()) &&
 | 
				
			||||||
 | 
										!COROUTINES_FLOW_CLASS_NAME.equals(actualParameter.getParameterType().getName()));
 | 
				
			||||||
 | 
								bodyParameter = (isContinuation ? actualParameter.nested() : actualParameter.nested().nested());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			returnValueMono = Mono.justOrEmpty(result.getReturnValue());
 | 
								returnValueMono = Mono.justOrEmpty(result.getReturnValue());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,6 +253,23 @@ public class ResourceWebHandlerTests {
 | 
				
			||||||
		assertResponseBody(exchange, "h1 { color:red; }");
 | 
							assertResponseBody(exchange, "h1 { color:red; }");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test  // gh-27538
 | 
				
			||||||
 | 
						public void filterNonExistingLocations() throws Exception {
 | 
				
			||||||
 | 
							List<Resource> inputLocations = Arrays.asList(
 | 
				
			||||||
 | 
									new ClassPathResource("test/", getClass()),
 | 
				
			||||||
 | 
									new ClassPathResource("testalternatepath/", getClass()),
 | 
				
			||||||
 | 
									new ClassPathResource("nosuchpath/", getClass()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ResourceWebHandler handler = new ResourceWebHandler();
 | 
				
			||||||
 | 
							handler.setLocations(inputLocations);
 | 
				
			||||||
 | 
							handler.afterPropertiesSet();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							List<Resource> actual = handler.getLocations();
 | 
				
			||||||
 | 
							assertThat(actual).hasSize(2);
 | 
				
			||||||
 | 
							assertThat(actual.get(0).getURL().toString()).endsWith("test/");
 | 
				
			||||||
 | 
							assertThat(actual.get(1).getURL().toString()).endsWith("testalternatepath/");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test // SPR-14577
 | 
						@Test // SPR-14577
 | 
				
			||||||
	public void getMediaTypeWithFavorPathExtensionOff() throws Exception {
 | 
						public void getMediaTypeWithFavorPathExtensionOff() throws Exception {
 | 
				
			||||||
		List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass()));
 | 
							List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass()));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2021 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -22,18 +22,20 @@ import kotlinx.coroutines.async
 | 
				
			||||||
import kotlinx.coroutines.delay
 | 
					import kotlinx.coroutines.delay
 | 
				
			||||||
import kotlinx.coroutines.flow.Flow
 | 
					import kotlinx.coroutines.flow.Flow
 | 
				
			||||||
import kotlinx.coroutines.flow.flow
 | 
					import kotlinx.coroutines.flow.flow
 | 
				
			||||||
import org.assertj.core.api.Assertions.*
 | 
					import org.assertj.core.api.Assertions.assertThat
 | 
				
			||||||
 | 
					import org.assertj.core.api.Assertions.assertThatExceptionOfType
 | 
				
			||||||
import org.springframework.context.ApplicationContext
 | 
					import org.springframework.context.ApplicationContext
 | 
				
			||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
 | 
					import org.springframework.context.annotation.AnnotationConfigApplicationContext
 | 
				
			||||||
import org.springframework.context.annotation.ComponentScan
 | 
					import org.springframework.context.annotation.ComponentScan
 | 
				
			||||||
import org.springframework.context.annotation.Configuration
 | 
					import org.springframework.context.annotation.Configuration
 | 
				
			||||||
import org.springframework.http.HttpHeaders
 | 
					import org.springframework.http.HttpHeaders
 | 
				
			||||||
import org.springframework.http.HttpStatus
 | 
					import org.springframework.http.HttpStatus
 | 
				
			||||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer
 | 
					import org.springframework.http.ResponseEntity
 | 
				
			||||||
import org.springframework.web.bind.annotation.GetMapping
 | 
					import org.springframework.web.bind.annotation.GetMapping
 | 
				
			||||||
import org.springframework.web.bind.annotation.RestController
 | 
					import org.springframework.web.bind.annotation.RestController
 | 
				
			||||||
import org.springframework.web.client.HttpServerErrorException
 | 
					import org.springframework.web.client.HttpServerErrorException
 | 
				
			||||||
import org.springframework.web.reactive.config.EnableWebFlux
 | 
					import org.springframework.web.reactive.config.EnableWebFlux
 | 
				
			||||||
 | 
					import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CoroutinesIntegrationTests : AbstractRequestMappingIntegrationTests() {
 | 
					class CoroutinesIntegrationTests : AbstractRequestMappingIntegrationTests() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +65,15 @@ class CoroutinesIntegrationTests : AbstractRequestMappingIntegrationTests() {
 | 
				
			||||||
		assertThat(entity.body).isEqualTo("foo")
 | 
							assertThat(entity.body).isEqualTo("foo")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@ParameterizedHttpServerTest  // gh-27292
 | 
				
			||||||
 | 
						fun `Suspending ResponseEntity handler method`(httpServer: HttpServer) {
 | 
				
			||||||
 | 
							startServer(httpServer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							val entity = performGet<String>("/suspend-response-entity", HttpHeaders.EMPTY, String::class.java)
 | 
				
			||||||
 | 
							assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
 | 
				
			||||||
 | 
							assertThat(entity.body).isEqualTo("{\"value\":\"foo\"}")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@ParameterizedHttpServerTest
 | 
						@ParameterizedHttpServerTest
 | 
				
			||||||
	fun `Handler method returning Flow`(httpServer: HttpServer) {
 | 
						fun `Handler method returning Flow`(httpServer: HttpServer) {
 | 
				
			||||||
		startServer(httpServer)
 | 
							startServer(httpServer)
 | 
				
			||||||
| 
						 | 
					@ -119,6 +130,12 @@ class CoroutinesIntegrationTests : AbstractRequestMappingIntegrationTests() {
 | 
				
			||||||
			"foo"
 | 
								"foo"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@GetMapping("/suspend-response-entity")
 | 
				
			||||||
 | 
							suspend fun suspendingResponseEntityEndpoint(): ResponseEntity<FooContainer<String>> {
 | 
				
			||||||
 | 
								delay(1)
 | 
				
			||||||
 | 
								return ResponseEntity.ok(FooContainer("foo"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@GetMapping("/flow")
 | 
							@GetMapping("/flow")
 | 
				
			||||||
		fun flowEndpoint()= flow {
 | 
							fun flowEndpoint()= flow {
 | 
				
			||||||
			emit("foo")
 | 
								emit("foo")
 | 
				
			||||||
| 
						 | 
					@ -151,4 +168,8 @@ class CoroutinesIntegrationTests : AbstractRequestMappingIntegrationTests() {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class FooContainer<T>(val value: T)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,6 +188,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
 | 
				
			||||||
	 * locations provided via {@link #setLocations(List) setLocations}.
 | 
						 * locations provided via {@link #setLocations(List) setLocations}.
 | 
				
			||||||
	 * <p>Note that the returned list is fully initialized only after
 | 
						 * <p>Note that the returned list is fully initialized only after
 | 
				
			||||||
	 * initialization via {@link #afterPropertiesSet()}.
 | 
						 * initialization via {@link #afterPropertiesSet()}.
 | 
				
			||||||
 | 
						 * <p><strong>Note:</strong> As of 5.3.11 the list of locations is filtered
 | 
				
			||||||
 | 
						 * to exclude those that don't actually exist and therefore the list returned
 | 
				
			||||||
 | 
						 * from this method may be a subset of all given locations.
 | 
				
			||||||
	 * @see #setLocationValues
 | 
						 * @see #setLocationValues
 | 
				
			||||||
	 * @see #setLocations
 | 
						 * @see #setLocations
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -466,6 +469,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
 | 
				
			||||||
		result.addAll(this.locationResources);
 | 
							result.addAll(this.locationResources);
 | 
				
			||||||
		result = result.stream().filter(Resource::exists).collect(Collectors.toList());
 | 
							result = result.stream().filter(Resource::exists).collect(Collectors.toList());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.locationsToUse.clear();
 | 
				
			||||||
		this.locationsToUse.addAll(result);
 | 
							this.locationsToUse.addAll(result);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue