The VelocityECSLayout has been deprecated in Turbine 2.3.

See: VelocityOnlyLayout Howto

Writing Directly To ServletOutputStream

On March 19, 2003, Peter Courcoux wrote to turbine-dev:

_Hi all,

I have recently changed from using turbine 2.2-b3 to 2.2.1 and from using VelocityECSLayout to VelocityOnly'*_Layout.

One of my actions which extends VelocitySecure_'Action handles a file download by obtaining the HttpServlet'Response setting the headers and then obtaining and writing directly to the ServletOutput*'Stream.

Before the changes outlined above this caused no problem. Having made the changes the following Exception occurs after the completion of the download and closing the ServletOutput'*_Stream:

java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.ResponseBase.getWriter(
at org.apache.catalina.connector.ResponseFacade.getWriter(
at org.apache.turbine.modules.layouts.VelocityOnlyLayout.doBuild(
at org.apache.turbine.modules.LayoutLoader.exec(
at org.apache.turbine.modules.pages.DefaultPage.doBuild(
at org.apache.turbine.modules.PageLoader.exec(
at org.apache.turbine.Turbine.doGet(
at org.apache.turbine.Turbine.doPost(

He later contributed a solution:*_

"I have solved this by creating a DirectResponse'*_Layout class which does nothing except check that declareDirectResponse() has been called on RunData. I then call


in my Action class.

Source of DirectResponse_*'Layout:

package com.whatever.modules.layouts;

// Turbine Classes
import org.apache.turbine.modules.Layout;
import org.apache.turbine.util.RunData;

 * This layout allows an action to manipulate the  
 * ServletOutputStream directly. It requires that 
 * data.declareDirectResponse() has been called to 
 * indicate that the OutputStream is being 
 * handled else an Exception is thrown 
 * @author <a href="">Peter Courcoux</a> 
public class DirectResponseLayout extends Layout
     * Method called by LayoutLoader. 
     * @param RunData 
    public void doBuild( RunData data ) throws Exception 
        if (!data.isOutSet()) 
                throw new Exception( 
                    "data.declareDirectResponse() has not been called"); 

One drawback is that it calls data.isOutSet() which is deprecated.


  1. Is there a better way?
  2. If not, would it be worth including the DirectResponse'*_Layout class in the turbine distribution.
  3. Is there a case for removing the deprecation of RunData.isOutSet()?
  4. Is this worth documenting. At least one other user appears to be doing something similar."


I have committed DirectResponse**Layout to cvs - it will come with future releases of Turbine (2.3.1 and 2.4) whenever those are released.
ScottEade 2003-10-17

  • No labels