Pages

Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, June 6, 2013

Online server console viewer with Ajax long polling.

This post will give you small web application which brings the real time server console to the browser.  I am going to explain you, how to run this web application as it is and also if you want to add more customization, how to build the project using the source.

The Comet concept

This application a demonstrative usage of the Comet concept introduced by  Alex Russell in 2006. Once you get the idea, you can develop innovative applications and make use of it with your web application. For example, Facebook, it shows new friend requests, inbox updates and notifications on time. That is one of the real time usage of Comet approach.

The Comet is a web application model which always keeps live  connection with the server and let the server push the data to the browser through that connection. The browser does not explicitly request specific data. It just keeps live connection with the server. What ever the data pushed (or published) by the server are carried to the browser through that open connection. Also this concept is know as Ajax-Push, Reverse-Ajax, Two-way-web, HTTP Streaming, HTTP-server push.

There are several  ways of implementing Comet model. The CometD is a java framework  developed by Dojo Foundation which implements the Comet concept with 'XMLHttpRequest long polling'. This works with all modern browsers which supports XHR. With XHR long polling, the browser makes an asynchronous request to the server and if there are data available at the server, the response will bring that data to the browser as XML or JSON. After processing the response at client side, browser makes another XHR to poll more available data from the server.

If you have frequent data changes on the server and want to update browsers, the comet approach will be a best fit, because this can be pretty network intensive, and you often make pointless requests, though nothing has happened on the server. For example, frequent stock market information can be published to many users as soon as latest information is available. 

How the application works?

This application keeps reading the specified server log file line by line and push collected chunk of lines to the browser as a one string. By default, the application reads the Tomcat's catalina.out file. Server runs a timer which is set to every one second and executes these log file reading function. It collects  all the lines read within a one second and push to the client. In the client side, application keeps appending new contents to HTML DIV element. The server function will always reads only the newly appending lines of the the log file.

How to run the application?

If you are using Tomcat, you can experiment this application without much worrying. You just need to download the 'console-viewer.war' file and deploy it in your Tomcat container. If you are testing this with your local configuration, point your browser to following URL.

http://localhost:8080/console-viewer

Click on 'Connect' button and keep looking while you are accessing some deployed application. You will see the Tomcat's console on your web browser. Keep in mind, by default, this application reads 'catalina.out' file. So you need to start the Tomcat with ./startup.sh command. If you are appending your application's logs into different log file or using different server, I will explain, how to customize the application for that later. 

How to build the project with source?

I have provided complete source to you so that you can download the source code and go one step further or to read different log file or run with different server other then Tomcat. You can build the project using maven. If you are not using maven, you can create your own simple web application and copy the required contents. If you want to get the set of .jar files, you can get it from console-viewer.war file.

Here are the steps to build the project using maven.

Download the source and extract it to some where in your local disk. 

1. Navigate to the location.

    cd /home/semika/console-viewer

2. Build the project with the following command.

    mvn clean install

You can see, it builds the project and copies the 'console-viewer.war' file into CATALINA_HOME/webapps folder.  

3. Start the Tomcat with the following command.

   ./startup.sh

If you want to read some other log file rather than default 'catalina.out' file, or you want to run this application to view different server's console, you have to provide required log file's absolute path as an initialization parameter of 'Initializer' servlet as follows and deploy the application on the server.

<servlet>
    <servlet-name>initializer</servlet-name>
    <servlet-class>com.semika.cometd.Initializer</servlet-class>
    <init-param>
         <param-name>logFilePath</param-name>
         <param-value>
             /home/semika/apache-tomcat-7.0.37/logs/catalina.out
         </param-value>
     </init-param>
     <load-on-startup>2</load-on-startup>
</servlet>

Download the application and source

Download console-viewer.war file.
Download source code. If you encounter some issues with this, please send me a mail. I am always ready to give help.

Sunday, November 18, 2012

How to read a dynamically growing file with Java?

This small post explains, how to read a text file which grows dynamically, using Java. The catalina.out file which displays tomcat's console is a good example for a file which grows dynamically. 

The following example shows, how to read tomcat's catalina.out file with Java. This file grows when the applications deployed on tomcat are being accessed by users. The following program displays newly adding contents of catalina.out file just one second delay and keep continuing it. 

The Java's 'RandomAccessFile' class provides great facilities to read this kind of files.  The major usage of it for the following program is, it provides a feature so that we can read a file from a particular point to onwards. Let's see our small program. 

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Timer;
import java.util.TimerTask;


public class ConsoleReader {

   /**
    * @param args
    */
    public static void main(String[] args) {
    File file = new File("/home/semika/apache-tomcat-7.0.25/logs/catalina.out");
       try {
           RandomAccessFile r = new RandomAccessFile(file, "r");
           //First time read
           String str = null;
           while((str = r.readLine()) != null) {
            System.out.println(str);
           }
           r.seek(r.getFilePointer());
           startTimer(r);
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       } 
    }
 
    private static void startTimer(final RandomAccessFile r) {
     Timer timer = new Timer();
     timer.scheduleAtFixedRate(new TimerTask() {
     @Override
     public void run() {
     String str = null;
     try {
          while((str = r.readLine()) != null) {
           System.out.println(str);
          } 
          r.seek(r.getFilePointer()); 
     } catch (IOException e) { 
         e.printStackTrace();
     }
      }
 }, 0, 1000);
    }
}

In the above program, it reads catalina.out file line by line and displays it in console. When you run the program, it will read the whole file up to the end at first and then immediately start a timer to read dynamically adding contents to the file. The timer will always start to read file from a particular point, in above case, it will always start to read the file from the next line which last line was displayed.

While you are accessing your applications deployed in your tomcat container, just keep looking at the output of above program. You can see the tomcat's console just like, you have used to see it before.

Monday, November 12, 2012

Java enums are more than constant fields.

An enum is a type which defines set of fixed constants. For example, if you think generally, the seasons of the year, the planets in the solar system can be defined as enums. Also, you can identify constant types  in your application and defined those as enums which gives you much reliability, maintainability and also the flexibility. Enums were introduced to the Java language with 1.5 release which provides great functionality than what we know, and what we are using. Before introducing enums to the language, we used int, string constants which have many shortages. 

With this post, I am going to discuss the advantages of using enums and the shortcomings of using traditional constants approach. Suppose, we want to keep constant types for seasons of the year. Before enum was introduced, we normally defined a constant group as follows. 

 public static final int SEASON_SPRING = 3;
 public static final int SEASON_SUMMER = 6;
 public static final int SEASON_AUTUMN = 9;
 public static final int SEASON_WINTER = 12;
The value assigned for each field is, the starting month of the season. For example, the summer season will start from 6th month of the year. In real world, the starting month of each season will vary from country to country. I used above values just for illustration purpose. 

Let's discuss the shortcomings of the above approach when comparing with enum types. 

Constant fields don't provide type safety. Suppose you have written a method which returns the months belong to each season.

private List<String> getMonthsOfSeason(int seasonStartingMonth) {
  
    switch(seasonStartingMonth) {
       case 3:
           return CalendarUtil.getMonthsOfYear(new int[]{2,3,4});
           //[March, April, May]
       case 6:
           return CalendarUtil.getMonthsOfYear(new int[]{5,6,7});
           //[June, July, August]
       case 9:
           return CalendarUtil.getMonthsOfYear(new int[]{8,9,10});
           //[September, October, November]
       case 12:
           return CalendarUtil.getMonthsOfYear(new int[]{11,0,1});
           //[December, January, February]
       default:
           return new ArrayList<String>(); 
    }
}

If we use traditional int constants approach, we have to implement similar method like above to get the months of a season. I will show you the code for CalendarUtil class later in this post.

