Monday, September 24, 2012

SLF4J doesn't log Exception stackTrace! Why?

A lot of people knowing slf4j do logging with string formatting for several reasons: mainly readability and performance. Using slf4j (and many other logging frameworks, too) we can transform this log statement:
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger()
    public static void main(String[] args) {
        log.info("Main is started with " + args.length + " arguments");
    }
}
into this:
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger()
    public static void main(String[] args) {
        log.info("Main is started with {} arguments", args.length);
    }
}

The log of an exception should always contain the stack trace, so we can write the following code:
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger()
    public static void main(String[] args) {
        log.info("Main is started with {} arguments", args.length);
        try {
            throw new RuntimeException("Do you now to log my stackTrace?");
        } catch (Exception e) {
            log.error("{} No, I don't!", e.getMessage(), e);
        }
    }
}
Are there any errors? No!? Yes, it compiles and runs as you wish... but?! Where is the stackTrace for the RuntimeException raised? The answer is simple: unfortunately slf4j does not provide methods with signatures like these:
  • [logLevel](String format, Object object, Throwable t)
  • [logLevel](String format, Object[] object, Throwable t)
So one solution is to write code this way:
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger()
    public static void main(String[] args) {
        log.info("Main is started with {} arguments", args.length);
        try {
            throw new RuntimeException("Do you now to log my stackTrace?");
        } catch (Exception e) {
            log.error(e.getMessage() + " Yes, I do!", e);
        }
    }
}

Don't you like it? Below the elegant solution:
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger()
    public static void main(String[] args) {
        log.info("Main is started with {} arguments", args.length);
        try {
            throw new RuntimeException("Do you now to log my stackTrace?");
        } catch (Exception e) {
            log.error("{} Yes, I do!", new Object[] {e.getMessage(), e});
        }
    }
}

The moral of the story is: always be careful about methods' signature.

Related posts:

Tuesday, September 18, 2012

Google Guava and Preconditions

In my previous article I talked about "single line else", now I'll share with you how to avoid the tedious code writing of input control blocks.

Google Guava library allows you to avoid the writing of classic if throw.
For example, code like this:
    public static int division(int a, int b) {
        if(b == 0)
            throw new IllegalArgumentException("Cannot divide by zero.")
        return a / b;
    }

With Guava becomes:
    public static int division(int a, int b) {
        Preconditions.checkArgument(b != 0, "Cannot divide by zero.")
        return a / b;
    }
Pay attention to the condition b != 0, the library allows you to formerly define a precondition so the variable b will be checked for the expected values instead of the exceptional ones.
Guava Preconditions utility methods are a lot, one for each type of exception, so you can write a big variety of if then throw, here's the list:


Related posts:

Saturday, September 15, 2012

Spring Data JPA for Repositories

Do you know repository patterns? Regardless of the answer to this question, you'll like Spring Data JPA.

What is it? A simple framework that lets you avoid the implementation of Repositories over a jpa project.

I don't want to write anything else, the extensive Spring Data JPA documentation should answer to any of your questions, read and enjoy!

Monday, September 10, 2012

Coding: Why I hate "single line else"

Have you ever seen code like this?
    public class B {
        boolean state;
        int value;
        String text;
    }
    public void method1(B b) {
        if (b.state) {
            //do something
            //do a lot of work 
        } else {
            log.info("Nooo! b.state illegal value... skip");
        }
    }
or like this?
public void method2(B b) {
        if (b.state) {
            //do something
            //do a lot of work 
        } else {
            throw new RuntimeException("Nooo! b.state illegal value");
        }
    }
or like this?
    public int method3(B b) {
        int result;
        if (b.state) {
            //do something
            //do a lot of work
            result = 1;
        } else {
            log.warning("Nooo! b.state illegal value");
            result = -1;
        }
        return result;
    }
This is what I named, often improperly, "single line else".
Maybe you are not interested in my opinion, but I hate this kind of coding style.
I don't understand why some people write code like that, maybe this people like tabbing code or like to make me forget what condition is related to the last statement.

