Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure HttpMessageConverter classes don't close the response stream [SPR-10095] #14728

Closed
spring-projects-issues opened this issue Dec 14, 2012 · 5 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Dec 14, 2012

Florian Hackenberger opened SPR-10095 and commented

Trying to return a MultiValueMap from a ReSt service method results in an exception when calling writeNewLine on line 253 within writeParts after the first body part. The reason is that all the message converter added in the constructor of FormHttpMessageConverter (e.g. ByteArrayHttpMessageConverter), close the stream, by using the FileCopyUtils.copy method.


Affects: 3.0.5, 3.2 GA

Issue Links:

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

It's broken in 3.2 or has it been broken since 3.0.5 (since both versions are in the report)? Can you provide the signature and annotations for the controller method?

@spring-projects-issues
Copy link
Collaborator Author

Florian Hackenberger commented

It is broken in 3.0.5 (that's what I'm using). I have checked the code from 3.2 and the relevant pieces are still the same, so the bug is present in 3.2 as well. Here is the controller method:

@Override
@PreAuthorize(MERCHANT_ADMIN_AUTH)
@RequestMapping(value = "/loyaltypoint/imageanddata", method = RequestMethod.POST)
@ResponseBody
@Produces(javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA)
public MultiValueMap<String, Object> createLoyaltyPointAsImageAndData(@RequestParam long loyaltyPointTypeId, @RequestParam double value) throws LoyaltyException {
     try {
          String qrCodeUrl = createLoyaltyPoint(loyaltyPointTypeId, value);
          byte[] imageData = toQrCodeImage(qrCodeUrl);
          MultiValueMap<String, Object> mp = new LinkedMultiValueMap<String, Object>();
          MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
          headers.set("Content-Type", MediaType.IMAGE_PNG.toString());
          HttpEntity<Object> image = new HttpEntity<Object>(imageData, headers);
          mp.add("image", image);
          headers.set("Content-Type", MediaType.APPLICATION_JSON.toString());
          HttpEntity<String> data = new HttpEntity<String>(loyaltyPointUUIDToUrl(qrCodeUrl), headers);
          mp.add("data", data);
          return mp;
     } catch (Exception e) {
          log.error(format("Failed to generate loyalty point type {0} with value {1}", loyaltyPointTypeId, value), e);
          throw new LoyaltyException(e);
     }
}

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

I've added a test project but haven't been able to reproduce the issue:
https://github.com/SpringSource/spring-framework-issues/tree/master/SPR-10095

The response is generated without any errors. It would be great if you could help demonstrate it. Thanks.

@spring-projects-issues
Copy link
Collaborator Author

Dmytro Polivenok commented

In my case response was generated without errors, but only one part of the content is present, for example if we add to map

mp.add("data1", "testData1");
mp.add("data2", "testData1");

in response body we will get only

--Oc1mWC3DNI1yeEzOdV5NFSHZFKRbrA
Content-Disposition: form-data; name="data1"
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 8

testData1

And it causes errors on client side (for example if you try to use MultipartStream from commons-fileupload). You can check it using any rest client. Also it looks like Spring restTemplate doesn't allow to receive MultiValueMap response, but this a different story

What is interesting that in Spring MVC test (mockMvc.perform(get("/documents/test")).andReturn().getResponse()) all parts of the response is returned

Thanks,

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Okay thanks for the additional feedback. That helps to confirm the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants