You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by "I-Sampige, Srinivas" <sr...@boeing.com> on 2003/04/22 23:51:27 UTC

RE: action getting invoked twice on PDF error - BEST PRACTICE?

Thanks for all your replies. After reading through all your replies a major question arises -

Here is what I am doing - once the struts action gets invoked for streaming the PDF file 
	- I get the byte array holiding the PDF from the user's session manager object in our application
      - immediately I call a method to set the buffer to null to free up space
	- then I open an output stream to the browser by calling 
		ServletOutputStream sout = response.getOutputStream();
	- then I stream the pdf
	- flush and close sout
      - return null

So the questions that arise now is(since as I understand from the replies that have come in the action does get invoked multiple times because of the way the plugin functions) -
      - Should I be setting the buffer(in the user's session manager object) to null? So that when the action is invoked two or three times, the buffer is not null for the second/third invocations?
	- Should I be closing the servlet output stream?
	
Here comes the code followed by the exception -

public org.apache.struts.action.ActionForward performAction(org.apache.struts.action.ActionMapping mapping, org.apache.struts.action.ActionForm form, HttpServletRequest request, HttpServletResponse response, com.boeing.etrac.security.UserSessionInfo userSessionInfo) throws IOException
{
	ServletOutputStream sout = null;
	PrintWriter pw = null;
	ReportManager reportManager = null;
	try
	{
		reportManager = userSessionInfo.getReportManager();
		if (reportManager == null)
			throw (new EtracSystemException("null ReporManager"));


	 	ReportForm reportForm = reportManager.getCurrentReportForm();
		if (reportForm == null)
			throw (new EtracSystemException("null ReportForm"));
		
		String outputFormat = reportForm.getOutputFormat();
		
		//depending on the output format set the appropriate content type
		if (ReportConstants.OUTPUT_FORMAT_PDF.equalsIgnoreCase(outputFormat))
		{
			response.setContentType("application/pdf");
			response.setHeader("Content-disposition","inline;filename=report.pdf");
		}
		else if(ReportConstants.OUTPUT_FORMAT_TEXT_TAB_DELIMITED.equalsIgnoreCase(outputFormat))
		{
			response.setContentType("application/octet-stream");
			response.addHeader("Content-disposition","attachment;filename=\"etracTabDelimitedReport.dat\"");
		}

		//push the generated report to the client.
		byte[] buffer = reportManager.getReportBuffer();
		response.setContentLength(buffer.length);
		sout = response.getOutputStream();
		sout.write(buffer);
		sout.flush();
		sout.close();
		
	}
	catch(EtracSystemException ese)
	{
		reportManager.setReportGenerated(false);		
        getServlet().log("PullPdfAction", ese);
		StringWriter sw = new StringWriter();
		pw = new PrintWriter(sw);
		pw.print("An error has occurred while loading the pdf report from the server. Please close this window and try again.\n");
		ese.printStackTrace(pw);        
        sout.println(sw.toString());
	}
	catch(Exception e)
	{
		reportManager.setReportGenerated(false);		
        getServlet().log("PullPdfAction", e);
		StringWriter sw = new StringWriter();
		pw = new PrintWriter(sw);
		pw.print("An error has occurred while loading the pdf report from the server. Please close this window and try again.\n");
		e.printStackTrace(pw);        
        sout.println(sw.toString());
	}
	finally
	{
		if (reportManager != null)
		{
			//now, the separate report window has submitted to this action,
			//to pull the generated window. Reset the "reportGenerated" flag
			//to false so that subsequebtly whenever the report menu screen
			//is refreshed it doesn't spawn off the separate report window
			//again
			reportManager.setReportGenerated(false);

			//clear the buffer holding the generated report
			reportManager.setReportBuffer(null);
		}			
		
		if (pw != null)
		{
			pw.flush();
			pw.close();
		}
		
		if (sout != null)
		{
			sout.flush();
			sout.close();	
		}			
	}

	//in a struts action when we get a hold of the output stream then
	//we should not forward. We must return a null. Otherwise we will
	//get an error saying that the output stream has already been obtained.	
    return null;
}

========================================================
Exception - (I guess this is happening because the buffer is null when the action gets invoked the second time by the plugin)

java.lang.NullPointerException
	java.lang.Throwable()
	java.lang.Exception()
	java.lang.RuntimeException()
	java.lang.NullPointerException()
	org.apache.struts.action.ActionForward com.boeing.etrac.action.PullReportAction.performAction(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, com.boeing.etrac.security.UserSessionInfo)
	org.apache.struts.action.ActionForward com.boeing.etrac.action.PullReportAction.performAction(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, com.boeing.etrac.security.UserSessionInfo)
	org.apache.struts.action.ActionForward com.boeing.etrac.action.EtracAction.perform(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	org.apache.struts.action.ActionForward org.apache.struts.action.ActionServlet.processActionPerform(org.apache.struts.action.Action, org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	void org.apache.struts.action.ActionServlet.process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	void com.boeing.etrac.action.EtracServlet.process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	void org.apache.struts.action.ActionServlet.doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	void javax.servlet.http.HttpServlet.service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	void javax.servlet.http.HttpServlet.service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
	void org.apache.tomcat.core.ServletWrapper.doService(org.apache.tomcat.core.Request, org.apache.tomcat.core.Response)
	void org.apache.tomcat.core.Handler.service(org.apache.tomcat.core.Request, org.apache.tomcat.core.Response)
	void org.apache.tomcat.core.ServletWrapper.service(org.apache.tomcat.core.Request, org.apache.tomcat.core.Response)
	void org.apache.tomcat.core.ContextManager.internalService(org.apache.tomcat.core.Request, org.apache.tomcat.core.Response)
	void org.apache.tomcat.core.ContextManager.service(org.apache.tomcat.core.Request, org.apache.tomcat.core.Response)
	void org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(org.apache.tomcat.service.TcpConnection, java.lang.Object [])
	void org.apache.tomcat.service.TcpWorkerThread.runIt(java.lang.Object [])
	void org.apache.tomcat.util.ThreadPool$ControlRunnable.run()
	void java.lang.Thread.run()




  
thanks
Srinivas


-----Original Message-----
From: Neil Erdwien [mailto:neil@k-state.edu]
Sent: Tuesday, April 22, 2003 1:37 PM
To: Struts Users Mailing List
Subject: Re: action getting invoked twice on PDF error


I've never produced a PDF from the server side, but I do remember that 
PDF viewers are sometimes optimized to just download the parts of the 
whole PDF file they need.  The procedure is:

Start the download, get the header, which contains a pointer to the 
object directory stored at the end of the file.  Cancel this download.

Start a new retrieval with a byte range starting at the offset from step 
1 and going to the end of the file.

Using information from the object directory, retrieve the objects (using 
byte range HTTP GETs) needed to render page 1.  Then page 1 can be 
displayed without retrieving the objects needed for page 2.  In other 
words, it is faster.

Exactly how this interacts with IE and your web server and your PDF 
plugin is still a research project.  Could it be your web server front 
end is claiming to support byte ranges but your application really doesn't?


I-Sampige, Srinivas wrote:
> Hi
> 
>  I have an application in which clicking on a button causes another browser window to be opened. This browser window has a self submitting form that submits to an action that streams back a PDF. Two of the users in our system are getting an error "File does not begin with %PDF" and the action is executed twice. This happens only on IE and only for those two users. 
> 
>              1) does anybody know why this is happening?
>              2) what is the explanation for the action getting executed twice?
> 	       3) is there any way to prevent this?
> 
> Thanks
> Srinivas
> 
> 
> Thanks
> Srinivas (206-544-5754)
> CUIS  (http://cuis.ca.boeing.com; Hotline : 206-544-5511)
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: struts-user-help@jakarta.apache.org

-- 
Neil Erdwien, neil@k-state.edu, Web Technologies Manager
Computing and Network Services, Kansas State University


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


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