Wrong catch block is reach

Hi,

I encounter a strange behaviour in exception handling.

My web app can generate pdf files, and download them. If client closes its browser window, a ClientAbortException is thrown (which is expected behaviour, I guess.)

However, I can't catch it correctly. Here is my code:

try{

// code for generating PDF and downloading it through response output stream.

}

catch(ClientAbortException caEx){

// No specific error handling required

logger.info("Request aborted by client ["+caEx.getClass()+"] ["+caEx.getMessage()+"]", caEx);

return"PDF_ERROR";

}

catch(Exception ex){

// A problem occured (TODO notify administrator)

logger.info("PDF generation failed ["+ex.getClass()+"] ["+ex.getMessage()+"]", ex);

return"PDF_ERROR";

}

The problem is that even in case of ClientAbortException, the exception is caught by the second catch block, and log is:

PDF generation failed [class org.apache.catalina.connector.ClientAbortException] [null]

As you can see, Class name is the same. I tried debugging by adding the following logs in the second catch block:logger.info("instanceof ? "+ (exinstanceof ClientAbortException));

logger.info("class ? "+ (ex.getClass() == ClientAbortException.class));

But both loggedfalse.

Could someone explain why it can happen?

[2106 byte] By [TimTheEnchantora] at [2007-10-2 12:48:06]
# 1

1) The fully qualified name of ClientAbortException from your class is indeed org.apache.catalina.connector.ClientAbortException. i.e., you are not importing some other ClientAbortException (that lives in a different package). You may want to print out exact class name by ClientAbortException.class.getName() or change the catch block as

catch (org.apache.catalina.connector.ClientAbortException caEx)

just to be sure.

2) If you get the situation even after verifying the fully qualified class name, then you may want to check whether these are loaded by the same loader or not. You may add the following lines:

logger.info("name equals? "+ (ex.getClass().getName().equals(ClientAbortException.class.getName());

logger.info("same loader ? "+ (ex.getClass().getClassLoader() == ClientAbortException.class.getClassLoader()));

if you get true and false respectively, then the what is seen is correct -- a class uniquely identified by fully qualified class name and the class loader that loaded it.

sundararajan.aa at 2007-7-13 9:58:15 > top of Java-index,Developer Tools,Debugging and Profiling Tool APIs...
# 2

Ok, exception class was not loaded by the same loader...

I'm using Tomcat.

Actually, the class is in catalina.jar, and this jar is present in two directories:

TOMCAT_ROOT/server/lib/

and

TOMCAT_ROOT/webapps/myApp/WEB-INF/lib/

I guess the first one is by default, but it can't be accessed by applications. (I guess that's why I copied it in the second directory.)

Is there any way to settle this issue?

Looks like my server startup fails if I move the jar (e.g. in TOMCAT_ROOT/common/lib/ )

TimTheEnchantora at 2007-7-13 9:58:15 > top of Java-index,Developer Tools,Debugging and Profiling Tool APIs...
# 3

Are you copying catalina.jar just for accessing this exception? If so, you can do the following.

1) remove catalina.jar from your app "lib" directory

2) check for ClientAbortException using name

try {

// .... code here....

} catch (Exception ex) {

String name = ex.getClass().getName();

if (name.equals("org.apache.catalina.connector.ClientAbortException") {

// generate log entry for client abortion

} else {

// generate log entry for any other exception

}

}

Having said that, it appears that Tomcat designers don't want application developers to access classes in catalina.jar. That is why they have moved this jar file under server/lib. If so, you probably hava to avoid accessing/depending on these classes...

sundararajan.aa at 2007-7-13 9:58:15 > top of Java-index,Developer Tools,Debugging and Profiling Tool APIs...
# 4

> check for ClientAbortException using name

This might be a last chance option.

> it appears that Tomcat designers don't want application developers to access classes in catalina.jar

Yes, it looks like they don't. However, I find the ClientAbortException information quite interesting, as the finest precision I can obtain otherwise is IOException (superclass of ClientAbortException), which I find a bit vague.

In fact, my goal was to ignore ClientAbortExceptions, and notify administrator in case of other exceptions (including IOExceptions.)

Thank you for your support.

TimTheEnchantora at 2007-7-13 9:58:15 > top of Java-index,Developer Tools,Debugging and Profiling Tool APIs...