So maybe now you are thinking that I have a short memory, and this is true, but what happens if code is not as short as "Method 1/2/3" and moreover contains more nested statement than above? Now I'll show you "Method X"!

    public void methodX(B b) {
        if (/* expected condition 1 */) {
            if (/* expected condition 2 */) {
                if (/* expected condition 3 */) {
                    //do work
                } else {
                    throw new RuntimeException("Unexpected condition 3");
                }
            } else {
                throw new RuntimeException("Unexpected condition 2");
            }
        } else {
            throw new RuntimeException("Unexpected condition 1");
        }
    } 
In my honest opinion logthrow and return based on a condition must be done in the if block instead of else, with only few exceptions. Method X could be written in the equivalent form:
    public void methodX(B b) {
        if (/* NOT expected condition 1 */)
            throw new RuntimeException("Unexpected condition 1");
        if (/* NOT expected condition 2 */)
            throw new RuntimeException("Unexpected condition 2");
        if (/* NOT expected condition 3 */)
            throw new RuntimeException("Unexpected condition 3");
        //do work
    }
When I see the longest Method X, often, the same person who wrote it, also codes like this:
    public int method4(B b) {
        int value = b.value;
        if (b.state) {
            return value * 2;
        } else {
            return value / 2;
        }
    }
Besides being able to write it as Method 4 - B
    public int method4(B b) {
        int value = b.value;
        if (b.state) {
            return value * 2;
        }
        return value / 2;
    }
This kind of code could seem same code as before but it isn't, it is worse than Method 4 - A. Writing double return in a logical if else is another thing I hate. If applications logic needs to switch between two conditions to do some work it must contain a single return producing code like this:
    public int method4(B b) {
        int result = b.value;
        if (b.state) {
            result *= 2;
        } else {
            result /= 2;
        }
        return result;
    }

Finally think to this code:
    public int method5(B b) {
        int value = b.value;
        if (b.state) {
            return value * 2;
        } else {
            return value;
        }
    }
in this case it's not a logical double return so i like to convert Method 5 - A into Method 5 - B:
    public int method5(B b) {
        int result = b.value;
        if (b.state) {
            result *= 2;
        }
        return result;
    }
Avoid the "single line else" is what I think and I say: "A person's mind changes now and then so let's everybody try to change our mind", this applies to me too. Keep this post easy!

Related posts:

Wednesday, September 5, 2012

How to deploy/import your maven test jar

A little useful maven feature. Using maven, you can produce and deploy your test-jar that could be used in other projects just by importing it.

Below the snippet, taken from apache maven mini guide attached-tests.

    [your group id]
    [your artifact id]
    [your version]
    
        
            
            maven-jar-plugin
                
                    
                        
                            test-jar
                        
                    
                
            
        
    

How to import? It's simple:

    
        
            [your group id]
            [your artifact id]
            [your version]
            test-jar
            test
        
    

Sunday, September 2, 2012

State of the art of logging in maven project

Yes! Another little maven snippet to copy and paste.
This code snippet enables your maven project to work with latest slf4j and logback version. You must remember to add exclusions for modules that import log4j, JCL.

    
        
            
                org.slf4j
                slf4j-api
                ${slf4j.version}
            
            
                org.slf4j
                jcl-over-slf4j
                ${slf4j.version}
            
            
                org.slf4j
                jul-to-slf4j
                ${slf4j.version}
            
            
                org.slf4j
                log4j-over-slf4j
                ${slf4j.version}
            
            
                ch.qos.logback
                logback-classic
                ${logback.version}
            
        
    
    
        
            org.slf4j
            slf4j-api
        
        
            org.slf4j
            jcl-over-slf4j
        
        
            org.slf4j
            jul-to-slf4j
        
        
            org.slf4j
            log4j-over-slf4j
        
        
            ch.qos.logback
            logback-classic
        
    
    
        UTF-8
        1.6
        1.6
        1.7.2
        1.0.7