Logging all thrown Exceptions in a web application in Tomcat - java

Do you know any way to and log all exceptions that are ever thrown (whether catched and handled or not) in java?
Here is my issue: There is an application, that I cannot change, and sometimes it has issues creating a lockfile (relevant code below). When it calls the tryLock() method , freezes for 30 seconds (despite the fact that tryLock is nonblocking), and returns with failure (CANT_CREATE_LOCK). As you see, all the catch tiers mask away the real problem, without even logging it.
final File lockFile = new File(fooHomeDir, ".foo-home.lock");
try
{
FileOutputStream stream = new FileOutputStream(lockFile);
try
{
if (stream.getChannel().tryLock() == null)
{
return LockResult.HELD_BY_OTHERS;
}
this.fileOutputStream = stream;
this.lockFile = lockFile;
return LockResult.OK;
}
catch (OverlappingFileLockException overlappingFileLockException)
{
return LockResult.HELD_BY_OTHERS;
}
catch (IOException ie)
{
return LockResult.CANT_CREATE_LOCK;
}
}
catch (FileNotFoundException fnfe)
{
return LockResult.CANT_CREATE_LOCK;
}
What I wish: Able to see what was the details of the exceptions.
Other info:
The environment is Linux, Java 1.7, Tomcat 7.
The fooHomeDir points to an NFS-backed mount point.
The fooHomeDir's permissions did not change.
The fooHomeDir's owner did not change.
The fooHomeDir's filesystem is not full.
There is no SELinux, or other thing that may interfere.
Basically, it worked before, and stopped "suddenly" and "without cause". So right now I'm investigating.
I'm commencing a remote debug of the application, but until then, suggestions are welcome :-)
Thanks,
joe
UPDATE
For the record, the root cause of the issue was that the rpc.statd daemon died.
Hence, the native locking mechanism failed over NFS.
The symptom was an IOException with the message: "No locks available".
Kudos to Hans Maes