The above method accepts any integer value as the season starting month. By mistakenly, you may pass a different integer constant field (some number except 3,6,9,12) into the method instead of passing one of the season number which has been defined as constants above. In that kind of scenario, the method will returns empty list which may result unexpected output.

Though, You can add considerable validation to the above method, still that method is brittle. The other thing is, you may compare the parameter value with any integer since defined constants are integer type.

   
   If(seasonStartingMonth == QUATER_THREE) {
     //some code
   }

In the above code 'QUATER_THREE' is some different integer constant field defined in the same class for different purpose. Our programmer has mistakenly compared 'seasonStartingMonth' variable with QUATER_THREE constant field. But this is valid comparison, no compile error, but it will give wrong output. Programmer actually intended to compare 'seasonStartingMonth' variable with one of the our defined season constant field. 

Java does not provide namespaces to distinguish each constant groups. We have to use prefixes when two int constant groups have identically named fields. I have used SEASON_ for season group for that purpose. 

The int constants are compile-time constants. The int enums are compiled into the clients that use them. If the int associated with an enum constant is changed, its clients must be recompiled. If they aren’t, they will still run, but their behaviour will be undefined. 

The int constants don't give good debugging information. The int constant fields do not give helpful information when you are debugging your code. If you print some int constant field, it will print just a number which does not make sense. There is no easy way to translate int constant fields into printable strings. 

There is no reliable way to iterate over all the constants defined in a particular constant group and also the size of the constant group. 

Above, I have highlighted some of the shortcoming when using traditional constant field approach.

I have small utility class as follows.

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;


public final class CalendarUtil {

    //Returns list of names of the months for a given array of month numbers.
    public static List<String> getMonthsOfYear(int[] months) {
         List<String> monthArray = new ArrayList<String>(3);
         Calendar cal = Calendar.getInstance();

         for (int i = 0; i < months.length; i++) {
             cal.set(Calendar.MONTH, months[i]);
             monthArray.add(cal.getDisplayName(Calendar.MONTH,
                    Calendar.LONG, Locale.ENGLISH));
         }
         return monthArray;
    }
}

In the above utility class, the 'getMonthsOfYear()' method returns list of month's name for a given array of month numbers of the year.

Now,let's try to do the same thing by using enum. The following code shows an enum definition for seasons of the year.

import java.util.ArrayList;
import java.util.List;

public enum Season {

   SEASON_SPRING(3), //[March, April, May]
   SEASON_SUMMER(6), //[June, July, August]
   SEASON_AUTUMN(9), //[December, January, February]
   SEASON_WINTER(12);//[September, October, November]
 
   private final int startingMonth;
 
   SEASON(int startingMonth) {
       this.startingMonth = startingMonth;
   }
 
   public List<String> getMonthsOfSeason() {

       switch(startingMonth) {
           case 3:
             return CalendarUtil.getMonthsOfYear(new int[]{2,3,4});
           case 6:
             return CalendarUtil.getMonthsOfYear(new int[]{5,6,7});
           case 9:
             return CalendarUtil.getMonthsOfYear(new int[]{8,9,10});
           case 12:
             return CalendarUtil.getMonthsOfYear(new int[]{11,0,1});
           default:
             return new ArrayList$lt;String>(); 
       }
    }
}

See how Java enums are smart? Java enums are classes that export one instance for each enumeration constant via a public static final field. This kind of enum declaration provides compile time safety. For example, consider the following method.

private List<String> getMonthsOfSeason(Season season) {

}

This method guaranteed that it won't accept any other types of values except Season. If we try to pass some other types, compiler will point it out as an error. 

Since Java enum has it's own namespace, identically named constants can coexist with out any problem. For example, We can use same enum constant field name with another enum declaration. 

We can easily convert enum constant fields to printable string using toString() method.

Java enum allows us to keep methods and fields associated with it. In the above example, I have declared one field and method with the enum. I have defined the method with the enum it self which returns months of the season. This is very reliable and convenience implementation. The likelihood of happening bugs in the application is comparatively less. If we want to get the months of winter seasion, we can do it as follows.

List<String> months = Season.SEASON_WINTER.getMonthsOfSeason();

In the above example, the defined method behaves similarly for every constant field. But, We can implement method which behaves differently for each constant field on the enum. I have discussed about field specific method implementation with another post. Please have a look on following URL.

http://skillshared.blogspot.com/2012/01/java-enum-constant-specific-method.html

We can associate data with each constant field of a enum. I have specified starting month number with each constant field of Season enum. We can associate data as many with the enum constant field with the declared fields with corresponding types of data and also the constructor parallel to those data. Enums are immutable, so all fields should be final.

Also, if you want to iterate over all the constant fields of the enum, you can do it as follows.

for (Season s : Season.values()) {
   System.out.println("Months of seasion : " + s.toString());
   System.out.println(s.getMonthsOfSeason());
}

I am going to conclude this article with nice example. Consider the eight planets of our solar system. There are tow constant attribute for each planet has, a mass and a radius, and from these two attributes you can compute its surface gravity. This in turn lets you compute the weight of an object on the planet’s surface, given the mass of the object. Here’s how this enum looks.The numbers in parentheses after each enum constant are parameters that are passed to its constructor. In this case, they are the planet’s mass and radius.
public enum Planet {
    MERCURY(3.302e+23,2.439e6),
    VENUS (4.869e+24,6.052e6),
    EARTH (5.975e+24,6.378e6),
    MARS(6.419e+23,3.393e6),
    JUPITER(1.899e+27,7.149e7),
    SATURN (5.685e+26,6.027e7),
    URANUS (8.683e+25,2.556e7),
    NEPTUNE(1.024e+26,2.477e7);

    private final double mass;
    private final double radius;
    private final double surfaceGravity;

    private static final double G = 6.67300E-11;

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
        surfaceGravity = G * mass / (radius * radius);
   }

   public double mass() {
         return mass;
   }

   public double radius() {
         return radius;
   }

   public double surfaceGravity() {
         return surfaceGravity;
   }

   public double surfaceWeight(double mass) {
        return mass * surfaceGravity;
   }
}

Sunday, November 11, 2012

How to display months of the year with Java?

The Calendar is very useful utility class provided by Java for manipulating calender fields. It represents months of the year in integer format starting from 0 and ending with 11, which 0 represents 'January' and 11 represents 'December'. The 'getDisplayName' method of Calendar class returns the string representation of the calendar field value in the given style and locale. If no string representation is applicable, null is returned. 

The following Java program displays months of the year in two formats.

import java.util.Calendar;
import java.util.Locale;

public class CalendarUtil {

    public static void main(String[] args) {
        displayMonthsInLongFormat();
        displayMonthsInShortFormat();
    }
 
    private static void displayMonthsInLongFormat() {
  
        Calendar cal = Calendar.getInstance();
  
        System.out.println("Months of the year in long format");
        System.out.println("---------------------------------");
  
        for (int i = 0; i < 12; i++) {
            cal.set(Calendar.MONTH, i);
   
             System.out.println(cal.getDisplayName(Calendar.MONTH, 
                           Calendar.LONG, Locale.ENGLISH));; 
        }
     }
 
     private static void displayMonthsInShortFormat() {
  
         Calendar cal = Calendar.getInstance();
  
         System.out.println("Months of the year in short format");
         System.out.println("---------------------------------");
  
         for (int i = 0; i < 12; i++) {
             cal.set(Calendar.MONTH, i);
   
             System.out.println(cal.getDisplayName(Calendar.MONTH, 
                       Calendar.SHORT, Locale.ENGLISH));; 
         }
     } 
}
The above program will generate the following output.

