I am creating a java application in which there is a possibility that exceptions might be thrown. I am handling these exceptions in a try-catch block and printing appropriate messages so that the business users don't have to see the ugly stack trace in case of a failure.
But now when I debug, I would like to invoke the JAR file in such a way that it will print the stack traces for me, so that I can know where exactly the problem lies.
Can someone enlighten me on how this can be achieved?
Why not use Logging levels.?
DEBUG for your technical errors and INFO or ERROR with the business codes that your users understand.
You could use slf4j as a facade in order to be able to change quickly implementations and logback as the implementation for your logging. The combination of slf4j and logback are currently a very efficient logging system. In case you would want to use another implementation such as log4j, JDK 1.4, or Jacarta Commons logging you could just change the jar of the implementation(binding) with the one you want. It follows a quick user manual of how to use slf4j with logback.
First of all you should import the necessary jars that are required to use slf4j.
Eclipse Guide
Go to your project in eclipse and right click on it. Select Properties.
From the left panel select Java Build Path
Select Libraries tab
Click Add External Jars
Locate your extracted folders and add logback-core-1.0.7.jar, logback-classic-1.0.7.jar from the logback-1.0.7 folder and slf4j-api-1.7.0.jar from the slf4j-1.7.0 folder. Click ok to return to the project.
Netbeans Guide
Go to your project in Netbeans and right click on it. Select Properties.
From the left panel select Libraries
Select Compile tab
Click Add Jar/Folder
Locate your extracted folders and add logback-core-1.0.7.jar, logback-classic-1.0.7.jar from the logback-1.0.7 folder and slf4j-api-1.7.0.jar from the slf4j-1.7.0 folder. Click ok to return to the project.
*In case you are not using any of the above environments you should add the above 3 jars in your classpath manually. Dependening your operating system there is a different procedure to follow.
First of all you should import the required dependencies:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Each class that you would like to log should have a private logger:
private final Logger logger = (Logger) LoggerFactory.getLogger(this.getClass())
By having a seperate logger for each class you provide more flexibility and easier change of your logging levels(WARN,ERROR,INFO,DEBUG).
According to the log level that would like to use you should have
logger.info("Your info message");
logger.error("Your error message");
logger.debug("Your debug message");
logger.warn("Your warn message");
There is also the possibility to use more complex method calls dependening on your needs. For example if you want to debug and show also the stacktrace you should use
logger.debug("Your debug message",e);
(e stands for a catched exception).
For example:
try{
//some code
}catch (IOException e){
logger.debug("An IOException was thrown at this method ",e);
logger.error("An IOException was thrown at this method ",e);
}
*At this point without adding any other configuration you have a simple logging system. In case you want more advanced configuration read the advanced settings of logback that i have posted below.
In order to have a more advanced logging system you should create an additional file which will contain all the logging configuration. For this example i am going to use the logback.xml. For more info regarding the different files of logback please refer to logback configuration.
At this point you should create a folder named resources and add it in the buildpath of your project.
Eclipse Guide
Create a folder named resources(You must see the folder in your project)
Go to your project in eclipse and right click on it. Select Properties.
From the left panel select Java Build Path
Select Source tab
Click Add Folder
Tick the resources folder that you have created and click ok. Click ok to return to the project.
At this point you should see the resources folder as a package.
Netbeans Guide
Create a folder named resources(it will not be visible yet on the projects view..Only in the files view)
Go to your project in Netbeans and right click on it. Select Properties.
From the left panel select Sources
In the Source package folders click Add Folder.
Select the resources folder and click ok.
You should see the folder created as a package.
*The name of the folder could be any name that you like. For convenience i named it resources.
The following applies in both Eclipse and Netbeans.
*In case you will not have the following file in your classpath which specify specific settings in the logging framework, the root logger level is automatically assigned in DEBUG. That means that all the logging levels are going to be logged. Debug is the higher level.
Inside logback.xml place the following tag.
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>[%-5level] - %msg%n
</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<append>false</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %class - %msg%n
</pattern>
</encoder>
<File>log/log.txt</File>
</appender>
<logger name="org.test" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.test" level="DEBUG" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="OFF">
</root>
The above configuration contains 2 different appenders,one in the console and one in a file named log.txt. The file is going to be placed in a folder named log. In case the folder log does not exist is going to be created automatically.
The pattern that you are going to use depends on you and how informative your messages will be. In the current configuration the console appender is less descriptive and shows only the logging level and the message, comparing to the file appender which contains logging level, thread name, class name, time and message. The value append is set to false in order to create a new log file after every run of your application.
The above configuration uses 2 different loggers for the same package. The first logger prints only the info messages in the console and the second logger prints the debug messages to a file. This is achieved by using the filter that is placed inside the appenders.
*In the logger name you can have the fully qualified name of your class or the package name. In this case i assumed package structure org.test and placed the class inside this package. If you have the fully qualified name of the class the logging configuration will be applied only for this class. In case you use the package name, all the classes inside this package are going to follow the above configuration.
There are many different ways to use the appenders and loggers and it depends in your needs and the complexity of your program. According to the situation that you described i believe that above solution could meet your needs.
P.S. For more descriptive definitions and more advanced configurations you could refer to the Logback manual
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With