From cdea667e581fd72445b9d78a7f827c719e2f76b8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 14 Feb 2023 16:57:22 +0100 Subject: [PATCH] Test for request attribute visibility in FreeMarker (backported from main) See gh-29787 --- .../servlet/view/AbstractTemplateView.java | 14 ++++---- .../view/freemarker/FreeMarkerViewTests.java | 35 ++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java index 7a1a24cd756..c6050a5d2fe 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,8 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView { /** * Set whether all request attributes should be added to the * model prior to merging with the template. Default is "false". + *

Note that some templates may make request attributes visible + * on their own, e.g. FreeMarker, without exposure in the MVC model. */ public void setExposeRequestAttributes(boolean exposeRequestAttributes) { this.exposeRequestAttributes = exposeRequestAttributes; @@ -73,7 +75,7 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView { /** * Set whether HttpServletRequest attributes are allowed to override (hide) - * controller generated model attributes of the same name. Default is "false", + * controller generated model attributes of the same name. Default is "false" * which causes an exception to be thrown if request attributes of the same * name as model attributes are found. */ @@ -122,11 +124,11 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView { String attribute = en.nextElement(); if (model.containsKey(attribute) && !this.allowRequestOverride) { throw new ServletException("Cannot expose request attribute '" + attribute + - "' because of an existing model object of the same name"); + "' because of an existing model object of the same name"); } Object attributeValue = request.getAttribute(attribute); if (logger.isDebugEnabled()) { - exposed = exposed != null ? exposed : new LinkedHashMap<>(); + exposed = (exposed != null ? exposed : new LinkedHashMap<>()); exposed.put(attribute, attributeValue); } model.put(attribute, attributeValue); @@ -144,11 +146,11 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView { String attribute = en.nextElement(); if (model.containsKey(attribute) && !this.allowSessionOverride) { throw new ServletException("Cannot expose session attribute '" + attribute + - "' because of an existing model object of the same name"); + "' because of an existing model object of the same name"); } Object attributeValue = session.getAttribute(attribute); if (logger.isDebugEnabled()) { - exposed = exposed != null ? exposed : new LinkedHashMap<>(); + exposed = (exposed != null ? exposed : new LinkedHashMap<>()); exposed.put(attribute, attributeValue); } model.put(attribute, attributeValue); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerViewTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerViewTests.java index d9fd65dce96..a7a79aa1659 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerViewTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerViewTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -145,6 +145,34 @@ public class FreeMarkerViewTests { assertThat(response.getContentType()).isEqualTo("myContentType"); } + @Test + public void requestAttributeVisible() throws Exception { + FreeMarkerView fv = new FreeMarkerView(); + + WebApplicationContext wac = mock(WebApplicationContext.class); + MockServletContext sc = new MockServletContext(); + + Map configs = new HashMap<>(); + FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); + configurer.setConfiguration(new TestConfiguration()); + configurer.setServletContext(sc); + configs.put("configurer", configurer); + given(wac.getBeansOfType(FreeMarkerConfig.class, true, false)).willReturn(configs); + given(wac.getServletContext()).willReturn(sc); + + fv.setUrl("templateName"); + fv.setApplicationContext(wac); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addPreferredLocale(Locale.US); + request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); + request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver()); + HttpServletResponse response = new MockHttpServletResponse(); + + request.setAttribute("myattr", "myvalue"); + fv.render(null, request, response); + } + @Test public void freeMarkerViewResolver() throws Exception { MockServletContext sc = new MockServletContext(); @@ -191,10 +219,9 @@ public class FreeMarkerViewTests { @Override public void process(Object model, Writer writer) throws TemplateException, IOException { assertThat(locale).isEqualTo(Locale.US); - boolean condition = model instanceof AllHttpScopesHashModel; - assertThat(condition).isTrue(); + assertThat(model instanceof AllHttpScopesHashModel).isTrue(); AllHttpScopesHashModel fmModel = (AllHttpScopesHashModel) model; - assertThat(fmModel.get("myattr").toString()).isEqualTo("myvalue"); + assertThat(String.valueOf(fmModel.get("myattr"))).isEqualTo("myvalue"); } }; }