You could create your own implementation of Exception, which will log every error created. And then add it to the classpath with the -Xbootclasspath:bootclasspath flag. I wouldn't recommend it as a 'best practice' but at least you can find the source of your problem.
A very quick example (with room for improvement)
package java.lang;
public class Exception extends Throwable {
public Exception() {
super();
String exception = "Exception";
logWithStack(exception);
}
public Exception(String message) {
super(message);
logWithStack(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
logWithStack(message);
}
public Exception(Throwable cause) {
super(cause);
logWithStack(cause.getMessage());
}
protected Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
logWithStack(message);
}
private void logWithStack(String exception) {
System.out.println(exception);
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
}
Compile to a class file and then add -Xbootclasspath:/directoryWhereClassFileIsLocated/ to the tomcat options.

Related

Throwing exceptions through components, good practice?

When a sub method throws an exception, would encapsulation in a dedicated "package" exception be considered good pratice ?
public String doStuff() throws UtilsException {
try {
throw new NullPointerException("test");
} catch (NullPointerException e) {
throw new UtilsException("something occured", e);
}
}
//use this exception for all classes of this package / component
public class UtilsException extends Exception {
private static final long serialVersionUID = 1L;
public UtilsException() {
super();
}
public UtilsException(String message, Throwable cause) {
super(message, cause);
}
public UtilsException(String message) {
super(message);
}
public UtilsException(Throwable cause) {
super(cause);
}
}
Could Optional.empty() be an alternative to avoid throwing/catching of a complex app?
public Optional<String> doStuff() throws UtilsException {
try {
return Optional.of("ok");
} catch (NullPointerException e) {
LOG.error("Something append... {}", e.getMessage());
return Optional.empty();
}
}
First, you should never catch a NullPointerException (or runtime exceptions in general) an return someting else like you are doing.
Ok, maybe there are a very few cases where you need to do that (like a buggy third party api).
Exceptions like those (NullPointer, ClassCast, IllegalArgument, ect) happen when your program has a bug and you should let
them bubble up and handle them in some high order component of your program.
That being said, (and there comes the infamous phrase) it depends...
Exceptions are "responsible" for informing errors,thus they need to be informative for the caller will use them to decide what to do. Consider the following:
public void readFile(String path) throws IOException {
// read file content
return content;
}
try {
return readFile("foo.txt");
} catch(FileNotFound e) {
// For this specific scenario not finding the file is not a problem
return "";
} catch(IOException e) {
// This we are not expecting to happen, if the file exists we should be
// able to read it, otherwise we should inform the user.
log.error(e);
display("We had a problem reading the file, Check the file permissions and try again");
}
As you can see in the example above, you won't want to wrap the IOException in another exception in this case
because you will remove the client's ability to decide what to do when an error happened.
Also, note that the IOException is a form of "wrap" since exceptions are objects too you can use inheritance
to generalize what kind of errors your method throws and then throw more specific errors so the caller can
decide what to do.
When to wrap.
There are cases when wrapping exceptions is a good practice and is the way to go.
For example, if you are creating a lib whose main functionality is to get weather information.
For the first version you kept it simple and used a third party api to get the values for the day.
The main method of your api looks like this.
public Weather getWeather(Date day) throws HTTPException {
return weather.get(day);
}
Your api is doing pretty well but you noticed you're doing too much requests to the weather api and
you will have to start paying for it very soon. You then decided to cache the results in a database table
so you can reduce the amount of requests.
public Weather getWeather(Date day) throws HTTPException, SQLException {
Weather w = getFromCache(day);
if (w != null) {
return w;
} else {
return getAndCache(day);
}
}
Now you have a problem, you can't add this new exception to the throws statement because you will most certainly break
your api's users code.
And if you think about it, your api's users are no interested if you had problems getting the data from the wheter api or
from your cache, they just want to be informed of errors. This is a very good case to wrap those exceptions in
a more generic one, like WeatherFetchException.
As you can see, it really depends...
The rule of thumb to me is, keep your exceptions meaningful and if you want to wrap them, do only when
it makes sense and when it doesn't remove the caller's ability to handle errors.
Wrapping exceptions just for the sake of it is most definitely not a good practice.

Using specific try catch, error overrides

This is my Exception:
public class MyException extends Exception {
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
Now immagine the next scenario, the code is way too long to paste here:
1 I got a Presentation class made in Swing in Presentation package
2 In package calculations I made simple operations with few numbers from received database fields
3 In package connections I got the database connections
Trouble comes here:
-In presentation layer I catch all errors, like this:
try {
//here is a method called updateCombo() wich throws:
//throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
} catch (MyException ex) {
try {
//Here we process error code, if error is not defined, uses default errors.
processCode(ex);
} catch (MyException ex1) {
Logger.getLogger(Presentacion.class.getName()).log(Level.SEVERE, null, ex1);
}
}
processCode is a simple list with cases, like this:
private void processCode(MyException e) throws MyException {
switch (e.getErrorCode()) {
case "ERROR_UPDATING_COMBO_BOX":
lblErrorText.setText("Error updating combo.");
throw e;
case "ERROR_SELECTING_PRIMARY_KEY":
lblErrorText.setText("Error selecting PK");
throw e;
case "ERROR_OPENING_CONNECTION":
lblErrorText.setText("Error opening connection.");
throw e;
default:
lblErrorText.setText("Excepcion not defined: "+ e.getMessage());
e.printStackTrace();
}
This is the scenario, the connection fails in 3rd package and leads to this:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
As I said, the error is thrown to the upper layer with throws clause in method header, this beeing 2nd package.
2nd package also throws a new exception to Presentation, because of failing connection:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
Presentation methods also throw this exception becase 2nd layer failed:
throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
The main problem:
Using debug i found out that the program does what it has to do. It gets to the connection layer and does this successfully:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
But, in 2nd layer, calculations, if connection fails it throws a new exception:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
This is the problem:
throw new
throwing new exception overrides ERROR_OPENING_CONNECTION with ERROR_SELECTING_PRIMARY_KEY. When it gets to presentation due to its "throw new" overrides ERROR_SELECTING_PRIMARY_KEY with ERROR_UPDATING_COMBO_BOX, resulting in the final error shown in the screen:
lblErrorText.setText("Error updating combo.");
Is there any way to return to presentation once first error is caught without overriding by next errors?
Maybe I misunderstood the concept but I want to catch all possible errors because:
-If connection is OK but method in 2nd layer fails it should throw ERROR_SELECTING_PRIMARY_KEY.
-If 2nd layer (calculations) does it OK but there is error in presentation it should lead to ERROR_UPDATING_COMBO_BOX.
You can use e.getCause() which will return a Throwable and check if this cause belongs to MyException. In case it is, you can check the e.getCause() again recursively until you obtain the deepest error code in the stacktrace and perform the validation for this exception.
Here's an example:
public MyException getDeepestException(MyException e) {
Throwable t = e.getCause();
if (t instanceof MyException) {
return getDeepestException((MyException)t);
}
return e;
}
As pointed out by #RealSkeptic, in order to use this approach, you will need to add an additional constructor to your custom exception:
public MyException(String message, Throwable cause, String errorCode){
super(message, cause);
this.errorCode = errorCode;
}
And when throwing your exception, call the proper constructor:
try {
//...
} catch (SomeException e) {
throw new MyException(<a proper message should be here>, e, "ERROR_SELECTING_PRIMARY_KEY");
}
If I understand you correctly, if the exception caught by one package happens to be a MyException, you want the original MyException to be passed up, otherwise (if the exception is some other type of Exception) you want to create a new MyException.
In this case, you should have two catch clauses.
try {
// Whatever you do in the try clause
} catch ( MyException myEx ) {
throw myEx;
} catch ( Exception e ) {
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
}

auto log java exceptions

I have written a huge Web-Application and 'forgot' to include logging (I only print the errors with the standard e.printStackTrace() method).
My question is, if there is any method to auto-log (getLogger.LOG(SEVERE,"...")) any thrown exception?
maybe with a custom exception-factory like in exceptionFactory JSF?
I want to log every thrown exception with my logger, e.g. before the program enters the catch-block, the exception has to be logged already:
try{
...
} catch(Exception1 e){
//Exception must have been already logged here (without adding getLogger().LOG(...) every time)
System.out.println(e.printStackTrace());
} catch(Exception2 e){
//Exception must have been already logged here (without adding getLogger().LOG(...) every time)
System.out.println(e.printStackTrace());
}
Take a look at aspect oriented programming which can insert logging code at runtime for your favorite logging framework. The JDK includes the java.lang.instrument package which can insert bytecodes during classloading to perform your logging.
Otherwise, you can install a servlet Filter as the top most filter in the call chain which will catch most of your exceptions.
public class LogFilter implements javax.servlet.Filter {
private static final String CLASS_NAME = LogFilter.class.getName();
private static final Logger logger = Logger.getLogger(CLASS_NAME);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.entering(CLASS_NAME, "doFilter", new Object[]{request, response});
try {
chain.doFilter(request, response);
} catch (IOException | ServletException | RuntimeException | Error ioe) {
logger.log(Level.SEVERE, "", ioe);
throw ioe; //Keep forwarding.
} catch (Throwable t) {
logger.log(Level.SEVERE, "", t);
throw new ServletException(t);
}
logger.exiting(CLASS_NAME, "doFilter");
}
#Override
public void destroy() {
}
}
You can set uncaught exception handler for main thread and every other you create using Thread.setUncaughtExceptionHandler() method and do all the required logging there.
I am now also in front of new larger project and interested in elimination of not necessary code to be produced. First I wanted to log every entry and exit from method including input and output data. In my case of event driven architecture I am pushing these data to elastic and analyse continuously method processing timeouts, that is lot of code lines. So I handled this with AspectJ. Very nice example of this is here:
http://www.baeldung.com/spring-performance-logging
Same applies for auto Error logging, here is dummy example which I will extend to work with slf4j, but these are details:
public aspect ExceptionLoggingAspect {
private Log log = LogFactory.getLog(this.getClass());
private Map loggedThrowables = new WeakHashMap();
public pointcut scope(): within(nl.boplicity..*);
after() throwing(Throwable t): scope() {
logThrowable(t, thisJoinPointStaticPart,
thisEnclosingJoinPointStaticPart);
}
before (Throwable t): handler(Exception+) && args(t) && scope() {
logThrowable(t, thisJoinPointStaticPart,
thisEnclosingJoinPointStaticPart);
}
protected synchronized void logThrowable(Throwable t, StaticPart location,
StaticPart enclosing) {
if (!loggedThrowables.containsKey(t)) {
loggedThrowables.put(t, null);
Signature signature = location.getSignature();
String source = signature.getDeclaringTypeName() + ":" +
(enclosing.getSourceLocation().getLine());
log.error("(a) " + source + " - " + t.toString(), t);
}
}
}
I would be happy to hear what else is good example of boiler plate code reduction. I of course use Loombok which does superior task...
NOTE: do not reinvent wheel, so look here as other people collected usefull AOP to be reused in your project out of the box :-)) open source is great community: https://github.com/jcabi/jcabi-aspects