Months of the year in long format ---------------------------------
January
February
March
April
May
June
July
August
September
October
November
December

Months of the year in short format ---------------------------------
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec

Wednesday, November 7, 2012

Why @Override annotation is important in Java?

The 'Override' annotation was introduced with Java 1.5 release which indicates that the annotated method declaration overrides the declaration in a super class. This annotation is used highly and most of the modern IDE's added this annotation automatically when we use some IDE's features. If you consistently use this annotation, it will protect you from a large class of sever bugs. Let's have some example. Consider the following class declaration.

public class Employee {

    private String nicNo;
    private String name;
 
    public Employee(String nicNo, String name) {
         super();
         this.nicNo = nicNo;
         this.name = name;
    }
    public String getNicNo() {
         return nicNo;
    }
    public void setNicNo(String nicNo) {
         this.nicNo = nicNo;
    }
    public String getName() {
         return name;
    }
    public void setName(String name) {
         this.name = name;
    }
    public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((nicNo == null) ? 0 : nicNo.hashCode());
         return result;
    }
    public boolean equals(Employee obj) {
         return obj.nicNo == this.nicNo;
    }
}

Sunday, November 4, 2012

Reduce the scope of local variable in Java

Old programing languages such as C,C++ force us to declare local variables at the head of the code block. Some programers used to continue the same with Java. But it is not a good practice though Java lets us declare local variable anywhere in the code.

The most easy way to reduce the scope of local variable is, declare local variables where it is first used. This will reduce the scope of local variables and also this will increase the code readability. If you declare your local variable at top of code block or method, by the time that variable is used, the code reader might not remember about the variable.

With this small post, I am going to give you an example which creates a bug in the application which is very hard to detect. We know that "Loops" have a special opportunity to minimize the scope of variables. The traditional for loop and new for-each loop allows you to declare loop variables limiting their scopes to the region where they are needed. 

Friday, August 24, 2012

Passing more parameters with login request - Java

If you are using some container managed authentication mechanism like standard java form based authentication or spring security authentication mechanism, You are not really involving with user credential validation, like checking user name and password against the database, but the container is fully responsible for this. But what will happen if you want to pass some additional parameters with log-in details(username and password)?. The well known and most common scenario is passing "Keep me logged in" or "Remember me" check box value with your log-in details and doing some work with that while container is authenticating the user. 

Recently, I had to implement the "Keep me logged in" function for one of my current project which are using spring 3 security as authentication mechanism. I am little new to spring 3 and it was challenging work for me of passing "Keep me logged in" check box status into spring's authentication provider class. 

With this post, I will explain, How I achieved that. The application uses 'AuthenticationProvider' class which extends from spring's 'AbstractUserDetailsAuthenticationProvider' and overrides 'retrieveUser' method which returns spring's UserDetails instance. Normally, authentication details are provided to 'retrieveUser' method via spring's 'WebAuthenticationDetails' instance.
Bellow shows the snip of code from 'retrieveUser' method of my authentication provider class.

@Override
protected User retrieveUser(String userName, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {

     OGGER.debug("Retrieve user : " + userName);
        
     final String password = authentication.getCredentials().toString();

     WebAuthenticationDetails webAuthenticationDetails = authentication.getDetails());

     try {
         User user = userBusiness.getUserByUsernameAndPassword(userName, password);
         logger.debug("Remote address : " + webAuthenticationDetails.getRemoteAddress());
         logger.debug("Session Id     : " + webAuthenticationDetails.getSessionId());
         //.................
            
         return user;
     } catch (Exception e) {
         e.printStackTrace();
     }
}

I wanted to get "Keep me logged in" check box value into 'retrieveUser' method. It was very obvious that I am not able to get the check box value with current situation. The 'WebAuthenticationDetails' provides some details like remote address, session id etc, But not our own additional details.

As the next step, I implemented my own custom class by extending 'WebAuthenticationDetails' and put 'rememberMe' as a bean property.That class shows bellow.

package com.blimp.webapp.security;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.web.authentication.WebAuthenticationDetails;

/**
 * @author semika
 *
 */
public class BlimpAuthenticationDetails extends WebAuthenticationDetails {

    private static final long serialVersionUID = 2012033417540858020L;
 
    private String rememberMe;
 
    public String getRememberMe() {
     return rememberMe;
    }
 
    //This constructor will be invoked by the filter
    public BlimpAuthenticationDetails(HttpServletRequest request) {
     super(request);
     this.rememberMe = request.getParameter("rememberMe");
    }
}

The next thing is, How we tell spring security engine to use my custom authentication detail class instead of using 'WebAuthenticationDetails' class when authenticating a user?.
For this one, we have to configure authentication processing filter in our spring security xml file. Some filtered contents from security XML file are shown bellow.

<http auto-config="false">
     <custom-filter ref="authenticationProcessingFilter" before="FORM_LOGIN_FILTER"/>
     <form-login login-page="/login.jsp?type=login"  authentication-failure-url="/login.jsp?login_error=true" default-target-url="/getRedirectPage.htm"/>
     <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER"  />
</http>
<authentication-manager alias="authenticationManager">
     <authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>
<beans:bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
     <beans:property name="authenticationManager" ref="authenticationManager"/>
     <beans:property name="authenticationDetailsSource">
          <beans:bean class="org.springframework.security.authentication.AuthenticationDetailsSourceImpl">
  <beans:property name="clazz" value="com.blimp.webapp.security.BlimpAuthenticationDetails"/>
   </beans:bean>
     </beans:property>
</beans:bean>

The 'daoAuthenticationProvider' is the instance of my 'AuthenticationProvider' class which extends 'AbstractUserDetailsAuthenticationProvider' and it has overridden 'retrieveUser' method. The my updated 'retrieveUser' method will be as follows.

