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 VelocityOnlyLayout.

One of my actions which extends VelocitySecureAction handles a file download by obtaining the HttpServletResponse setting the headers and then obtaining and writing directly to the ServletOutputStream.

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 ServletOutputStream.

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 DirectResponseLayout 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 DirectResponseLayout :-

{{{

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 { {{{ /**

  • 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 DirectResponseLayout 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 { { { DirectResponseLayout } } } to cvs - it will come with future releases of Turbine (2.3.1 and 2.4) whenever those are released. -- ScottEade 2003-10-17


CategoryJakartaTurbine2HowTo