auto log java exceptions - java

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

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.

Logging all thrown Exceptions in a web application in Tomcat

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.

GWT Catching exception thrown by HttpServlet

From the server Code (in an HttpServlet) I'm throwing an exception if the file is too large:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
// Check if the blob has correct size, otherwise delete it
final BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
long size = blobInfo.getSize();
if(size > 0 && size <= BasicConstants.maxImageSize){
res.sendRedirect("/download?blob-key=" + blobKey.getKeyString());
} else { // size not allowed
bs.delete(blobKey);
throw new RuntimeException(BasicConstants.fileTooLarge);
}
From the client code I'm missing to successfully catch the exception with this snippet:
try {
uploadForm.submit(); // send file to BlobStore, where the doPost method is executed
} catch (Exception ex) {
GWT.log(ex.toString());
}
However, from this other client code snippet I'm somehow detecting when the exception was thrown with an ugly workaround that I don't trust at all:
uploadForm.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
// This is what gets the result back - the content-type *must* be
// text-html
String imageUrl =event.getResults();
// This ugly workaround apparently manages to detect when the server threw the exception
if (imageUrl.length() == 0) { // file is too large
uploadFooter.setText(BasicConstants.fileTooLarge);
} else { // file was successfully uploaded
...
}
The Development Mode view in Eclipse reports an error of type "uncaught exception", which suggests that I'm really doing a bad job at detecting it.
Can anyone tell me how to properly catch the exception, and if the workaround I'm using makes any sense?
Thanks!
Your first attempt
try {
uploadForm.submit(); // send file to BlobStore, where the doPost method is executed
} catch (Exception ex) {
GWT.log(ex.toString());
}
doesn't work, because submit() doesn't wait until the browser receives the response (it's an asynchronous call).
uploadForm.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
...
Here you actually receive the response from the server. But it's a form submission, not a GWT-RPC call, so the result is just plain text, not GWT Java Objects.
When you throw a RuntimeException in a Servlet, the server will simply send a response with an error code (probably '500', but ideally use the "Network" tab in Firebug or Chrome Developer Tools to see the actual response and response code.) So in the success case you'll get the URL, otherwise the response is empty.
Possible solution
You can catch Exceptions on the server side, and send better descriptions explicitly:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
...
if (...) {
throw new MyTooLargeException();
} else {
...
res.getWriter().write("ok " + ...);
}
} catch (MyTooLargeException e) {
res.getWriter().write("upload_size_exceeded"); // just an example string
// (use your own)
res.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
}
}
Then, on the client, check for
"upload_size_exceeded".equals(event.getResults()).

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.

Detecting when a handler couldn't be started when embedding Jetty

I'm embedding Jetty in a similar manner as described here. When the RequestLogHandler can't open the specified logfile, it throws an exception which is unfortunately caught by org.eclipse.jetty.server.Server and swallowed (but logged first, at least). This means that there's no obvious way for me to tell if the log handler was started correctly.
Is there a way that I'm missing to detect when a handler couldn't start?
This idea is based on the implementation of WebAppContext where you can use WebAppContext.getUnavailableException() to determine whether the context was initialized successfully.
Simply replace the default implementation of Server and Context with your own:
public static class MyContext extends Context {
private Exception _exception;
#Override
protected void doStart() throws Exception {
try {
super.doStart();
} catch (final Exception e) {
_exception = e;
}
}
#Override
protected void doStop() throws Exception {
try {
super.doStop();
} finally {
_exception = null;
}
}
public Exception getException() {
return _exception;
}
}
public static class MyServer extends Server implements InitializingBean {
public void afterPropertiesSet() throws Exception {
start();
for (final Handler h : getHandlers()) {
if (h instanceof MyContext) {
final MyContext c = (MyContext) h;
if (c.getException() != null) {
throw new RuntimeException("failed to init context " + c.getDisplayName(),
c.getException());
}
}
}
}
}
In your beans.xml, simply replace org.mortbay.jetty.Server (and remove init-method="start") and org.mortbay.jetty.servlet.Context with your own implementations.
This code is for Jetty 6 though (as is the example you linked to), as that's what I have around. I didn't test it though, but it's pretty much the same as we are successfully using in conjunction with WebAppContext. In order to extend this to RequestLogHandler, you could either do the same for just any handler you are using or create a decorator to wrap any handler. You may want to look at org.mortbay.jetty.handler.HandlerWrapper for this purpose.
How about modifying the jetty code? You could add some simple println statements in strategic places in the RequestLogHandler which would indicate to you whether or not the handler was started.

Categories

Resources