@Override
protected User retrieveUser(String userName, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {

     OGGER.debug("Retrieve user : " + userName);
        
     final String password = authentication.getCredentials().toString();

     BlimpAuthenticationDetails webAuthenticationDetails = ((BlimpAuthenticationDetails) authentication.getDetails());

     try {
         User user = userBusiness.getUserByUsernameAndPassword(userName, password);
         logger.debug("Remote address : " + webAuthenticationDetails.getRemoteAddress());
         logger.debug("Session Id     : " + webAuthenticationDetails.getSessionId());
         logger.debug("Remember me    : " + webAuthenticationDetails.getRememberMe());
         //.................
            
         return user;
     } catch (Exception e) {
         e.printStackTrace();
     }
}

As you can see above, I can get the remember me check box value from 'retrieveUser' method.
You may also like:

Sunday, August 5, 2012

Java class for Valums AJAX file uploader for IE9 with spring MVC

I wanted to have AJAX file upload which supports multiple files uploading for my recent project. The Valums AJAX file up-loader gave me a very good experience and integrated that into my application. This file up-loader uses XHR for uploading files on the browsers which supports XMLHttpRequest level 2 and falls back to hidden iframe based upload in other browsers. 

My application should run in FF, Chrome and IE. IE9 does not support XHR file uploads and even Valums GitHub has only provided a java example for XHR Level 2 supporting browsers which directly reads the input stream from the request. 

For browsers which do not support XHR Level 2, up-loader send the file to server as 'multipart/form-data'. Therefor, we should write our up-loader java controller class so that it reads multipart form data when request coming from browsers which do not support XHR file upload (like IE9) and directly read the input stream for the requests coming from the browsers which support XHR file uploads (like FF3.6+, Safari4+, Chrome). 

In both type of browsers, we should make sure that the response type as 'text/plain'. My application is running with spring 3 MVC which persuaded me to do some work around when reading multipart form data from the request. In spring 3 MVC environment, 'HttpServletRequest' which has 'multipart/form-data' are wrapped into 'MultipartHttpServletRequest', not like in normal servlet environment. 

Here, I am going to give you an example and basic java code which reads multipart form data with spring 3 MVC environment. If you are not using, spring 3 MVC and using some other controllers like pure servlets or struts 2 action class, you can directly read the multipart form data by using HttpServletRequest. 

However, for Valums file up-loader, we should write our controller class in tow conditional way. One is for XHR file upload supporting browsers and one for 'multipart/form-data' based file uploading browsers.

@RequestMapping(value = "*ajax*", method = RequestMethod.POST)
public @ResponseBody
String uploadFile(HttpServletRequest request, HttpSession session, HttpServletResponse response, Principal principal, Model model, Locale locale) throws IOException, ServletException {

   InputStream is = null;
   String filename = null; 
   String result = null; 
   try {
      
       if (isMultipartContent(request)) { 
            MultipartHttpServletRequest mrequest = (MultipartHttpServletRequest)request;
            Map<String MultipartFile> fileMap = mrequest.getFileMap();           
            for (Map.Entry<String MultipartFile> entry : fileMap.entrySet()) {
               MultipartFile mfile = entry.getValue(); 
               is = mfile.getInputStream();
               filename = mfile.getOriginalFilename();               
               break;
            }
       } else {
           filename = request.getHeader("X-File-Name");
           is = request.getInputStream();
       }
      
       result = "{success:true}";

   } catch (Exception ex) {
       ex.printStackTrace();
       result = "{success:false}";  
   } finally {
       try {
    is.close();
       } catch (IOException ignored) {}
   } 
   return result;
}


private static final boolean isMultipartContent(HttpServletRequest request) {
    String contentType = request.getContentType();
    if (contentType == null) {
     return false;
    }
    if (contentType.toLowerCase().startsWith("multipart/")) {
     return true;
    }
    return false;
}


I hope this will help you. At the beginning, even I thought, Valums ajax file up-loader does not work in IE9. But it works fine in IE as well. If you need any help, feel free to put comment or send a mail to me.
You may also like:

Tuesday, May 22, 2012

How to expose an exsisting service as a web service ?

Introduction

This tutorial addresses a most practical scenario which is being faced by a developer. Most of the time, We may need to expose some of our existing services as web services. This situation can be encountered in different stages of project life cycle. If It is the initial stage, then You are almost safe and You can well prepare for that. But, What will happen, this requirement comes just after half of the development has finished or the system is running in production environment. 

This will be little tricky if the web services have not been taken into consideration for initial project architecture. You may involve with different kind of project architectures and use different kind of technologies. As a developer, You are not allowed to change some architectural stuff and configurations since there may be lots of dependencies. 

Most of the tutorials on the Internet explains the basic stuff of creating a web service. Some time, 'Hello world' application or sometime it may be simple calculator like that. These tutorials are good to have the basic understanding about the web services. But the real world scenario's are ten time complex than that and have to face difficulties when following those kind of tutorials. 

Practical scenario

With this tutorial, I am going to explain, How We really address a real world requirement that came through your supervisor. I am going to explain the same kind of scenario, which I faced recently. 

A health care organisation is running a plenty of pharmacies all around the island. They have a web application which handles all the inventories, pricing and billing, issuing pharmacy items etc. They needed to expose their pharmacy items prices through a web service so that their client application in the pharmacy can access those via the web service. 

Their web application has been developed within struts2, spring and hibernated integrated environment. It has all the spring managed DAO classes and also the service classes. The application uses spring's auto wiring technique, component scanning, transaction management etc. With these kind of background, I needed to expose pharmacy item prices as a web service. That is some of the methods from our current pharmacy service are needed to be exposed to outside via a web service.

I will show you, How to achieve this kind of requirement with a minimal modification to our existing project. 

Additional Libraries

I am going to implement the web service with JAX-WS. I have used JAX-WS 2.2 for my project. You can download the required JAX-WS version from here. This provides few tools that can be used to generate web service and it's client stuff. After downloading the required version of library, extract it some where in your local machine. I have placed it in my home folder. 

ie: /home/semika/jaxws-ri-2.2

Implementing web service

I already have spring managed service classes and DAO classes for pharmacy item which are being used internally by the web application. Those are not exposed to out side. Suppose, We need to expose findAll() method which returns a list of 'PharmacyItem' of 'PharmacyService' interface as a web service.

For Your convenience, I will show you the "PharmacyServiceImpl" java class which is used to perform normal pharmacy item operations. This is a usual spring mange bean. Keep in mind, methods of this class can only be used for internal operations of our web application currently. Those are not exposed as web services. 

PharmacyServiceImpl.java

/**
 * 
 */
package com.slauto.service.pharmacy.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.slauto.exceptions.ServiceException;
import com.slauto.model.pharmacy.PharmacyItem;
import com.slauto.persist.pharmacy.api.PharmacyItemDao;
import com.slauto.service.pharmacy.api.PharmacyItemService;

/**
 * @author semika
 *
 */
@Service("pharmacyItemService") 
public class PharmacyItemServiceImpl implements PharmacyItemService {

  @Autowired
  private PharmacyItemDao pharmacyItemDao;
 
  @Override
  public List<Pharmacyitem> findAll() throws ServiceException {
     return pharmacyItemDao.findAllPharmacyItems();
  }
}

As You can see, I have auto wired instance of 'PharmacyItemDao' with in the implementation class. As We all know, this is a spring managed service implementation class.

Next, We will implement the web service end point class for above spring managed service bean to expose it's methods as a web service methods. For the clarity, I created a separate class as web service end point.

PharmacyItemServiceEndPoint.java

package com.slauto.service.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.slauto.exceptions.DataAccessException;
import com.slauto.model.pharmacy.PharmacyItem;
import com.slauto.service.pharmacy.api.PharmacyItemService;

/**
 * @author semika
 *
 */
@WebService(serviceName="pharmacyItemService") 
public class PharmacyItemServiceEndPoint {
 
  @WebMethod
  public List<Pharmacyitem> findAll() throws DataAccessException {
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     PharmacyItemService pharmacyItemService = (PharmacyItemService)context.getBean("pharmacyItemService");
     return pharmacyItemService.findAll();
  }
}

As You can see here, I am using "pharmacyItemService" bean which is used by our web application to access the relevant service method. The "pharmacyItemService" is a usual spring mange bean which is used to perform day to day pharmacy item operation. Nothing special on that. Specially note that @WebService and @WebMethod annotation which indicates this class works as a web service end point.

Here, I am getting service class instance via application context. Further, We can auto wire web service end point classes with spring by extending end point classes from "SpringBeanAutowiringSupport"  provided by spring. In that case, We do not need to create application context instance as I have done above. I could not make that work, that is why, I used the above technique.

With "SpringBeanAutowiringSupport", when deploying web service (explain bellow), I encountered an exception which was hard  for me to resolve that. So I choose this technique. Any way, I do not like, what I have used above :) .

Generating web service

I am using a apt, wsgen and wsimport tools provided by JAX-WS to generate the portable artefacts used in JAX-WS services. The relevant ant targets for the 'build.xml' file will be as follows. 

Your may need following property declared at the top of the 'build.xml' file.

Property:

<property name="tomcat.home"        value="/home/semika/apache-tomcat-7.0.25" />
<property name="jaxws.home"         value="/home/semika/jaxws-ri-2.2" />
<property name="build.classes.home" value="${basedir}/WEB-INF/classes" />
<property name="java.home"          value="/home/semika/java/jdk1.6.0_30">

