5

I am using the following (which looks like a lot to this) code to download a file:

@RequestMapping(value = "/tunes/{file_name}", method = RequestMethod.GET)
public void downloadTune(@PathVariable(value = "file_name") String tuneId,
        HttpServletResponse response) {
    perfomanceLogger.trace("=== Start retrieving tune with id: " + tuneId);
    try {
        String location = "";
        // try {
        location = resourceManagementService.getArtifcatByIdAndType(tuneId,
                ControllerConstants.TYPE_MP3);
        String pathSeparator = File.separator;

        if (location == null || location.equals("")) {// load the default
                                                        // tune
            location = System.getProperties().get("jboss.server.base.dir")
                    + pathSeparator + ServicesConstants.FILE_LOCATION
                    + pathSeparator + "ringtone_1.mp3";
            if (!new File(location).exists()) {
                location = "";
            }
        }

        if (!location.equals("")) {
            Path musicFile = Paths.get(location);
            response.setContentType("audio/wav");
            response.setContentLength((int) Files.size(musicFile));
            try (OutputStream out = response.getOutputStream()) {
                Files.copy(musicFile, out);
                response.flushBuffer();
            } catch (Exception e) {
                log.info("Could not stream tune with id: " + tuneId + " "
                        + e.getCause() + " " + e.getMessage());
            }
        }
    } catch (IOException | InvalidPathException | IllegalStateException e) {
        log.info("Could not stream tune with id: " + tuneId + " "
                + e.getMessage());

    }
    perfomanceLogger.trace("=== Finished retrieving tune with id: "
            + tuneId);
}

I am using Spring 3.2.2 and Spring Security 3.2.0.M1 and JBoss 7.1.1.Final. The problem is that some times I get an IllegalStateException. Here is the stacktrace:

2014-01-21 12:23:34,969 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/MyWebApplication].[appServlet]] (http--0.0.0.0-80-2) Servlet.service() for servlet appServlet threw exception: java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:2636) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.Request.getSession(Request.java:2375) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:841) [jbossweb-7.0.13.Final.jar:]
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:255) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.springframework.web.context.request.ServletRequestAttributes.getSession(ServletRequestAttributes.java:79) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.context.request.ServletRequestAttributes.setAttribute(ServletRequestAttributes.java:129) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.bind.support.DefaultSessionAttributeStore.storeAttribute(DefaultSessionAttributeStore.java:54) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.method.annotation.SessionAttributesHandler.storeAttributes(SessionAttributesHandler.java:123) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.method.annotation.ModelFactory.updateModel(ModelFactory.java:202) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.getModelAndView(RequestMappingHandlerAdapter.java:842) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:751) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:734) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) [spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:150) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.0.M1.jar:3.2.0.M1]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_21]

Is there something wrong with the session from time to time?

Community
  • 1
  • 1
ampofila
  • 655
  • 2
  • 13
  • 28
  • I don't believe that the problem is in this piece of code. If it is working sometimes, it seems that there is a communication problem. Are you sure that the other side is working properly? – andreadi Jan 21 '14 at 11:57
  • I have seen this. It has to do with Mojarra and JSF. I am not using JSF nor am I returning a view in the controller. – ampofila Jan 21 '14 at 12:04
  • My previous comment was for the answer of @pbal, stack overflow decided to make it an answer after all. – ampofila Jan 21 '14 at 12:20
  • @andreadi Yes it appears later when the flow has left the handler. However debugging did not help. I found a way to produce this error upon every request. I use apache HttpComponents without sending a cookie with a session id. – ampofila Jan 21 '14 at 12:21

2 Answers2

2

Get rid of

response.flushBuffer();

which commits the response.

The Servlet container will take care of committing the response and flushing the OutputStream when it needs to.

If your file is too big, you'll want to create the session yourself before starting the download.


To answer comment:

It seems you never created an HttpSession during your request handling.

The container's implementation of HttpServletResponse commits the response (headers) and starts flushing the OutputStream when you've written X amount of bytes (configurable and depends on container). You cannot force the container to create an HttpSession after that's happened.

Obviously you weren't creating the HttpSession yourself, but Spring uses it to manage its model attributes, so it had to create it. It does that in

at org.springframework.web.method.annotation.ModelFactory.updateModel(ModelFactory.java:202) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]

The simple solution is to get a reference to the HttpServletRequest and call its getSession(boolean) method, passing true so that it forces the creation of the HttpSession. Do this anywhere before you start pushing the file.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • I have tried this as well. The error is the same, somehow the response is committed and then a session cannot be created. I could not find a way to force session creation with Spring Security but I found a work around, in a Spring interceptor I create a session by prehandling the request but I still do not get why this is happening. Could you please define "big"? The files are rather small, about 50-300 KB. – ampofila Jan 21 '14 at 14:56
  • @ampofila If it does, you should be ok. If it doesn't, just do it yourself. – Sotirios Delimanolis Jan 21 '14 at 15:31
  • 1
    Yes the interceptor worked. Thank you for the prompt and helpful explanation. Appreciate it. – ampofila Jan 21 '14 at 15:34
0

There is a similar problem here: Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed

Community
  • 1
  • 1
pbal
  • 531
  • 1
  • 7
  • 19
  • I have seen this. It has to do with Mojarra and JSF. I am not using JSF nor am I returning a view in the controller. – ampofila Jan 21 '14 at 12:11