During testing a Java Servlet on Tomcat that uses ImageIO and ServletOutputStream to display several guitar chord diagrams, I ran into a strange problem, that I can't explain or solve. The pattern used was found in several locations on the Internet. It creates a BufferedImage that is written to the ServletOutputStream:
// Set PNG content type response.setContentType("image/png"); // Construct a diagram creator for the provided chord name
DiagramCreator diagramCreator = new DiagramCreator(chordName); // Create the image of a chord diagram. BufferedImage diagram = diagramCreator.createImage(width, height, notes); // Write the image to the output stream ServletOutputStream out = response.getOutputStream(); ImageIO.write(diagram, "PNG", out); out.close();
As long as the servlet "diagram.png" is called only once per HTML page, there are no issues and the correct image is rendered on the page. The problem starts when multiple calls to the same servlet are made on the same page. Simplified HTML example:
<img src="diagram.png?n=Cmaj¬es=E4/1/0,G3/3/0,C3/5/3"> E4/1/0,G3/3/0,C3/5/3 <img src="diagram.png?n=Cmaj¬es=E4/1/0,C4/2/1,G3/3/0,C3/5/3"> E4/1/0,C4/2/1,G3/3/0,C3/5/3 <img src="diagram.png?n=Cmaj¬es=G4/1/3,E3/4/2,C3/5/3"> G4/1/3,E3/4/2,C3/5/3
The images are rendered in the HTML page, but repeatedly calling the same page will render different images each time. The text below the image should always match the text inside the image. The red circled ones don't. There the diagram image belongs to another chord pattern. So the wrong image is rendered, indicating to me that somewhere there is a buffering or thread-safety issue.
There is some debate if ImageIO is thread-safe. Also Tomcat is using a ServletOutputStream pool where a stream might be used simultaneously by multiple browser threads? Using .isReady() didn't provide a solution either. Whatever the root cause, it's blocking further development of the application :(
The dangers of Javas ImageIO
I'm using the Java ImageIO to dynamically serve images and get strange Exceptions from time to time. Is this a bug in Tomcat?
Java Code Examples for javax.servlet.ServletOutputStream
ServletOutputStream.isReady() returns true while it is not yet ready
Should I close the servlet outputstream?
temp imageio files in Tomcat gnerated by botBinFormat ?
Broken Pipe when writing bytes in ServletOutputStream
Problem with multiple images in a JSP (Connection reset by peer)