Class path:

<path id="project.class.path">
   <pathelement location="${java.home}/../lib/tools.jar" />
   <fileset dir="${jaxws.home}/lib">
        <include name="*.jar" />
   </fileset>
   <pathelement location="${basedir}/WEB-INF/classes" />
   <fileset dir="${basedir}/WEB-INF/lib" includes="*.jar" />
</path>

JAX-WS apt tool target:

<target name="apt" depends="javac">
   <taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
       <classpath refid="project.class.path" />
   </taskdef>
   <apt fork="true"
        debug="true"
        verbose="true"
        destdir="${basedir}/WEB-INF/classes"
        sourcedestdir="${basedir}/WEB-INF/src"
        sourcepath="${basedir}/WEB-INF/src">
        <classpath>
            <path refid="project.class.path" />
        </classpath>
        <option key="r" value="${basedir}/WEB-INF" />
        <source dir="${basedir}/WEB-INF/src">
            <include name="**/*.java"/>
        </source>
   </apt>
</target>

If you want to know further about apt tool provided by JAX-WS, look into this. When running apt target, it scans the source path (src folder) and generates the required *.class and *.java files for the classes annotated with @WebService. In this case, for 'PharmacyItemServiceEndPoint.java'. If You look into the package where 'PharmacyItemServiceEndPoint' is in, You can see, it has a new package called 'jaxws' created. Inside that package, I could see following three java files. 

DataAccessExceptionBean.java
FindAll.java
FindAllResponse.java

These classes are generated by the tool and it varies based on your service implementation and dependent classes which you are involving to your web service. Actually, you don't need to much worry about these generated stuff.

Similarly, You can see the relevant *.class files under /WEB-INF/classes folder.

JAX-WS wsgen tool target:

<target name="wsgen" depends="apt"> 
    <taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen">
         <classpath path="project.class.path"/>
    </taskdef>
  
    <wsgen 
          xendorsed="true"
          sei="com.slauto.service.ws.PharmacyItemServiceEndPoint"
          destdir="${basedir}/WEB-INF/classes"      
          resourcedestdir="${wsdl.dir}"
          sourcedestdir="${basedir}/WEB-INF/src"      
          keep="true"
          verbose="true"
          genwsdl="true">
          <classpath refid="project.class.path"/>
    </wsgen>
</target>

The wsgen tool will generate the WSDL file for our end point web service class. After running this target, have a look on ${wsdl.dir} location. You can see our WSDL file has been generated. If you want to know further about wsgen tool provided by JAX-WS, look into this

Deploying Web service

I wanted to deploy the web service with the usual server start up. SoI had to add the following configuration into the web.xml file.

<listener>
      <listener-class>
              com.sun.xml.ws.transport.http.servlet.WSServletContextListener
      </listener-class>
</listener>
<servlet>
      <servlet-name>pharmacyItemService</servlet-name>
      <servlet-class>
         com.sun.xml.ws.transport.http.servlet.WSServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
      <servlet-name>pharmacyItemService</servlet-name>
      <url-pattern>/pharmacyItemService</url-pattern>
</servlet-mapping>

As I told you before when deploying the web service with the end point class extended from "SpringBeanAutowiringSupport", it gives an exception. That is why, I decided to get the service bean via application context. If you manage this situation, please just post it.

And also, You need to create sun-jaxws.xml under the WEB-INF folder and declare the web service end point as follows.

<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">    
  <endpoint
      name="pharmacyItemService"
      implementation="com.slauto.service.ws.PharmacyItemServiceEndPoint"
      url-pattern="/pharmacyItemService"/>
</endpoints>

I am using apache tomcat 7.0.25 to deploy the web service. You will need to tell tomcat where it can find JAX-WS libraries when the tomcat is starting up. You can edit the 'catalina.properties' file located in CATALINA_HOME/conf folder. Look for the common.loader property. It will mostly look like follows.

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar

Modify it as follows.

common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,/home/semika/jaxws-ri-2.2/lib/*.jar

As You can see, I have added my JAX-WS library path at the end of comma separated list. These classes are made visible to both tomcat internal classes and to all web applications deployed in the tomcat container. Now, You can copy your .war file into tomcat's webapps folder and start the tomcat. Your web service should be deployed. To confirm your web service is deployed properly, You can check for it's WSDL. For WSDL file, You should check the URL in following format.

http://localhost:8080/<your context name>/pharmacyItemService?wsdl

If You can see your WSDL file on the browser, You are done, You have success fully deployed the web service.

Generating Web service client

Now, We have a deployed web service. Next, We will see how to write client class to access the web service with java program. You can create a simple java project and use the following build.xml file there. I have placed the complete build.xml file for client generation. I am using wsimport tool coming with JAX-WS to generate the web service client artefacts.
<?xml version="1.0" encoding="utf-8" ?>
<project name="WS-client" default="wsimport" basedir=".">
 
 <property name="jaxws.home"  value="/home/semika/jaxws-ri-2.2" />
 <property name="java.home" value="/home/semika/java/jdk1.6.0_30"/>
 
 <path id="jaxws.classpath">
  <pathelement location="${java.home}/../lib/tools.jar" />
  <fileset dir="${jaxws.home}/lib">
        <include name="*.jar" />
     </fileset>
 </path>
 
 <target name="wsimport"> 
  <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
        <classpath path="jaxws.classpath"/>
  </taskdef>
  <wsimport   xendorsed="true"
              debug="true"
       verbose="true"
              keep="true"
       destdir="src"
       package="com.slauto.service"
       wsdl="http://localhost:8080/slautomanage/pharmacyItemService?wsdl">
  </wsimport>
 </target>
</project>

If You want to know further about wsimport tool, you can look into this. After running the above target, just have a look on the package where you have specified under wsimport attributes. You will see set of java files generated. You can compile and bundle these into a single client.jar file and can be used with any of the java project which need this web service. 

I have created very simple java class to fetch the pharmacy items information through the web service. 

Client.java

package com.slauto.client;

import java.util.List;

import com.slauto.service.PharmacyItem;
import com.slauto.service.PharmacyItemService;
import com.slauto.service.PharmacyItemServiceEndPoint;

/**
 * @author semika
 *
 */
public class Client {

 /**
  * @param args
  */
  public static void main(String[] args) {
  
        PharmacyItemService p = new PharmacyItemService();
        PharmacyItemServiceEndPoint ep = p.getPharmacyItemServiceEndPointPort();
        List<PharmacyItem> pharmacyItems = ep.findAll();
  
        for (PharmacyItem pharmacyItem : pharmacyItems) {
           System.out.println(pharmacyItem.getCode()); 
        }
     }
  }

It is wonderful isn't it ?. You will see list of pharmacy item codes displayed just after running this class. These pharmacy information are coming through web service deployed by a web application developed with heavily complicated environment.
That is it from this tutorial. I hope this will be helpful for you and if you pick something up from this tutorial, don't forget to put a comment. 

Monday, May 14, 2012

Use primitives over boxed primitives whenever you have the choice - Java

Just with the reading of this post's title, some of you may be confused because, some of the java developers have used to use boxed primitives (Wrapper class objects of primitives) without a specific reason. But, We should be care of using primitives rather than the boxed primitives when We have a choice. I will explain Why, We should choose primitives.

There are differences between primitives and boxed primitives though You did not pay attention too much on that.

Primitives are simpler and faster, and they have only their values. Primitives are generally more time- and space-efficient than boxed primitives. But the boxed primitives have different identities though they have same value. Consider the following code which most of the java developers are well known and understandable.

 Integer first = new Integer(41);
 Integer second = new Integer(41);
  
 if (first == second) {
      System.out.println("Equal");  
 }

