Monday, November 19, 2012

Implement Logging with log4j in Java Console Application using Eclipse IDE

Logging is a very important part of programming that provides advanced debugging capabilities and structured organisation of information recorded at the run time. If I say debugging, you may ask "Why not System.out.println (SOP)?". SOP is a powerful debugging technique that helps to troubleshoot all the errors at the time of development. But when you implement your application in a real time environment, unexpected results and exceptions might occur. Logging provides you an effective mechanism to track all the errors that occurs in your application after you deploy it, so that you can understand what went wrong with your application.

Log4j is an effective open source Logging API that is written in Java by the Apache Software Foundation. All logging API's share a common architecture that consists of three main components,

log4j_architecture
log4j Components
1. Loggers: Loggers are responsible for capturing logging information
2. Appenders: Through appenders you tell the system on where to log the information such as files, database.etc.
3. Layouts: Layouts enable you to specify the format or displaying style of logging information.

In this post, I am going to provide step by step instructions for implementing logging with log4j in a simple Java Application using Eclipse IDE with appropriate code and screenshots.

1. First of all download the latest version of log4j and unzip it.Locate  log4j-xxx.jar file where xxx denotes the version of log4j release you have downloaded.

2. Open Eclipse IDE and create a Java Project and name it. In this example I have named it as "LoggingExample".


3. Create a package under the default package, by right clicking on 'src' in Package Explorer > New > Package, I have named this package as 'test'.

4. Next step is to add the log4j-xxx.jar you have downloaded to the application you have just created. To do this, right click on the project in Package Explorer > Build Path > Configure Build Path

In the Java Build Path dialogue, go to Library tab, Click Add External JARs and add the log4j-xxx.jar > Click OK.

Now the log4j jar file is available to be used in your application.

5. Now create a file named as "log4j.properties" in your default package where all your source code is placed. This is the file that is going to hold all the configuration settings for log4j implementation for all classes in your application. To do this, right click the default package, in this case 'src' in package explorer > New > File >File Name: log4j.properties
6. Copy the below code to the log4j.properties file you just created

# Log levels
log4j.rootLogger=INFO,CONSOLE,R
# Appender Configuration
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# Pattern to output the caller's file name and line number
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
# Rolling File Appender
log4j.appender.R=org.apache.log4j.RollingFileAppender
# Path and file name to store the log file
log4j.appender.R.File=./logs/testlog.log
log4j.appender.R.MaxFileSize=200KB
# Number of backup files
log4j.appender.R.MaxBackupIndex=2
# Layout for Rolling File Appender
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d - %c - %p - %m%n

Explanation to the above configuration file

First step is to define the log level. Log4j logs messages at six different levels. For example, if you have a program that generates lot of warning messages then you can ignore them by setting the log level to ERROR to avoid the log file getting more clumsy. The log levels and the priority is as follows,

TRACE < DEBUG < INFO < WARN < ERROR < FATAL

If you specify the log level as WARN, then the INFO, DEBUG and TRACE log level messages will be omitted while the WARN, ERROR and FATAL log level messages will be logged. In our example we have set the log level as DEBUG which means TRACE level logs will not be logged.

Next comes the appender settings. I have used two appenders, Console Appender and Rolling file appender. This means my log information will be displayed on the console as well as stored in a file. Since we have used RollingFileAppender, log4j will open a new file whenever the log file reaches the maximum file size of 200 KB mentioned in R.MaxFileSize property and the old one will be backed up. You can specify the number of backup files in the R.MaxBackupIndex property.

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.R=org.apache.log4j.RollingFileAppender

You can also use other appenders, like JDBCAppender,SocketAppender,SysLogAppender etc. according to your requirement to route the logging information to appropriate destinations.

Each appender is associated with layout settings that specifies the format of information that is being logged. I have used PatternLayout for both the appenders and have defined two different patterns for each of them. For console appender,

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

where,
%5p - Priority of the logging event
%t - Name of the thread that initiated the logging event
%F- File name where the logging issue was requested
%L - line number that caused the logging message to be generated

Sample output of the above layout:
WARN [main] (Main.java:14) - Variable is not initiated!


You can also use other layouts such as HTMLLayout, DateLayout, XMLLayout etc.
7. Last step is to incorporate logging in your java class. To do this, Create a Class in the package you have created in Step 3. Right Click the package > New > Class > Class Name: LoggingSample.java

Now Copy and Paste the below code in LogginSample.java class.

