tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Tomcat Wiki] Update of "FAQ/KnownIssues" by KonstantinPreisser
Date Sun, 14 Aug 2011 14:28:48 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tomcat Wiki" for change notification.

The "FAQ/KnownIssues" page has been changed by KonstantinPreisser:
http://wiki.apache.org/tomcat/FAQ/KnownIssues?action=diff&rev1=1&rev2=2

Comment:
Add information about using the Java ImageIO in servlets and how it could produce broken responses

  
   1. [[#TomcatIssues|What are the known issues in any given Tomcat version?]]
   1. [[#OracleJREIssues|What are the known issues with the Oracle JRE?]]
+  1. [[#ImageIOIssues|I'm using the Java ImageIO to dynamically serve images and get strange
Exceptions from time to time. Is this a bug in Tomcat?]]
  
  == Answers ==
  
@@ -25, +26 @@

  
   * [[https://issues.apache.org/bugzilla/show_bug.cgi?id=50518|jps.exe and jvisualvm.exe
cannot detect tomcat using jdk1.6.0_23 onwards]]
  
+ <<BR>>
+ <<Anchor(ImageIOIssues)>>'''I'm using the Java ImageIO to dynamically serve
images and get strange Exceptions from time to time. Is this a bug in Tomcat?'''
+ 
+ Imagine you have a servlet which dynamically generates images and serves them via the Java
ImageIO. To write the image to the OutputStream, perhaps you are doing something like this:
+ 
+ {{{
+     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
+         BufferedImage img = createMyImage(); // makes a BufferedImage
+         
+         response.setContentType("image/png");
+         try {
+             try (OutputStream out = response.getOutputStream()) { // try-with-resources
+                 ImageIO.write(img, "PNG", out);
+             }
+         } catch (IOException ex) {
+             // Client abandoned connection
+         }
+     }
+ }}}
+ 
+ Now, although there shouldn't be any Exception logged (because the IOException which occurs
when the client abandoned the connection is ignored), you see strange Exceptions in Tomcat's
log which may belong to other Servlets/JSP (at least with Sun/Oracle JVM on Windows), saying
that the response has already commited, althought you didn't write anything to it at that
time. For example:
+ {{{
+ 13.07.2011 00:13:51 org.apache.catalina.core.StandardWrapperValve invoke
+ SEVERE: Servlet.service() for servlet [myApp.MyServlet] in context with path [] threw exception
+ java.lang.IllegalStateException: Cannot create a session after the response has been committed
+ 	at org.apache.catalina.connector.Request.doGetSession(Request.java:2734)
+         ...
+ }}}
+ 
+ or maybe you use the ISAPI Redirector for IIS on Windows, and get these logs:
+ {{{
+ [Tue Jul 12 06:04:49.812 2011] [4124:2444] [error] ajp_connection_tcp_get_message::jk_ajp_common.c
(1296): wrong message format 0xdaed from 127.0.0.1:8019
+ }}}
+ 
+ '''Is this a bug in Tomcat?'''
+ 
+ Actually, it's a bug (or at least a strange behavior) in the Java ImageIO. When the ImageIO
writes to an OutputStream and gets an IOException during writing, it could happen that some
later time, when the ImageWriter is garbage-collected, the flush() method is called on that
OutputStream. Tomcat recycles OutputStream objects to save resources, so it could be that
when flush() is called from the ImageIO, the particular OutputStream object already belongs
to another Response, which can produce the above errors, when the Servlet tries to get a Session
for example, or can generally lead to broken responses.
+ <<BR>>See also [[http://nerd.dk/blogs/bug-tomcat-or-java2d|here]] or this [[https://issues.apache.org/bugzilla/show_bug.cgi?id=37516|Bug
report]].
+ 
+ '''So how to resolve the errors?'''
+ 
+ To resolve this, I'm using an OutputStream decorater class which decorates Tomcat's OutputStream
and prevents any flush() calls. Additionally, when close() is called on that Stream, it nulls-out
the reference to Tomcat's OutputStream and prevents any other operations:
+ 
+ {{{
+ /**
+  * A OutputStream which can be used to write Images
+  * with the ImageIO in servlets.
+  */
+ public class MyImageIOOutputStream extends OutputStream {
+ 
+     private OutputStream out;
+     private volatile boolean isActive = true;
+ 
+     public MyImageIOOutputStream(OutputStream out) {
+         this.out = out;
+     }
+ 
+     @Override
+     public void close() throws IOException {
+         if (isActive) {
+             isActive = false; // deactivate
+             try {
+                 out.close();
+             } finally {
+                 out = null;
+             }
+         }
+     }
+ 
+     @Override
+     public void flush() throws IOException {
+         // do nothing (pevent polluting the stream)
+     }
+ 
+     @Override
+     public void write(byte[] b, int off, int len) throws IOException {
+         if (isActive)
+             out.write(b, off, len);
+     }
+ 
+     @Override
+     public void write(byte[] b) throws IOException {
+         if (isActive)
+             out.write(b);
+     }
+ 
+     @Override
+     public void write(int b) throws IOException {
+         if (isActive)
+             out.write(b);
+     }	
+ 
+ }
+ }}}
+ 
+ Now you just have to use this Decorater class instead of using Tomcat's OutputStream directly:
+ {{{
+         response.setContentType("image/png");
+         try {
+             try (OutputStream out = new MyImageIOOutputStream(response.getOutputStream()))
{
+                 ImageIO.write(img, "PNG", out);
+             }
+         } catch (IOException ex) {
+             // Client abandoned connection
+         }
+ }}}
+ and the errors should be gone away.
+ <<BR>>
+ An alternative would be to write the Image contents to a ByteArrayOutputStream, and using
its writeTo() method to write the contents to the Servlet's Response. However that would require
some additional memory, as the contents have to be buffered.
+ 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message