As You well known, the above code will not print the "Equal" since it performs an identity comparison on the two object references. Applying == operator on boxed primitives always gives wrong output. To fix the above problem, either You can use Integer's equal() method or getting integer values from Integer's intValue() method. Now, You consider the following code.

Integer first = new Integer(41);
Integer second = new Integer(41);
       
if (first > second) {
     System.out.println("First is greater than Second");  
} else {
     System.out.println("First is not greater than Second");
}

Can you spot the output of above code? The above code will print the else condition. In this case, it did not perform the identity comparison like == comparison. It compared the actual values and gave the correct output. So When evaluating this kind of comparison, Integer instances are auto-unboxed;that is, it extracts their primitive values. I know, You have used this kind of comparison plenty of times. Think, You really knew about this. So We must choose primitives or boxed primitives when We have a choice. 

Next, We will move to another difference. You know that, When We declare a variable with primitive type, it always has functional values. But boxed primitives can have 'null' values which sometime can raise exception. Consider the following example.


package com.semika.mail;

public class BoxPrimitiveTest {
 
static Integer x;
static int y;

public static void main(String[] args) {

   if (x == 0) {
        System.out.println("X is Zero");  
   }
  
   if (y == 0) {
        System.out.println("Y is Zero");  
   }
}
}

What will be the output of the above program. The above code will not run and it will throw an exception. As You can see, variable 'x' is declared with boxed primitive type. It has 'null' value when evaluating the x==0 expression. When a null object reference is auto-unboxed,You get a NullPointerException

Next, I will explain the harm of mixing both box primitives and primitives in a single operation. When You mix primitives and boxed primitives in a single operation, the boxed primitive is auto-unboxed which results severe performance problems. Consider the following class.

class LineItem {
 
double price;

public double getPrice() {
    return price;
}

public void setPrice(double price) {
    this.price = price;
}
}

Suppose, You want to iterate list of 'LineItem' and calculate the total value. Note that 'price' variable is declared with a primitive type. Look into the following code of calculating total cost.

Double totoalCost = 0.0; 
  
for (LineItem lItem : lineItemList) {
    totoalCost += lItem.getPrice();
}

The above code makes a server performance problem. Since, You have declared 'totoalCost' variable to be of the boxed primitive type Double instead of primitive type double. The program compiles and run without an error or warning.But the variable is repeatedly boxed and unboxed, causing the observed performance degradation.

Finally, the developer should never ignore the distinction between primitives and boxed primitives. You have to choose what to use.

Wednesday, March 21, 2012

Java form based authentication

Implementing a login module using JAAS  is an of advance topic and also most of the developers have rare chance of involving with this kind of development. But the basic implementation of JAAS login module is not that much hard implementation.That is because, I intended to post this. Here, I am explaining, how to implement a tomcat managed authentication module. This implementation is not container dependent one. We can use it with any container with slight configuration change. 

As the first step, We need to create a login module class which implements javax.security.auth.spi.LoginModule interface. This interface exposes 5 methods that must be implemented by our login module class. Those are initialize(), login(), commit(), abort(), logout().

initialize() method is passed four arguments .

The 'Subject'  is what, We need to authenticate. The subject can represents the related information for a single login user. It can represent identities like 'username', 'password' etc. And also, it can represents the roles assigned to the user. All these identities should be represent as java.security.Principal. So We should create separate classes to distinguish these entities by implementing  java.security.Principal. In my tutorial, I have created separate classes for username, password and role as JAASUserPrincipal, JAASPasswordPrincipal and JAASRolePrincipal.
Subject's getPrincipals() method returns a set of java.security.Principal associated with the subject. To distinguish these, it is important of Creating separate classes for each identity.

The 'CallbackHandler'  is used to communicate with the user. When authenticating the user by the login module, the login module invokes the handle() method of the CallbackHandler instance to get the user name and password. We do not want to worry about CallbackHandler instance yet. Because the container manages to provide the required callbakcs. The tomcat provides JAASCallbackHandler for this purpose. But, If We want to invoke the authentication explicitly, We need to create our own call back handler class by implementing the javax.security.auth.callback.CallbackHandler. I will explain this at the end of the tutorial.

The next important argument for initialize() method is 'options'. These options where We declare those in 'jass.config' file. With the initialisation of login module, map of options declared in 'jass.config' file are provided. I will explain the 'jaas.config' file of our tutorial later.

Next, I will show the full source code for our principal classes.

JAASUserPrincipal.java

package com.rainyday.server.login;

 import java.io.Serializable;
 import java.security.Principal;

/**
 * @author semika
 *
 */
 public class JAASUserPrincipal implements Principal, Serializable {

 private String name;
 
 /**
  * @param name
  */
 public JAASUserPrincipal(String name) {
  
 if (name == null) {
     throw new NullPointerException("NULL user name");
 }
     this.name = name;
 }
 
 @Override
 public String getName() {
     return name;
 }

 @Override
 public String toString() {
     return "UserPrincipal [name=" + name + "]";
 }

 @Override
 public int hashCode() {
     final int prime = 31;
     int result = 1;
     result = prime * result + ((name == null) ? 0 : name.hashCode());
     return result;
 }

 @Override
 public boolean equals(Object obj) {
     if (this == obj)
        return true;
     if (obj == null)
        return false;
     if (getClass() != obj.getClass())
        return false;
     JAASUserPrincipal other = (JAASUserPrincipal) obj;
     if (name == null) {
        if (other.name != null)
           return false;
     } else if (!name.equals(other.name))
        return false;
  
     return true;
 }
}

JAASRolePrincipal.java

package com.rainyday.server.login;

 import java.io.Serializable;
 import java.security.Principal;

/**
 * @author semika
 *
 */
 public class JAASRolePrincipal implements Principal, Serializable {

 private String name;
 
 /**
  * @param name
  */
 public JAASRolePrincipal(String name) {
     if (name == null) {
        throw new NullPointerException("NULL role name");
     }
     this.name = name;
 }

 @Override
 public String getName() {
    return name;
 }

 @Override
 public String toString() {
     return "JASSRolePrincipal [name=" + name + "]";
 }

 @Override
 public int hashCode() {
     final int prime = 31;
     int result = 1;
     result = prime * result + ((name == null) ? 0 : name.hashCode());
     return result;
 }

 @Override
 public boolean equals(Object obj) {
     if (this == obj)
        return true;
     if (obj == null)
        return false;
     if (getClass() != obj.getClass())
        return false;
     JAASRolePrincipal other = (JAASRolePrincipal) obj;
     if (name == null) {
        if (other.name != null)
           return false;
     } else if (!name.equals(other.name))
        return false;
     
     return true;
 }
}
JAASPasswordPrincipal.java 

package com.rainyday.server.login;

 import java.io.Serializable;
 import java.security.Principal;

/**
 * @author semika
 *
 */
 public class JAASPasswordPrincipal implements Principal, Serializable {

 private String name;
 
 /**
  * @param name
  */
 public JAASPasswordPrincipal(String name) {
     if (name == null) {
        throw new NullPointerException("NULL password.");
     }
     this.name = name;
 }

 @Override
 public String getName() {
     return name;
 }

 @Override
 public int hashCode() {
     final int prime = 31;
     int result = 1;
     result = prime * result + ((name == null) ? 0 : name.hashCode());
     return result;
 }

 @Override
 public boolean equals(Object obj) {
     if (this == obj)
         return true;
     if (obj == null)
         return false;
     if (getClass() != obj.getClass())
         return false;
     JAASPasswordPrincipal other = (JAASPasswordPrincipal) obj;
     if (name == null) {
        if (other.name != null)
           return false;
     } else if (!name.equals(other.name))
        return false;
     
     return true;
 }

 @Override
 public String toString() {
     return "JAASPasswordPrincipal [name=" + name + "]";
 }

}

