Do not override requestContextAttribute with null in UrlBasedViewResolvers

Prior to this commit, if a subclass of
org.springframework.web.servlet.view.AbstractView or
org.springframework.web.reactive.result.view.AbstractUrlBasedView
configured a custom value for the requestContextAttribute, that value
was overwritten with null whenever the View was dynamically
instantiated by a UrlBasedViewResolver, and this could lead to
confusing behavior for users of the View.

This commit addresses this issue by ensuring that the
UrlBasedViewResolvers in spring-webmvc and spring-webflux do not
override the requestContextAttribute in a View if the
UrlBasedViewResolver has not been explicitly configured with a custom
requestContextAttribute value.

Closes gh-23129
This commit is contained in:
Sam Brannen
2019-06-13 17:42:14 +03:00
parent c4075cf216
commit 451cce4fe8
4 changed files with 234 additions and 166 deletions

View File

@@ -37,20 +37,60 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
* @author Sam Brannen
*/
public class UrlBasedViewResolverTests {
private UrlBasedViewResolver resolver;
private final UrlBasedViewResolver resolver = new UrlBasedViewResolver();
@Before
public void setup() {
StaticApplicationContext context = new StaticApplicationContext();
context.refresh();
this.resolver = new UrlBasedViewResolver();
this.resolver.setApplicationContext(context);
}
@Test
public void urlBasedViewResolverOverridesCustomRequestContextAttributeWithNonNullValue() throws Exception {
assertThat(new TestView().getRequestContextAttribute())
.as("requestContextAttribute when instantiated directly")
.isEqualTo("testRequestContext");
this.resolver.setViewClass(TestView.class);
this.resolver.setRequestContextAttribute("viewResolverRequestContext");
Mono<View> mono = this.resolver.resolveViewName("example", Locale.getDefault());
StepVerifier.create(mono)
.consumeNextWith(view -> {
assertThat(view).isInstanceOf(TestView.class);
assertThat(((TestView) view).getRequestContextAttribute())
.as("requestContextAttribute when instantiated dynamically by UrlBasedViewResolver")
.isEqualTo("viewResolverRequestContext");
})
.expectComplete()
.verify(Duration.ZERO);
}
@Test
public void urlBasedViewResolverDoesNotOverrideCustomRequestContextAttributeWithNull() throws Exception {
assertThat(new TestView().getRequestContextAttribute())
.as("requestContextAttribute when instantiated directly")
.isEqualTo("testRequestContext");
this.resolver.setViewClass(TestView.class);
Mono<View> mono = this.resolver.resolveViewName("example", Locale.getDefault());
StepVerifier.create(mono)
.consumeNextWith(view -> {
assertThat(view).isInstanceOf(TestView.class);
assertThat(((TestView) view).getRequestContextAttribute())
.as("requestContextAttribute when instantiated dynamically by UrlBasedViewResolver")
.isEqualTo("testRequestContext");
})
.expectComplete()
.verify(Duration.ZERO);
}
@Test
public void viewNames() throws Exception {
@@ -98,6 +138,10 @@ public class UrlBasedViewResolverTests {
private static class TestView extends AbstractUrlBasedView {
public TestView() {
setRequestContextAttribute("testRequestContext");
}
@Override
public boolean checkResourceExists(Locale locale) throws Exception {
return true;