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(ResponseBase.java:750)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:165)
at org.apache.turbine.services.rundata.DefaultTurbineRunData.getOut(DefaultTurbineRunData.java:1013)
at org.apache.turbine.modules.layouts.VelocityOnlyLayout.doBuild(VelocityOnlyLayout.java:120)
at org.apache.turbine.modules.Layout.build(Layout.java:91)
at org.apache.turbine.modules.LayoutLoader.exec(LayoutLoader.java:123)
at org.apache.turbine.modules.pages.DefaultPage.doBuild(DefaultPage.java:169)
at org.apache.turbine.modules.Page.build(Page.java:90)
at org.apache.turbine.modules.PageLoader.exec(PageLoader.java:123)
at org.apache.turbine.Turbine.doGet(Turbine.java:563)
at org.apache.turbine.Turbine.doPost(Turbine.java:658)

_
*
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

 data.setLayout("DirectResponseLayout"); 

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="mailto:peter@courcoux.biz">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.

Questions:

  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