The above three classes are exactly similar. But, We need to create separate classes for each principal to distinguish them.
The login() method of login module performs the authentication. This validates the user entered user name and password with the database. Now, You may have a problem, How login details entered by the user comes into the login() method. As I explained earlier, the call back handler brings the login identities into the login() method. From the login() method, the login module invokes the handle() method of call back handler by passing the required call backs into it. Then handle() method populates those call backs with the required information and make available to login() method.

The commit() method is invoked by the login module after the successful authentication. The subject can be populated with associated principals. For example, We can retrieve user assigned roles from the database and attached those to the subject.

The next, I will explain the required configurations to work this login module.

We should create 'jass.config' file and should be placed that file under '$CATALINA_HOME/conf'. The 'jass.config' file of this tutorial is as follows.
rainyDay {
   com.rainyday.server.login.JAASLoginModule required
   dbDriver="com.mysql.jdbc.Driver"
   dbURL="jdbc:mysql://localhost/rainyday"
   dbUser="root"
   dbPassword="abc123"
   userQuery="select username from secu_user where secu_user.username=? and secu_user.password=?"
   roleQuery="select secu_user_role.rolename from secu_user, secu_user_role where secu_user.username=secu_user_role.username and secu_user.username=?"
   debug=true;
};

'jass.config' file should have this similar format. In addition to the login module declaration, You can declare options as your wish. These options are made available by login module with 'options' map in initialize() method argument.

Additionally, We should tell the tomcat, Where to locate the 'jaas.config' file by adding it's path to JAVA_OPTS environment variable. I have added this into 'catalina.sh' file under $CATALINA_HOME/bin as follows.

JAVA_OPTS="$JAVA_OPTS -Djava.security.auth.login.config==../conf/jaas.config"

Next, You need to declare the JAASRealm configurations. You can add a new 'Realm' entry into the server.xml file under $CATALINA_HOME/conf. In our tutorial, the 'Realm' entry is as follows.

<Realm className="org.apache.catalina.realm.JAASRealm"
                appName="rainyDay"
                userClassNames="com.rainyday.server.login.JASSUserPrincipal,com.rainyday.server.login.JAASPasswordPrincipal"
                roleClassNames="com.rainyday.server.login.JASSRolePrincipal"/>


For apache tomcat's realm configuration, You can view this documentation. The complete source code for our jaas login module.

JAASLoginModule.java

package com.rainyday.server.login;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.apache.log4j.Logger;

/**
 * @author semika
 *
 */
public class JAASLoginModule implements LoginModule { 
 
    private static Logger LOGGER = Logger.getLogger(JAASLoginModule.class); 
 
    // initial state
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map options;

    // configurable option
    private boolean debug = false;
    
    // the authentication status
    private boolean succeeded = false;
    private boolean commitSucceeded = false;
    
    //user credentials
    private String username = null;
    private char[] password = null;
    
    //user principle
    private JAASUserPrincipal userPrincipal = null;
    private JAASPasswordPrincipal passwordPrincipal = null;
    
    public JAASLoginModule() {
         super();
    }

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
                Map<string, ?=""> sharedState, Map<string, ?=""> options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;
  
        debug = "true".equalsIgnoreCase((String)options.get("debug")); 
    }

    @Override
    public boolean login() throws LoginException {
  
        if (callbackHandler == null){
            throw new LoginException("Error: no CallbackHandler available " +
            "to garner authentication information from the user");
        }
        Callback[] callbacks = new Callback[2];
        callbacks[0] = new NameCallback("username");
        callbacks[1] = new PasswordCallback("password: ", false);
  
        try {
   
            callbackHandler.handle(callbacks);
            username = ((NameCallback)callbacks[0]).getName();
            password = ((PasswordCallback)callbacks[1]).getPassword();
   
            if (debug) {
                LOGGER.debug("Username :" + username);
                LOGGER.debug("Password : " + password);
            }
   
            if (username == null || password == null) {
                LOGGER.error("Callback handler does not return login data properly");
                throw new LoginException("Callback handler does not return login data properly"); 
            }
   
            if (isValidUser()) { //validate user.
                succeeded = true;
                return true;
            } 
   
        } catch (IOException e) { 
             e.printStackTrace();
        } catch (UnsupportedCallbackException e) {
             e.printStackTrace();
        }
  
        return false;
    }

    @Override
    public boolean commit() throws LoginException {
        if (succeeded == false) {
            return false;
        } else { 
            userPrincipal = new JAASUserPrincipal(username);
            if (!subject.getPrincipals().contains(userPrincipal)) {
                subject.getPrincipals().add(userPrincipal);
                LOGGER.debug("User principal added:" + userPrincipal);
            }
            passwordPrincipal = new JAASPasswordPrincipal(new String(password)); 
            if (!subject.getPrincipals().contains(passwordPrincipal)) {
                subject.getPrincipals().add(passwordPrincipal);
                LOGGER.debug("Password principal added: " + passwordPrincipal);
            }
      
            //populate subject with roles.
            List<string> roles = getRoles();
            for (String role: roles) {
                JAASRolePrincipal rolePrincipal = new JAASRolePrincipal(role);
                if (!subject.getPrincipals().contains(rolePrincipal)) {
                    subject.getPrincipals().add(rolePrincipal); 
                    LOGGER.debug("Role principal added: " + rolePrincipal);
                }
            }
      
            commitSucceeded = true;
      
            LOGGER.info("Login subject were successfully populated with principals and roles"); 
      
            return true;
       }
   }

   @Override
   public boolean abort() throws LoginException {
      if (succeeded == false) {
          return false;
      } else if (succeeded == true && commitSucceeded == false) {
          succeeded = false;
          username = null;
          if (password != null) {
              password = null;
          }
          userPrincipal = null;    
      } else {
          logout();
      }
      return true;
   }

    @Override
    public boolean logout() throws LoginException {
        subject.getPrincipals().remove(userPrincipal);
        succeeded = false;
        succeeded = commitSucceeded;
        username = null;
        if (password != null) {
            for (int i = 0; i < password.length; i++){
                password[i] = ' ';
                password = null;
            }
        }
        userPrincipal = null;
        return true;
   }
 
   private boolean isValidUser() throws LoginException {

      String sql = (String)options.get("userQuery");
      Connection con = null;
      ResultSet rs = null;
      PreparedStatement stmt = null;
  
      try {
          con = getConnection();
          stmt = con.prepareStatement(sql);
          stmt.setString(1, username);
          stmt.setString(2, new String(password));
   
          rs = stmt.executeQuery();
   
          if (rs.next()) { //User exist with the given user name and password.
              return true;
          }
       } catch (Exception e) {
           LOGGER.error("Error when loading user from the database " + e);
           e.printStackTrace();
       } finally {
           try {
               rs.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing result set." + e);
           }
           try {
               stmt.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing statement." + e);
           }
           try {
               con.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing connection." + e);
           }
       }
       return false;
   }

 /**
  * Returns list of roles assigned to authenticated user.
  * @return
  */
  private List<string> getRoles() { 
  
      Connection con = null;
      ResultSet rs = null;
      PreparedStatement stmt = null;
  
      List<string> roleList = new ArrayList<string>(); 
  
      try {
          con = getConnection();
          String sql = (String)options.get("roleQuery");
          stmt = con.prepareStatement(sql);
          stmt.setString(1, username);
   
          rs = stmt.executeQuery();
   
          if (rs.next()) { 
              roleList.add(rs.getString("rolename")); 
          }
      } catch (Exception e) {
          LOGGER.error("Error when loading user from the database " + e);
          e.printStackTrace();
      } finally {
           try {
               rs.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing result set." + e);
           }
           try {
               stmt.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing statement." + e);
           }
           try {
               con.close();
           } catch (SQLException e) {
               LOGGER.error("Error when closing connection." + e);
           }
       }
       return roleList;
 }
 
 /**
  * Returns JDBC connection
  * @return
  * @throws LoginException
  */
  private Connection getConnection() throws LoginException {
  
      String dBUser = (String)options.get("dbUser");
      String dBPassword = (String)options.get("dbPassword");
      String dBUrl = (String)options.get("dbURL");
      String dBDriver = (String)options.get("dbDriver");

      Connection con = null;
      try {
         //loading driver
         Class.forName (dBDriver).newInstance();
         con = DriverManager.getConnection (dBUrl, dBUser, dBPassword);
      } 
      catch (Exception e) {
         LOGGER.error("Error when creating database connection" + e);
         e.printStackTrace();
      } finally {
      }
      return con;
   }
}

