title: How to use StreamingResponseBody and try-with-resources?
body: <p>I'd like to create an Excel sheet dynamically and return that to the client. I'd like to use the <code>StreamingResponseBody</code> as the return type in order to save some RAM. I'm also using <code>try-with-resources</code> to close the <code>workbook</code> automatically. Here is the code.</p>
  <pre class="lang-java prettyprint-override"><code>@RestController
  public class ExcelController {
  
    @GetMapping(&quot;/hello&quot;)
    public ResponseEntity&lt;StreamingResponseBody&gt; excel() throws IOException {
      try (var workbook = new XSSFWorkbook();) {
        workbook.createSheet(&quot;hello world&quot;);
        return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType(&quot;application/vnd.ms-excel&quot;))
            .header(HttpHeaders.CONTENT_DISPOSITION, &quot;attachment; filename=data.xlsx&quot;)
            .body(workbook::write);
      }
    }
  }
  </code></pre>
  <p>Unfortunately this does not work and I'm getting the following error message.</p>
  <pre><code>Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
  
  java.io.IOException: Cannot write data, document seems to have been closed already
          at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:215) ~[poi-ooxml-5.1.0.jar:5.1.0]
          at org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler$StreamingResponseBodyTask.call(StreamingResponseBodyReturnValueHandler.java:111) ~[spring-webmvc-5.3.13.jar:5.3.13]
          at org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler$StreamingResponseBodyTask.call(StreamingResponseBodyReturnValueHandler.java:98) ~[spring-webmvc-5.3.13.jar:5.3.13]
          at org.springframework.web.context.request.async.WebAsyncManager.lambda$startCallableProcessing$4(WebAsyncManager.java:337) ~[spring-web-5.3.13.jar:5.3.13]
          at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
          at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
          at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
          at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
          at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
  </code></pre>
  <p>I already tried using my custom TaskExecutor as described by <code>StreamingResponseBody</code> but that didn't really help. In the end I found a solution that works but I'm wondering why the first solution including <code>try-with-resources</code> and method reference does not work.</p>
  <pre class="lang-java prettyprint-override"><code>@RestController
  public class ExcelController {
  
    @GetMapping(&quot;/hello&quot;)
    public ResponseEntity&lt;StreamingResponseBody&gt; excel() throws IOException {
      var workbook = new XSSFWorkbook();
      workbook.createSheet(&quot;hello world&quot;);
      return ResponseEntity.ok()
          .contentType(MediaType.parseMediaType(&quot;application/vnd.ms-excel&quot;))
          .header(HttpHeaders.CONTENT_DISPOSITION, &quot;attachment; filename=data.xlsx&quot;)
          .body(
              out -&gt; {
                workbook.write(out);
                workbook.close();
              });
    }
  }
  </code></pre>
  <p>I highly appreciate your help! Thank you</p>