Saturday, March 12, 2011

jQuery FlexGrid & Spring MVC 3

Recently I have been working on Spring MVC 3. There is inbuilt support for returning JSON data using @ResponseBody annotation. Just make sure that jackson-all-x.x.x.jar is on your classpath. I used jackson-all-1.7.4.jar.This works great.

I wanted to display the results in a tabular format with some basic sorting and paging functionality with AJAX. So I thought I will give a shot at jQuery. jQuery is such an amazing JavaScript library it makes this a lot easier when it comes to working with JavaScript or manipulating DOM.

I found this amazing jQuery plugin, FlexGrid. It was pretty much what I wanted. Though it does not support i18N or themed L&F, it did the job for me.

So I started integrating the pieces. jQuery FlexGrid expects the JSON data to be in a specific format:

   total: (no of rec)
   page : (page no)
   rows : [{id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]},
           {id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]}
          ]

But the data returned from the method with @ResponseBody annotation is in the following format:

   
{(col1 value) , (col2 value) ,..}

So I thought I might as well go ahead and modify my DAO's to return the data in the required format. But well, why should I modify my DAO's? Its after all a UI layer requirement. This is what I came up with.

Write a wrapper class that will hold the data required for FlexGrid and send this as a JSON response. Here's the wrapper class:

import java.io.Serializable;
import java.util.List;

/**
 * Wrapper class for JSON data to send to the client.
 * 
 * Currently we are using jQuery FlexGrid for displaying JSON data in table.
* * jQuery FlexGrid plug-in requires data to be in the below specified format. * * * total: (no of rec) * page : (page no) * rows : [{id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]}, * {id: idVal, cell: [ (col1 value) , (col2 value) ,.. ]} * ] * * To keep the data service independent of this requirement as far as possible, * the id, cell format specifically ignored. we wrap the result from the data * service and further format the result using JavaScript as required. * * * @author Enterprise Integrals * * @version 1.0 * @see jQuery FlexGrid * * @param T generic data type for list of objects to be sent in the JSON response. */ public class JsonDataWrapper<T> implements Serializable { private static final long serialVersionUID = 1L; //current page private int page; //total number of records for the given entity. private long total; //list of records to be displayed. private List<T> rows; public JsonDataWrapper(int page, long total, List<T> rows) { this.page = page; this.total = total; this.rows = rows; } // getter setter }
Here is how it is used in Spring MVC 3
/**
* FlexGrid submits the following parameters
* page: current page
* rp: rows per page
* sortname: sorting done on which column:
* sortorder: sort order asc/desc
* query: search criteria if you are using search option
* qtype: search on which column in grid. this is again customizable.
* 
* These parameters can be used as filters in the DAO to get the data.
*
* By default the FlexGrid uses POST. You can change to GET.
* @param T the entity list to displayed in grid
*/
@RequestMapping(value="/some Path", method= RequestMethod.POST)
public @ResponseBody JsonDataWrapper<T> getRows(WebRequest request) {
 //get the current page posted from the grid.
 int page = Integer.parseInt(request.getParameter("page"));
 //get the list of objects to be displayed from the db calling the service
 //the total number of pages are dynamically calculated on the basis of the total number of rows in the table. get that.
 JsonDataWrapper<T> jdw = new JsonDataWrapper<T>(page, total rows, rows);
 return jdw;
}
But there is a catch here. The FlexGrid plugin again refuses to render the data. The reason is the List<T> rows is again a list of objects returned from the DAO layer. It does not format the data as required by FlexGrid plugin. How do we do that? So I decided lets not put this logic in our MVC implementation. Here is how the data is set on to the FlexGrid using JavaScript.

 
$("#flex1").flexigrid({
   // standard flexgrid configuration as per your need,
   preProcess: formatData
});

Note the preProcess definition. It pre processes the data before the grid is populated with the JSON data return from the server. You can inline the function that actually formats the data but I kept it separate. Here it goes:

function formatData(data) {
 var rows = Array();
 $.each(data.rows,function(i,row){
                //id can be mapped to any attribute of the return object in the list
  rows.push({id:row.val1, cell:[row.val1,row.val2]});
});
 
 return {
  total:data.total,
  page:data.page,
  rows:rows
 };     
}

Now the grid populated correctly. There are other grid plugins for jQuery but FlexGrid & jQGrid are the best. FlexGrid has lot less functionality as compared to jQGrid but I like it because its light. For advanced features you can have a look at jQGrid.

Sunday, February 20, 2011

PHP 5.3 Date Timezone issue

I was recently trying to setup PHP on my development machine. I downloaded the php-5.3.5-Win32-VC6-x86.zip for Windows and started to manually configure PHP (to get a feel. You can ofcourse use something like XAMPP to get started quickly.)

Then I quickly executed some PHP scripts and found everything was running fine. I dumped some of the PHP samples I had and played around until one started complaining

It is not safe to rely on the system's timezone settings.

Little researching solved the issue. PHP 5.3 requires you to set date.timezone in php.ini file

e.g. date.timezone = Asia/Calcutta

http://nl3.php.net/manual/en/timezones.php

Thursday, June 17, 2010

Which style of WSDL should I use?

A Web Services Description Language (WSDL) binding style can be RPC or document. The use can be encoded or literal. How do you determine which combination of style and use to use? The author describes the WSDL and SOAP messages for each combination to help you decide.

Which style of WSDL should I use?

Saturday, October 31, 2009

Java 5 EOSL

Java 5 has reached End Of Life. Most of the bigger organization in the service industry are still using Java 1.4 and are not willing to migrate as they anticipate migration issues and feel that its a risk and unjustifiable. Java 6 has been out for a long and its time to take advantage of the new features, especially the web services stack (JAX-WS). There are lot of performance improvements which might be one reason to migrate.

On a personal note migration is little to do with technical, but more often political.

http://java.sun.com/products/archive/eol.policy.html

Thursday, September 17, 2009

File Download issue with IE over HTTPS

I am currently working on a project where the user can download PDF, XLS and CSV files. These files are dynamically generated within the application and thrown out on the browser when the user clicks on a particular link. This was running like a charm till recently, we decided to move to HTTPS and it stopped working. We were getting a message saying

"The file could not be stored in cache."
"Internet Explorer was unable to open this site. The requested site is either unavailable or cannot be found. Please try again later."


After a little googling I found that it is a known issue with IE. Refer to the link below. http://support.microsoft.com/kb/815313 But installing a hotfix was out of question. So I went looking for a solution that could be handled through code and here is the solution that seems to work for us and the magic required to satisfy IE
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "max-age=0");