Sunday, May 20, 2007

servletContext.getRealPath() issue

Our application was using getRealPath() method to obtain the base path of the web application on the server. I noticed that the method was not behaving consistently across JEE containers.
On Windows/Tomcat5.5, getRealPath returned the path with a '/' at the end.
But on Solaris/Websphere, getRealPath returned the path without a '/' at the end.

The best way to handle this is to have a utility method that would handle all cases :-
String realPath = 
getServletContext.getRealPath(path);

if ((realPath != null)
&& !realPath.endsWith("/"))
realPath += "/";
Also check if using getRealPath is really required. The Servlet API specifies a temp directory that can be accessed using the following code:
File dir=(File)getServletContext().getAttribute
("javax.servlet.context.tempdir");

Tuesday, May 15, 2007

Silently print PDFs on the browser

If your web application needs to print PDF's silently on the browser, then check out this blog.

Of all options given, I found the iText trick the simplest to use. The concept is quite simple:
- Create a PDF on the fly using iText
- Embed Acrobat Javascript into the PDF that would print it automatically to the default printer.
- Open the PDF document in a iFrame that is hidden (size 0*0)

A live example can be found here.

Thursday, May 03, 2007

Modal Dialog submit issue

In our application we were using a modal window pop-up. The user has to enter some fields and submit the form. The strange thing was that whenever I submitted the form, a new window was getting poped up.
I knew there was nothing wrong with the javascript code...so I googled around a bit and found the soultion here.

All that is needed is to add the following line inside the "head" tag of the modal page :
<base target=_self>

Generating PDFs on the fly

If we need to generate PDFs on the fly in a JEE web application , then we have 2 open-source options: using Apache FOP or iText.

The approach used by both the leading projects is different. Apache FOP uses XML/XSL to create a XSL-FO file using XSLT Transformation. This XSL-FO is then rendered into a PDF using the PDF FO processor. This is a pretty neat solution as there is a clear separation of concerns. But the only caveat is that U need to have a pretty good hold over the XSL language, which in my personal opinion is very arcane and difficult to learn. But if you gain mastery over XSL, then there is pretty much nothing U cannot do with FOP :)

iText is a pure Java API that allows developers to create PDFs on the fly. For e.g. the iText API would have methods such as 'addPara','addBlock','addImage' etc. etc. So U end up embedding the presentation logic in Java code...but it may not be a big deal for anyone except design purists. It is also possible to use absolute coordinates while creating your PDF's, but I would advice against if there is a possibility of the look&feel of reports changing often.

iText is hugely popular and has been ported to .NET (C-Sharp port known as iTextSharp and the J-Sharp port known as iText.NET)
The popular JasperReports open-source reporting tool uses iText in the background to make PDF documents. Also iText boasts of superb speed - (Creating a 1000 page PDF takes only a few seconds). Even on the FOP site, they recommend iText as a post-processor tool for merging, encrypting, changing PDF documents.

If someone is looking only for a PDF manipulation tool then they should have a look at pdftk. It is also based on iText.

Tuesday, May 01, 2007

Setting Cache headers for Gifs, Css and JS files

By default, browser and servers use the "if-modified-since" header to check if the file should be downloaded from the server or given from the cache.
Though this default behaviour is good for performance, we can increase the performance by giving a cache expiry period. This would make the browser cache the content for that period - i.e. the browser won't even make "if-modified-since" conditional fetch requests.

The best place to set these headers in a J2EE application is thru a filter.
Suppose you want to cache GIFs, CSS and JPEG for 2 hours, just add this header in the response:
Cache-Control: max-age=120

Setting nocache headers in Struts Applications

In older versions of struts, it was a common practise to extend the ActionServlet and set the no-cache response headers there, so that they are applied to all requests.

In Struts 1.2.x, there is a easier way - without writing a single line of Java code.
Just add the "nocache" attribute to the controller element in struts-config.xml file.

<controller
processorClass="MyRequestProcessor"
nocache="true" />

Disabling keep-alive connections in Tomcat

I was using TcpTrace utility to dump my HTTP requests/responses. But the problem was that my Server (Tomcat) was using keep-alive connections and bcoz of this, the output in TcpTrace was all muddled up.
Disabling keep-alive connections in Tomcat 5.5 was quite simple:

Just add the maxKeepAliveRequests="1" attribute to the Connector tag in server.xml

CSS caching in IE

A strange problem regarding CSS caching had frustrated me for a whole 2 hours today.

The problem was reported by one of the developers that even if the CSS on the server was changed, IE was still used the cached version. I checked the application and found that there were no Cache headers that were set. This meant that IE should have made a GET "if-modified-since" request everytime for the CSS.

I even dumped the requests using the TcpTrace sniffer. I could see that IE did send a request for the CSS file and also the server responding with the new CSS file. Still no change on the page ?? This really baffled me ...If I hit F5/refresh, then the new CSS was loaded, but if I revisited the page, then still the old CSS was being used..

Then I learned from some site, that IE behaves a bit oddly here : IE usually caches CSS files by browser session (until you exit the browser). With a new session, the browser does a head request to see if the file has been modified, if so it reloads. So if I logged off the application and logged in again, the CSS would be reloaded. Strangely, this would not always happen...But if I close the browser and open the application again, I always get the new CSS..
It seems that IE is a bit erratic in this respect...so to be absolutely sure that U get the new CSS, you may have to close the browser and open it again :)