Skip to content

Commit 6f58491

Browse files
committed
MarshallingView explicitly skips BindingResult when searching for a model object
Just implementing common custom subclass behavior out-of-the-box... Issue: SPR-11417
1 parent 3716a8e commit 6f58491

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/view/xml/MarshallingView.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.oxm.Marshaller;
2626
import org.springframework.util.Assert;
2727
import org.springframework.util.StreamUtils;
28+
import org.springframework.validation.BindingResult;
2829
import org.springframework.web.servlet.View;
2930
import org.springframework.web.servlet.view.AbstractView;
3031

@@ -38,6 +39,7 @@
3839
* property or have Spring locate the Source object.
3940
*
4041
* @author Arjen Poutsma
42+
* @author Juergen Hoeller
4143
* @since 3.0
4244
*/
4345
public class MarshallingView extends AbstractView {
@@ -67,15 +69,15 @@ public MarshallingView() {
6769
*/
6870
public MarshallingView(Marshaller marshaller) {
6971
this();
70-
setMarshaller(marshaller);
72+
Assert.notNull(marshaller, "Marshaller must not be null");
73+
this.marshaller = marshaller;
7174
}
7275

7376

7477
/**
7578
* Sets the {@link Marshaller} to be used by this view.
7679
*/
7780
public void setMarshaller(Marshaller marshaller) {
78-
Assert.notNull(marshaller, "Marshaller must not be null");
7981
this.marshaller = marshaller;
8082
}
8183

@@ -112,9 +114,10 @@ protected void renderMergedOutputModel(Map<String, Object> model, HttpServletReq
112114
}
113115

114116
/**
115-
* Locates the object to be marshalled. The default implementation first attempts to look
116-
* under the configured {@linkplain #setModelKey(String) model key}, if any, before attempting
117-
* to locate an object of {@linkplain Marshaller#supports(Class) supported type}.
117+
* Locate the object to be marshalled.
118+
* <p>The default implementation first attempts to look under the configured
119+
* {@linkplain #setModelKey(String) model key}, if any, before attempting to
120+
* locate an object of {@linkplain Marshaller#supports(Class) supported type}.
118121
* @param model the model Map
119122
* @return the Object to be marshalled (or {@code null} if none found)
120123
* @throws IllegalStateException if the model object specified by the
@@ -134,7 +137,8 @@ protected Object locateToBeMarshalled(Map<String, Object> model) throws IllegalS
134137
return obj;
135138
}
136139
for (Object obj : model.values()) {
137-
if (obj != null && this.marshaller.supports(obj.getClass())) {
140+
if (obj != null && (model.size() == 1 || !(obj instanceof BindingResult)) &&
141+
this.marshaller.supports(obj.getClass())) {
138142
return obj;
139143
}
140144
}

spring-webmvc/src/test/java/org/springframework/web/servlet/view/xml/MarshallingViewTests.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.web.servlet.view.xml;
1818

1919
import java.util.HashMap;
20+
import java.util.LinkedHashMap;
2021
import java.util.Map;
2122
import javax.xml.transform.stream.StreamResult;
2223

@@ -26,6 +27,8 @@
2627
import org.springframework.mock.web.test.MockHttpServletRequest;
2728
import org.springframework.mock.web.test.MockHttpServletResponse;
2829
import org.springframework.oxm.Marshaller;
30+
import org.springframework.validation.BeanPropertyBindingResult;
31+
import org.springframework.validation.BindingResult;
2932

3033
import static org.junit.Assert.*;
3134
import static org.mockito.BDDMockito.*;
@@ -35,16 +38,18 @@
3538
*/
3639
public class MarshallingViewTests {
3740

41+
private Marshaller marshallerMock;
42+
3843
private MarshallingView view;
3944

40-
private Marshaller marshallerMock;
4145

4246
@Before
4347
public void createView() throws Exception {
4448
marshallerMock = mock(Marshaller.class);
4549
view = new MarshallingView(marshallerMock);
4650
}
4751

52+
4853
@Test
4954
public void getContentType() {
5055
assertEquals("Invalid content type", "application/xml", view.getContentType());
@@ -159,6 +164,26 @@ public void renderNoModelKey() throws Exception {
159164
verify(marshallerMock).marshal(eq(toBeMarshalled), isA(StreamResult.class));
160165
}
161166

167+
@Test
168+
public void renderNoModelKeyAndBindingResultFirst() throws Exception {
169+
Object toBeMarshalled = new Object();
170+
String modelKey = "key";
171+
Map<String, Object> model = new LinkedHashMap<String, Object>();
172+
model.put(BindingResult.MODEL_KEY_PREFIX + modelKey, new BeanPropertyBindingResult(toBeMarshalled, modelKey));
173+
model.put(modelKey, toBeMarshalled);
174+
175+
MockHttpServletRequest request = new MockHttpServletRequest();
176+
MockHttpServletResponse response = new MockHttpServletResponse();
177+
178+
given(marshallerMock.supports(BeanPropertyBindingResult.class)).willReturn(true);
179+
given(marshallerMock.supports(Object.class)).willReturn(true);
180+
181+
view.render(model, request, response);
182+
assertEquals("Invalid content type", "application/xml", response.getContentType());
183+
assertEquals("Invalid content length", 0, response.getContentLength());
184+
verify(marshallerMock).marshal(eq(toBeMarshalled), isA(StreamResult.class));
185+
}
186+
162187
@Test
163188
public void testRenderUnsupportedModel() throws Exception {
164189
Object toBeMarshalled = new Object();

0 commit comments

Comments
 (0)