package test;
import org.apache.log4j.Logger;
import java.io.*;
public class LoggingSample {
 private static Logger logger=Logger.getLogger("LoggingExample");
  public static void main(String[] args){
   try{
      FileInputStream fstream = 
                         new FileInputStream("D:\\textfile.txt");
      DataInputStream in = 
                         new DataInputStream(fstream);
      BufferedReader br = 
                  new BufferedReader(new InputStreamReader(in));
      String strLine;
      while ((strLine = br.readLine()) != null){
    System.out.println (strLine);
      }
      in.close();
   }catch (FileNotFoundException fe){
    logger.error("File Not Found",fe);
        logger.warn("This is a warning message");
        logger.trace("This message will not be logged since log  
                      level is set as DEBUG");
   }catch (IOException e){
    logger.error("IOEXception occured:", e);
  }
 }
}



In the above code I am trying to read a file which does not exist. The log that is generated
on the console is,

ERROR [main] (LoggingSample.java:19) - File Not Found
java.io.FileNotFoundException: D:\textfile.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at test.LoggingSample.main(LoggingSample.java:10) 
WARN [main] (LoggingSample.java:20) - This is a warning message
At the same time log file is generated at \workspace\LoggingExample\logs\testlog.log with the following content,


2012-07-21 23:58:21,694 - LoggingExample - ERROR - File Not Found
java.io.FileNotFoundException: D:\textfile.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at test.LoggingSample.main(LoggingSample.java:10)
2012-07-21 23:58:21,699 - LoggingExample - WARN - This is a warning message

Please note that in the above output, TRACE level message is not generated since it's priority is lower than that of DEBUG level which we have set in our log4j.properties file, while WARN level message is logged since it's priority is higher than that of DEBUG level.

Keyboard shortcuts to Java IDEs



This blog is about useful keyboard shortcuts for Top 5 Java IDEs. Java is an highly scalable and platform independent programming language, which is used by almost every programmer in the world. Since it comes under open source category it has always been the first choice for every programmer around the world. Hence, knowing the keyboard shortcuts for the Java IDE of your choice will not only increase your productivity but will give you more time for the things you like to do. Here I have listed about some useful keyboard shortcuts for 5 most used Java IDEs.

Let me first list out the top 5 Java IDEs, 
  1. NetBeans 
  2. Eclipse
  3. IntelliJ IDEA
  4. My Eclipse
  5. IBM RAD

NetBeans Shortcuts

  1. Ctrl-Space                                 Code completion
  2. Esc                                           Close code completion
  3. Shift-Space                               Enter a space without expanding an abbreviation
  4. Alt-F1                                       Display Javadoc
  5. Shift-F1                                    Search Javadoc
  6. Alt-Shift-I                                  Import class
  7. Alt-G                                        Go to declaration
  8. Alt-O                                        Go to source
  9. Crtl-;                                        Add semicolon to the line on cursor
  10. F9                                            Compile selected file/package
  11. Ctrl-Shift-F9                             Compile project
  12. Alt-Shift-C                                Stop compilation
  13. F6                                            Run selected file
  14. Ctrl-Shift-F6                              Run project

Eclipse Shortcuts

  1. Ctrl-1                                      Quick fix errors
  2. Ctrl-T                                      Find class (From jar files also)
  3. Ctrl-R                                      Find resource files
  4. Ctrl-Shift-O                             Organize imports
  5. F3                                           Go to declaration
  6. Ctrl-/                                      Commenting and Uncommenting lines
  7. Ctrl-Shift-F                              Text Formatting
  8. Ctrl-E                                      Switch to other open editors
  9. Ctrl-W                                     Close current file
  10. Ctrl-D                                      Delete a line
  11. Ctrl-Q                                      Go to last modified line

IntelliJ IDEA Shortcuts

  1. Alt-F1                                      Switch between views(Project,Structure.etc)
  2. Alt-Home                                 Show Navigation Bar
  3. Ctrl-J                                      Insert a live template
  4. Alt-Enter                                  Quick fix
  5. Ctrl-Space                                Invoke Code Completion
  6. Ctrl-N                                       Find Class by name
  7. Ctrl-D                                       Duplicate the current line or selection
  8. Ctrl-Shift-Enter                         Smart Statement Completion

MyEclipse Shortcuts

  1. Shift-Ctrl-E                               Switch to Editor
  2. Ctrl-F10                                    Show view menu
  3. Shift-Ctrl-/                               Add Block comment
  4. Shift-Ctrl-M                              Add Import
  5. Shift-Alt-J                                Add Javadoc comment
  6. Ctrl-F11                                    Run
  7. F3                                            Open Declaration
  8. Shift-F2                                    Open attached JavaDoc
  9. Ctrl-1                                       Quick Fix
  10. Alt-/                                         Word Completion
  11. Ctrl+B                                       Build All

IBM RAD Shortcuts