The abort() method of the login module will be invoked if something went wrong within the login() or commit() method execution. In this kind of situation, We can not say that the authentication process was successfully completed and the required clean up operations can be done within the abort() method, if the authentication process encountered a failure.

We can utilise the 'options' map which was initialise within the initialize() method of the login module to get the configuration information declared within the 'jass.config' file. You can come up with a good technique to get JDBC connection object. I did not concentrate on that with in this tutorial and only wanted to show you the mechanism, How the things should be done.
By now, We have completed the thing which are required for basic JAAS authentication module. Next, We should configure our security constraints in web.xml file.
  
<login-config>
     <auth-method>FORM</auth-method>
     <realm-name>rainyDay</realm-name>
     <form-login-config>
          <form-login-page>/login.jsp</form-login-page>
          <form-error-page>/error.jsp</form-error-page>
     </form-login-config>
</login-config>
<security-role>
    <role-name>*</role-name>
</security-role>
<security-constraint>
    <web-resource-collection>
         <web-resource-name>Rainy day</web-resource-name>
         <url-pattern>/</url-pattern>
         <http-method>POST</http-method>
         <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
         <role-name>*</role-name>
    </auth-constraint>
</security-constraint>

With the above security constraints, if some request comes to a particular resource in the protected area of the application with out the authentication, the request will be redirected to the 'login' page. Next, I will show you the simple HTML form which invokes our login module with the submission of the form.

 <form id="loginForm" name="loginForm" method="post" action="j_security_check">
        User Name : <input id="username" type="text" name="j_username" class="textbox"></input>
        Password : <input id="password" type="password" name="j_password" class="textbox"></input>
        <input name="login" type="submit" value="LOGIN" id="submit" class="button blue">
 </form>

So, We are done with that.This is very basic implementation of JAAS. The advantage of this kind of JAAS module is, We can switch to a different login module implementation just with a single configuration change and without doing any modification to our existing code. And also this is container independent. If You want to deploy this with jBoss server, instead of 'jass.config', You can use 'login-config.xml' file in jboss conf folder. As I promised you to explain, How to invoke this kind of login module explicitly, here it is. There are some circumstances, We need to authenticate a particular user with pragmatically, but still We should use our implemented login module. In this kind of situation, the big problem is providing user identities (user name, password etc) to the our login module. In the above case, We used a 'CallbackHandler' class which is 'JAASCallbackHander' provided by apache catalina. But, Here We can not use and We have to implement our own call back handler class.

JAASCallbackHandler.java
package com.rainyday.server.login;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.log4j.Logger;

/**
 * @author semika
 *
 */
 public class JAASCallbackHandler implements CallbackHandler {

 private static final Logger LOGGER = Logger.getLogger(JAASCallbackHandler.class);
 
 private String username = null;
 private String password = null;
 
 /**
  * @param username
  * @param password
  */
 public JAASCallbackHandler(String username, String password) {
     this.username = username;
     this.password = password;
 }


 @Override
 public void handle(Callback[] callbacks) throws IOException,
   UnsupportedCallbackException {
  
     LOGGER.info("Callback Handler invoked ");
  
     for (int i = 0; i < callbacks.length; i++) {
        if (callbacks[i] instanceof NameCallback) {
           NameCallback nameCallback = (NameCallback) callbacks[i];
           nameCallback.setName(username);
        } else if (callbacks[i] instanceof PasswordCallback) {
           PasswordCallback passwordCallback = (PasswordCallback) callbacks[i];
           passwordCallback.setPassword(password.toCharArray());
        } else {
           throw new UnsupportedCallbackException(callbacks[i], "The submitted Callback is unsupported");
        }
     }
 }
}

Next, We have to create an instance of 'LoginContext' to invoke the authentication explicitly.

    LoginContext lc = null;
    try {
        lc = new LoginContext("rainyDay", new JAASCallbackHandler(username, password));
        lc.login();
        //get the subject.
        Subject subject = lc.getSubject();
        //get principals
        subject.getPrincipals();
        LOGGER.info("established new logincontext");
    } catch (LoginException e) {
        LOGGER.error("Authentication failed " + e);
    } 
If We end up with the execution of above code without any exception, that implies the authentication was succeeded. If an exception was encountered, authentication has failed. 

That's all from this tutorials. http://docs.oracle.com/javaee/1.4/tutorial/doc/Security5.html was a good tutorial for me to understand login authentication.

Monday, January 23, 2012

Java enum - constant-specific method implementations

This is a one of the interesting feature with java enum introduced with java 1.5. Normally We are using java enum to define some set of constants which enhance code readability and provides compile time type safety and more. If We want to define some behaviors specific to each of the constants define in enum, How Can We do it? 

There is a way to associate a different behavior with each enum constant.Declare an abstract method in the enum type, and override it with a concrete method for each constant in a constant-specific class body. Here is an example.

/**
 * @author semikas
 *
 */
public enum Operation {

 PLUS {
      @Override
      double apply(double x, double y) {
          return x + y;
      }
 },
 MINUS {
       @Override
       double apply(double x, double y) {
           return x - y;
       }
 },
 TIMES {
      @Override
      double apply(double x, double y) {
           return x*y;
      }
 },
 DIVIDE {
       @Override
       double apply(double x, double y) {
           return x/y;
       }
 };

 abstract double apply(double x, double y);
}

Thursday, January 12, 2012

String reverse algorithm

I went for a java technical interview recently and they told me to write simple java method to get the reverse of a given string object. I used java's 'StringBuilder' class and it provides 'reverse()' method. I guess, I am correct. They smiled and went one step ahead. They told me to do the same thing without using any java providing function and write my own function to reverse the string. I wrote that as well. Finally they told me to write it using the recursive algorithm. I was little stuck and they moved to next question. 

I came home and though for a algorithm to reverse the string. I came up with this solution. 

We can get the character array from the given string and characters can be swapped in the following manner.



public String reverseStr(String s) {
    char arr[] = reverseStr(0, s.toCharArray());
    return new String(arr);
}
private char[] reverseStr(int charIndex, char[] arr) {

    if (charIndex > arr.length - (charIndex+1)) {
      return arr;
    }
    char temp = arr[charIndex];
    arr[charIndex] = arr[arr.length - (charIndex+1)];
    arr[arr.length - (charIndex+1)] = temp;
  
    charIndex++;
  
    return reverseStr(charIndex, arr);
}
My implementation may not be the best way of doing this. I just wanted to find an algorithm for this.
Share

Widgets