Friday, December 29, 2006

Caching headers in HTTP

All dynamic applications need to prevent caching so that the request actually reaches the server each time.
In this post, I found over the internet, a good explanation of the different cache headers was given. Snippet from the post:

First of all you have to remember that these directives are used by all downstream caches (proxy servers and the browser) and therefore what might work in one situation (say, a direct connection between web server and client) may not work if there is a caching proxy server in between if the cache control headers are not thought through carefully.

Taking the directives in turn:

response.setHeader("Pragma", "no-cache");
This is the only cache control directive for HTTP 1.0, so should feature in addition to any HTTP 1.1 cache control headers you include.

response.setHeader("Cache-Control", "no-cache"); // HTTP 1.1
This directive does NOT prevent caching despite its name. It allows caching of the page, but specifies that the cache must ask the originating web server if the page is up-to-date before serving the cached version. So the cached page can still be served up i- f the originating web server says so. Applies to all caches.

response.setDateHeader ("Expires", 0); // HTTP 1.1
This tells the browser that the page has expired and must be treated as stale. Should be good news as long as the caches obey.

response.setHeader("Cache-Control", "private"); // HTTP 1.1
This specifies that the page contains information intended for a single user only and must not be cached by a shared cache (e.g. a proxy server).

response.setHeader("Cache-Control", "no-store"); // HTTP 1.1
This specifies that a cache must NOT store any part of the response or the request that elicited it. Adding these two headers should prevent the caching of pages anywhere between the web server and browser, as well as in the browser itself. The meaning of each directive is very specific and so a given combination of directives has a different effect in any one environment.

Showing Modal windows in HTML Browsers

It had always been a challenge for web developers to show modal dialog boxes using Javascript that works across all browsers.

IE has a proprietary javascript method called 'showModalDialog', where as FireFox accepts an 'modal' attribute in the window.open function. Here's a sample code for the same:

function modalWin()
{
if (window.showModalDialog)
{window.showModalDialog("xpopupex.htm","name",
"dialogWidth:255px;dialogHeight:250px");}
else
{window.open('xpopupex.htm','name','height=255,width=250,toolbar=no,
directories=no,status=no,menubar=no,
scrollbars=no,resizable=no ,modal=yes');}
}

But there still remains one more problem. How to disable the close button in the dialog. There is no support in JS for that, hence the simple answer is that NO-it cannot be done.

But we can write our own custom dialog. An example of the same is given here:
http://javascript.about.com/library/blmodald1.htm But this involved a lot of work.

Being lazy, I was looking for a out-of-box solution and my prayers were answered - The Yahoo widget UI library. This is one of the coolest AJAX, DHTML library I have seen in years and its FREE for all use.
The Yahoo UI Library has a SimpleDialog Component that can be made modal and also the close button on the header can be disabled. Also the control is very simple to use.
http://developer.yahoo.com/yui/container/simpledialog/

Thursday, December 28, 2006

Dealing with currency calculations

Many novice developers use 'float' and 'double' data-types to represent dollars and cents. This is dangerous as float/double calculations always involve rounding off and precision errors.

More info can be found at the following links:
http://www-128.ibm.com/developerworks/java/library/j-jtp0114/
http://www.javaworld.com/cgi-bin/mailto/x_java.cgi
http://en.wikipedia.org/wiki/IEEE_754

Currency values require exactness. Hence use the 'BigDecimal' class in Java for handling currencies. Here is some code snippet:

//Get the base value of the policy and store it in a BigDecimal object
BigDecimal d = new BigDecimal("1115.32");

//get the extra's multiplier from database
BigDecimal multiplier = new BigDecimal("0.0049");

//Do the multiplication - use methods of Big Decimal
BigDecimal d2 = d.multiply(multiplier);
System.out.println("Unformatted no scale: " + d2.toString());

//Set the scale (2 decimal places) and round-off mode
d2 = d2.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("Unformatted with scale: " + d2.toString());


NumberFormat n = NumberFormat.getCurrencyInstance(Locale.UK);
double money = d2.doubleValue();
String s = n.format(money);
System.out.println("Formatted: " + s);

Wednesday, December 27, 2006

Javascript: Conditional Comments and Conditional Compilation

Recently came across some cool new features of Javascript that reduced the amount of coding required. For many years, developers have been writing Javascript code to detect the browser type and accordingly fire javascript functions or do a document.write()

But now there are more developer-friendly ways of detecting the browser type and handling content.
Conditional Comments: These look like HTML comments, but IE browsers treat them differently.
For e.g.
<!--[if IE]>You are using IE (IE5+ and above).<![endif]-->
The above line would be rendered only if the browser is IE.

To render something if the browser in non-IE use the following:
<![if !IE]>You are NOT using IE.<![endif]>

We can also check the IE version number:
<!--[if IE 6]>You are using IE 6!<![endif]-->

Another feature of IE is Conditional Compilation. Non-IE browsers would ignore the @cc block
/*@cc_on
/*@if (@_win32)
document.write("OS is 32-bit, browser is IE.");
@else @*/
document.write("Browser is not IE (ie: is Firefox) or Browser is not 32 bit IE.");
/*@end@*/

Wednesday, December 20, 2006

Beware of using Application Context in a WAS clustered environment

Websphere 6.1 Network Deployment App Server Package provides out-of-the-box support for clustering, thus providing for fail-over and load-balancing.
In a cluster, WAS provides data-replication services for 'session' data, 'WAS dynamic cache' data, etc. across member in a cluster.
But it does not provide replication of objects stored in the Application context or Servlet Context across the nodes of the cluster.

Hence if Ur application relies on state stored in the App Context, then it would fail in a cluster unless U make sure that all the concerned requests (which expect objects in the context) have the same JSESSIONID cookie and session affinity is configured on WAS. In this case, the WAS infrastructure would consider the jsession id present in the request and forward the request to the appropriate Appserver.

Another solution is to use a database or a file and not the Servlet Context for storing data to be shared across sessions.