Tuesday, February 5, 2008

One template file for all pages using Servlets and JSP

One of my recent tasks was making a new skin for one of our websites. the site had a common header, left side area and right side area that are to be shared among all pages. we used to include file for "header", "left side", "right side" in each of the pages.. it wasn't that pretty i know.

I wanted to think of something better where i can define the template in exactly one file and i do not have to include that file on every new page i add. something pretty much close the RubyOnRails "<% yield %>' directive to import the page content inside the template. i finally managed to do it.

I'll use two simple pages to illustrate the concept:

mahmoud.jsp


and index.jsp



what we want is to have each of the two pages displayed in a layout where is one header, banners and so. which will look like the following.





I was able to do this using a servlet that intercepts the request. and loads the template jsp file and pass the desired page to as a parameter to be included.

The template file is called template.jsp will look like:


The only line that matters in the template code is where we make the jsp:include page="<%request.getParameter("targetPage")%>"

The servlet intercepts http requests and loads this template using RequestDispatcher and passes the original desired page as a parameter:



The Servlet and servlet mapping in web.xml will look like



A note to be mentioned is that I had to configure my template to be initiated with requests to html pages (i can choose to work on any extension except jsp). When I configure my servlet mapping to be associated with jsp URLs, i get stuck in an infinite loop as since including the page inside the template results in a new jsp request.

The idea is simple. You are free to create your own template and to work on any file extensions in the url, but you have to specify a type other than jsp to avoid the infinite loop trap.

Bon appetite

Sunday, January 6, 2008

Restful Pagination in Rails

Have you ever tried to cache your paginated lists? Sadly, vanilla Rails wont help much as they ignore the url query parameters when caching and hence the page=x value is not honored and Rails caching (action or page caching) will simply stick to the first page rendered for all requests.

One might come with a solution that overrides the cache key generation to incorporate the query string, which will work, but will result in very long and ugly hash keys.

Luckily there is a better approach, if you simply defined routs for pages (for the paginated resources) and name them page parameter with the same name you give it in the paginator then Rails will pick up the route when creating paginated links.

In your routes.rb

map.resources :users
map.paged_users '/users/pages/:page'
map.formatted_paged_users '/users/pages/:page.:format'

once the above routes are in place, all you need is to make sure your paginators are using 'page' as the page parameter name and you will see the pagination links created like this:

/users/pages/1
/users/pages/2

Don't forget the formatted route to support pagination with various formats so you can use routes like:

/users/pages/1.xml

These urls are very cache friendly and adhere to REST much more than the default parameters based ones.

Happy caching (with pagination)