You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Bart Busschots <ba...@so-4pt.net> on 2006/08/13 19:43:11 UTC

Problem writting to the output stream within an action

Hi,

I'm trying to write a struts action that will render a PDF rather than 
some JSP. My code is below. The problem is that the line to get the 
output stream throws an exception:

java.lang.IllegalStateException: getOutputStream() has already been called for this response
	org.apache.coyote.tomcat5.CoyoteResponse.getWriter(CoyoteResponse.java:599)
	org.apache.coyote.tomcat5.CoyoteResponseFacade.getWriter(CoyoteResponseFacade.java:163)
	org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:122)
	org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:115)
	org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:190)
	org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:115)
	org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:75)
	org.apache.jsp.util.error_jsp._jspService(error_jsp.java:90)
	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	org.apache.struts.action.RequestProcessor.doForward(RequestProcessor.java:1062)
	org.apache.struts.action.RequestProcessor.processForwardConfig(RequestProcessor.java:386)
	org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:229)
	org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
	org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:802)



Any ideas where I'm going wrong?

Cheers,

Bart.

public ActionForward execute(ActionMapping mapping, ActionForm form, 
HttpServletRequest request, HttpServletResponse response) throws Exception {
    //create the needed helper items
    SessionHelper sessHelp = new SessionHelper(request.getSession(true));
    RequestHelper reqHelp = new RequestHelper(request);
    Logger log = new Logger(this.getClass().getName(), false);
    MessageResources messageResources = getResources(request);
    AssignmentService service = new AssignmentService();
    UserDataBean userData = sessHelp.getUserData();

    //
    // Get form data
    //
    DynaActionForm theForm = (DynaActionForm)form;
    String aid = (String)theForm.get("aid");

    //get the details of the assignment
    AssignmentDetailsBean details = null;

    //if we got no assignment ID from the form, try get details from the 
session
    if(aid == null || aid.equals("")) {
      try {
        details = sessHelp.getCurrentAssignment();
      } catch(Exception e) {
        log.iLogWarning("Failed to retrieve Assignement Details from the 
session", e);
        
reqHelp.setErrorMessage(messageResources.getMessage("paper.renderPdf.fail.insufficientData"));
        return mapping.findForward("error");
      }
    } else {
      //try get one from the DB and make sure we are allowed to view it
      try {
        details = service.getAssignmentDetails(aid);

        //ensure that the person logged in can see the paper
        if(!service.canViewPaper(userData, aid)) {
          log.iLogInfo("***security*** The user " + 
userData.getUserName() + " tried to view the paper " + aid + " which 
they are not authorised to view.");
          
reqHelp.setErrorMessage(messageResources.getMessage("paper.renderPdf.fail.noAuth"));
          return mapping.findForward("error");
        }
      } catch(Exception e) {
        log.iLogWarning("Failed to retrieve Details for the assignment " 
+ aid + " from the DB", e);
        
reqHelp.setErrorMessage(messageResources.getMessage("paper.renderPdf.fail"));
        return mapping.findForward("error");
      }
    }

    //output the PDF
    PaperOutputter paperOut = new PaperOutputter(details, messageResources);
    try {
      paperOut.renderPdf(response.getOutputStream());
    } catch(Exception e) {
      log.iLogWarning("Failed to render the PDF for the paper " + aid, e);
      
reqHelp.setErrorMessage(messageResources.getMessage("paper.renderPdf.fail"));
      return mapping.findForward("error");
    }

    //end the request
    return mapping.findForward(null);
  }

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: Problem writting to the output stream within an action

Posted by David Friedman <hu...@ix.netcom.com>.
Yes.  Just return or return null instead of an ActionForward.  Don't look
for a mapping using mapping.findforward(null).  As a side note, you have a
lot of nested "try/catch" and "if" statements which a) can be difficult to
read (I had trouble) and the nested try/catches can cause performance issues
on high activity sites.  You might want to consider creating a few custom
exceptions and having everything in one TRY with a catch at the end for each
possible exception it your general method might look more readable like
this:

=-=-=-=-=-=-=-=-=-=-=-=-=-=-
try {
   // step 1
   // step 2

   // step 3, an if "failed"? Throw an exception to catch
   //     below like "MySecurityException"

   // ...

   // ***everything worked?  Return null because we sent
   // ** the headers and returned a binary, i.e. your PDF.
   return;

  // Catch specific exceptions and set logs/messages
} catch ( MyNoAssignmentException mnoe )
   // setmessage
   // log
} catch ( MySecurityExeption mse ) {
   // setmessage
   // log
} catch ( MyNoAssignmentDetailsException mnade ) {
   // setmessage
   // log
} catch ( MyRenderException mre ) {
   // setmessage
   // log
}

// We got this far so we MUST have an error, return error page
return mapping.findForward("error");

=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Now wouldn't that be easier to read?  It would also be a bit more performant
because we have one try for the JVM to follow but any failure above must
result in a log, message setup, and a showing of the error page mapping.

Regards,
David


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org