Bug 37516

Summary: A committed HttpServletResponse is passed to the doGet() method
Product: Tomcat 5 Reporter: Adriano Oliveira <nobreadriano>
Component: Servlet & JSP APIAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED INVALID    
Severity: critical CC: nobreadriano
Priority: P2    
Version: 5.5.9   
Target Milestone: ---   
Hardware: All   
OS: All   

Description Adriano Oliveira 2005-11-16 00:07:24 UTC
I'm getting a committed HttpServletResponse object in my doGet() without 
executing any command that could change its state to committed. Some of the 
times this error has occurred I noticed that the response was committed even 
before the first command in the doGet method. I don't get this behavior on Sun 
Java System Application Server 8.1. I got this behavior on Tomcat 5.5.7, 
5.5.9, 5.5.12 both on Windows XP and Linux (Fedora 2).

I'm sending a brief code to simulate this error (two servlets and the 
descriptor. Please note that in order to test this code you may have to change 
the port number in the HTML generated in Test.java. Also, the generated page 
uses a HTML Header to automatically refreshs the page every second to spare 
the person who's testing to press F5. But one can erase this Refresh-Header 
and do the refreshs by pressing F5 and after some refreshs the error will 
occur).

//*********** web.xml ***************
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>Test</servlet-name>
    <servlet-class>Test</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>Image</servlet-name>
    <servlet-class>Image</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Test</servlet-name>
    <url-pattern>/test</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Image</servlet-name>
    <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
            30
        </session-timeout>
  </session-config>
</web-app>



// ******************* Test.java ***********************************
// Note: if you use a port number other than 8080 please change the line 
out.println("<img alt=\"image\" src=\"http://localhost:8080/... in Test.java

import java.io.*;
import java.net.*;
 
import javax.servlet.*;
import javax.servlet.http.*;
 
/**
 *
 * @author Adriano
 * @version
 */
public class Test extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, 
HttpServletResponse response)
    throws ServletException, IOException {
        if (response.isCommitted()) {
            System.out.println("Response is committed in Test.processRequest");
        }
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<meta http-equiv=\"Refresh\" content=\"1\">");
        out.println("<title>Servlet Test</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<img alt=\"image\" 
src=\"http://localhost:8080/BugTest/image.jpg\"");
        out.println("</body>");
        out.println("</html>");
        out.close();
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse 
response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse 
response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
}


//******************************* Image.java *************************
 
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
 
import javax.servlet.*;
import javax.servlet.http.*;
 
/**
 *
 * @author Adriano
 * @version
 */
public class Image extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, 
HttpServletResponse response)
    throws ServletException, IOException {
        
        if (response.isCommitted()) {
            System.out.println("Response is committed in 
Image.processRequest");
        }
        
        response.setContentType("image/jpg");
        response.setBufferSize(8192);
        
        OutputStream out = response.getOutputStream();
        
        //Generates an image
        BufferedImage image = new BufferedImage(100, 100, 
BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        Font font = new Font("Arial", Font.BOLD, 20);
        graphics.setFont(font);
        graphics.drawString("Test", 20, 20);
        Iterator writers = ImageIO.getImageWritersByFormatName("jpg");
        ImageWriter writer = (ImageWriter)writers.next();
        ImageOutputStream imageOutput = ImageIO.createImageOutputStream(out);
        writer.setOutput(imageOutput);
        writer.write(image);
        writer.dispose();
        
        out.close();
        
        response.flushBuffer();
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse 
response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse 
response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
}
Comment 1 Remy Maucherat 2005-11-16 21:59:13 UTC
I looked at that issue in the past, and Java2D accesses the streams outside of
the service methods.