Throwing and logging Exceptions, a better way

Ultimately, i'd like to
if (badThingsHappen) {
log the issue
throw exception with description
}
The obvious redundancy here is that often exception description and the message to be logged is (often) the same.
This looks needlessly verbose
if (badThingsHappen) {
logger.error("oh no! not again!");
throw new AppException("oh no! not again!");
}
Declaring temporary String feels wrong
if (badThingsHappen) {
String m = "oh no! not again!";
logger.error(m);
throw new AppException(m);
}
Is it ok to have Exception's constructor handle the logging? Is there a better (cleaner) way?
You could use a utility method:
public class AppException extends Exception {
public static AppException logAndThrow(Logger logger, String message) throws AppException {
AppException e = new AppException(message);
// log the stack trace as well
logger.error(message, e);
throw e;
}
}
and the use it:
if (badThingsHappen) {
AppException.logAndThrow(logger, "oh no! not again!");
}
I usually prefer to log exceptions when I catch them, rather then when I throw them.
This cleans up the logs quite a bit more, and also lets the "client" code handle the exception and information output much more precisely, since the information you want to associate with the exception when logging can be dependent of context.
If you do want to log as soon as it happens, I would build the exception and log it before throwing, something like:
if(badthingshappen){
Exception e = new Exception("holy $%##");
logger.log(e);
throw e;
}
A bit verbose yes... but this is java.
Typically when working with Exceptions and logging requirements I include logging support in the Exceptions.
Exceptions typically inherit from a Base Exception class in our project and it has hooks for logging log4j or other logging utilities.
class Problem extends java.lang.Exception {
private boolean debug=false;
public Problem(String message) {
if(debug) {
logging.exception(message);
/* Maybe a stack trace? */
}
}
}
I just wrote an error-logging method myself, today (this is used to log errors if they occur in a listener method, so it's also logging the method in which the error occurred and the object in which the listener is implemented to help tracking):
protected void listenerError(String listenerMethodName, Object listener,
RuntimeException e) {
logger.error("Exception while calling " + listenerMethodName
+ " on object " + listener, e);
throw e;
}
I wrote it in the class in question (or the base class, to be exact), because you probably want to use the logger in that class (and all subclasses). Another option would be to create a utility method in a utility class (I would not write an Exception class for it), and provide the logger as parameter:
class ExceptionUtil {
public static error(Exception e, Logger logger) {
logger.error(e);
throw e;
}
}
You can, of course, provide the method and object as params for this method (or an overloaded version of it), as necessary.

correctly printstacktrace of servlet exception

so i am using a filter to catch servlet exception (because we are using a mix of jsf/plain servlets)
when catching the ServletException and calling printstacktrace most of the information is lost.
the "true" root exception seems to be hidden behind the "funny" expression
((ServletException) e.getRootCause().getCause()).getRootCause().getCause().getCause().getCause()
this is clearly not the way to do it.
is the an easy way to print the "full" information of such an exception.
can someone explain me why the exception is wrapped this way?
Take a look at the ExceptionUtils class from commons-lang. It contains several useful methods for printing the entire chain of exceptions.
after i had a look at ExceptionUtils, this solved the problem!
final StringWriter stacktrace = new StringWriter();
ExceptionUtils.printRootCauseStackTrace(throwable,new PrintWriter(stacktrace));
msg.append(stacktrace.getBuffer());
this prints out the full stacktrace with every piece of information that is relevant.
That is called exception chaining. By wrapping an exception in a different exception you can let exceptions bubble up the stack without having your main application classes to worry about some low-level exceptions.
Example:
public void doStuff() throws StuffException {
try {
doDatabaseStuff();
} catch (DatabaseException de1) {
throw new StuffException("Could not do stuff in the database.", de1);
}
}
This way your application only has to handle StuffException but it can get to the underlying DatabaseException if it really needs to.
To get to the bottom-most (and all other) exception(s) of an exception you caught you can iterator over its root causes:
...
} catch (SomeException se1) {
Throwable t = se1;
logger.log(Level.WARNING, "Top exception", se1);
while (t.getCause() != null) {
t = t.getCause();
logger.log(Level.WARNING, "Nested exception", t);
}
// now t contains the root cause
}
Exception chaining for ServletException is tricky. Depending on the web server implementation and web development framework in use, at runtime the chain may use cause and/or rootCause. This link explains it very well. To complicate things, I've seen exceptions where the cause points to the exception itself.
Here's a recursive method we have used that covers all bases for ServletExceptions:
public static Throwable getDeepCause(Throwable ex) {
if (ex == null) {
return ex;
}
Throwable cause;
if (ex instanceof ServletException) {
cause = ((ServletException) ex).getRootCause();
if (cause == null) {
cause = ex.getCause();
}
} else {
cause = ex.getCause();
}
if (cause != null && cause != ex) {
return getDeepCause(cause);
} else {
// stop condition - reached the end of the exception chain
return ex;
}
}

Categories

Resources