views:

35

answers:

3

We have some code on production which is effectively doing what this code does:

http://java.sun.com/products/java-media/2D/reference/faqs/index.html#Q_Can_I_use_Java2D_to_generate_d

This works fine, however I have noticed some concerning behaviour.

When a servlet is requested and some image data is returned to the browser via a ServletOutputStream, if another request is triggered before the image has finished painting itself on the screen, this will invariably crash the entire Jaguar server with the following trace:

j  com.sybase.jaguar.servlet.JaguarConnection.writeClient([BII)V+0
j  com.sybase.jaguar.servlet.JagHttp11OutputStream.writeChunk()V+92
j  com.sybase.jaguar.servlet.JagHttp11OutputStream.writeOut()V+57
j  com.sybase.jaguar.servlet.ResponseImpl.flushBuffer(Z)V+93
j  com.sybase.jaguar.servlet.ResponseImpl.flushBuffer()V+17
j  com.sybase.jaguar.servlet.JaguarOutputStream.flush()V+19
j  javax.imageio.stream.FileCacheImageOutputStream.close()V+50
j  javax.imageio.stream.ImageInputStreamImpl.finalize()V+8

I have found a couple of references online saying that what I am trying to do is unreliable, ie:

http://forums.sun.com/thread.jspa?trange=15&threadID=560000&forumID=20&tstart=0

However, to be honest, I am unclear as to what the EDT is.

Has anyone come across this issue, and been able to create a workaround for it?

+1  A: 

I can at least say what the EDT it: that's the Event Dispatch Thread, the thread where all AWT and Swing operations are done.
AFAIK, there can be only one EDT per JVM, since that's the operations outputting graphics on screen. I understand your operation is headless, but perhaps the rule still applies.
I am unsure of what the correct fix could be. Perhaps spawning one JVM per request thread? Not sure if it is practical...

PhiLho
A: 

Do you mean that the same browser is trying to navigate to a new URL before the images on the previous page have been retrieved and rendered? This may cause the browser to close the network connections used to retrieve the images, which depending on the servlet implementation may cause an exception to be caught and logged, although no real error situation is present (the browser simply has dropped the connection before the servlet has finished its work).

You are posting a stack trace here, but what is the actual Exception, which is thrown by the JaguarConnection class?

jarnbjo
+1  A: 

This sounds like that some request scoped variables are been declared as an instance variable of the servlet. In other words, the code is not threadsafe. There's only one instance of the servlet in webapplication's lifetime. It is shared concurrently between all requests. Each request counts as a separate thread. Imagine that you declare variable X (e.g. the image) as instance variable of the servlet and set it in thread A (request A) and then during processing thread B will use the same servlet and override variable X. This will cause trouble in thread A because the variable has been changed during processing it to the output.

Thus, you should never assign request or session scoped variables as instance variable of the servlet:

public class ImageServlet extends HttpServlet {

    private Image image;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        this.image = imageDAO.find(request.getPathInfo()); // Not threadsafe!! image is been shared among all requests.
        // ...
    }
}

but rather so

public class ImageServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        Image image = imageDAO.find(request.getPathInfo()); // Threadsafe.
        // ...
    }
}

this way each thread has its own variable.

That said, the EDT is the "Event Dispatcher Thread". I don't do Swing so I can't tell much about it, but it makes sense that he is trying to tell that you should keep all variables threadlocal (i.e. declare them all inside the servlet's method block) to avoid them being shared among all threads (requests).

BalusC