  1. Ctrl-1                                     Quick Fix
  2. Ctrl-/                                     Comment
  3. Ctrl-\                                      Uncomment
  4. Ctrl-E                                     Next Problem
  5. Ctrl-Shift-E                             Previous Problem
  6. Ctrl-F11                                  Run
  7. Ctrl-U                                     Run Snippet
  8. Ctrl-Space                              Content Assist

AJAX with Servlets using JQuery and JSON




In my previous post, I explained about making AJAX calls to a servlet from a JSP page and updating a part of the JSP page with the response from the Servlet. That was a very simple example I provided in that post by returning a piece of text from the servlet to JSP to start with, and now in this post I am going to add something more to it by making the servlet return complex Java Objects such as lists, maps, etc. To do this, let us get introduced to JSON(Javascript Object Notation), in addition to JQuery and AJAX. JSON is derived from Javascript for representing simple data structures and associative arrays, called objects. Here in our scenario, we are going to use a JSON library in Servlet to convert Java objects (lists,maps,arrays.etc) to JSON strings that will be parsed by JQuery in the JSP page and will be displayed on the web page.


There are many JSON libraries available that can be used to pass AJAX updates between the server and the client. I am going to use google's gson library in this example. 

Now, let us create a simple JSP page with two drop down lists, one that contains values for countries and the other that is going to be populated with values for states based on the value of country selected in the first drop down list. Whenever the value is selected in the "country" drop down list, the "states" drop down list will be populated with corresponding state values based on the country selected. This has to be done without a page refresh, by making AJAX calls to the servlet on the drop down list change event.

Here are the steps to reproduce in Eclipse,

1. First of all create a "Dynamic Web Project" in Eclipse.
2. Create a new JSP page under "Webcontent" folder and copy paste the below code in it.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>AJAX calls to Servlet using JQuery and JSON</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
    $(document).ready(function() {
        $('#country').change(function(event) {  
        var $country=$("select#country").val();
           $.get('ActionServlet',{countryname:$country},function(responseJson) {   
           var $select = $('#states');                           
               $select.find('option').remove();                          
               $.each(responseJson, function(key, value) {               
                   $('<option>').val(key).text(value).appendTo($select);      
                    });
            });
        });
    });          
</script>
</head>
<body>
<h1>AJAX calls to Servlet using JQuery and JSON</h1>
Select Country:
<select id="country">
<option>Select Country</option>
<option value="India">India</option>
<option value="US">US</option>
</select>
<br/>
<br/>
Select State:
<select id="states">
<option>Select State</option>
</select>
</body>
</html>


3. Download google's GSON library from here and place it in your project's WEB-INF/lib folder.
4. Create a servlet in the name 'ActionServlet' (since I have used this name in the jquery code above') in the src directory. Copy and paste the below code in the doGet() method of the servlet and add the import statement in the header section of the servlet.


import com.google.gson.Gson;

protected void doGet(HttpServletRequest request,   HttpServletResponse response) throws ServletException, IOException {

  String country=request.getParameter("countryname");
  Map<String, String> ind = new LinkedHashMap<String, String>();
    ind.put("1", "New delhi");
    ind.put("2", "Tamil Nadu");
    ind.put("3", "Kerala");
    ind.put("4", "Andhra Pradesh");
    
    Map<String, String> us = new LinkedHashMap<String, String>();
    us.put("1", "Washington");
    us.put("2", "California");
    us.put("3", "Florida");
    us.put("4", "New York");
    String json = null ;
    if(country.equals("India")){
     json= new Gson().toJson(ind);   
    }
    else if(country.equals("US")){
     json=new Gson().toJson(us);  
    }
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);       
 }

}


In the above code, we create two maps for two countries, and return the one based on the country parameter passed to the servlet in the AJAX call made by the JQuery's get() method. Here we convert the map objects to json strings in order to send the response back to the JSP page.

5. Make sure you have done servlet mapping properly in web.xml file. An example of this is given below,

<servlet>
    <servlet-name>ActionServlet</servlet-name>
    <servlet-class>ajaxdemo.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ActionServlet</servlet-name>
    <url-pattern>/ActionServlet/*</url-pattern>
</servlet-mapping>

In the above code,'ajaxdemo' is the package name in which I have created the servlet. Replace it with your package structure to make the servlet work properly.


Thats it! You are now all set to run the project with Tomcat. When you run this project, the second drop down list will be populated automatically when you change the value in the first drop down list. 
Output Screenshots:
First drop down list changing,


On selecting 'India' in the first drop down list,


On selecting 'US' in the first drop down list,


Please leave your comments and queries about this post in the comment sections in order for me to improve my writing skills and to showcase more useful posts.