Friday, 28 November 2008

Why JSPs are a bad idea

It's pretty much accepted wisdom these days that no-one uses JSPs in the way they were originally conceived. We used to use a <jsp:bean tags to create or find a Java object, and then use scriptlets - little snippets of Java enclosed in <% and %> symbols - to insert data into the page, or to implement some basic logic. After many spaghetti JSPs had been written, it became clear that passing a web request direct to a JSP and programming that one JSP to deal with all possible complications was a really bad idea. It produced brittle web applications that were hard to fix and even harder to extend.

Nowadays, most people use some kind of MVC architecture. Instead of each web request being passed directly to a JSP, it is passed a handler, be it a servlet, a Struts action, or whatever. The handler, written in Java, deals with the request and decides what needs to be done. It retrieves the necessary data, and then invokes a view to create an HTML page. There are various ways of implementing views, but by far the most common method is to use a JSP. The data is attached to the request object using the setAttribute method, and the request is forwarded to the JSP, which retrieves the data either using scriptlets (not usually recommended) or via a tag library, such as JSTL or the Struts 2 tag library.

In my view, JSPs are a bad idea even for this limited usage. They have numerous problems, most of which could be fixed with better implementations (why, after all this time, can't an exception generate a stack trace giving you the actual line number in the JSP?), but there are two fundamental problems:
  1. each JSP is tied into the web application framework as a web page. That means you have to use something else to generate e-mails, for example, or any other templating task you may have. It also means that common features of your dynamic web pages, such as setting a charset encoding or cache-control, need to be repeated in every page. There is no way to specify these things once and have them honoured everywhere.
  2. there is no workable provision for re-use. You have two choices: use an include file (static or dynamic), or take the repeated code out of the JSP language altogether by writing a tag library.
Include files are incredibly primitive. They offer no way at all to manage data coupling between the included code and the page that calls it, so they are best restricted to situations where the included code has little or no data in common with the calling page.

Writing a tag library is hard work, although for code that will be re-used often, it's worth it for the clean interface and documentation features. What it doesn't do is to give me the quick, simple re-use that I can get in Java. If I'm writing a Java method, and I realise that what I need is something I've already written, my IDE (Eclipse or IDEA) can easily convert a fragment of Java into a method I can call. Most Java programmers will have heard of the DRY principle: Don't Repeat Yourself. Ensure that common functions are implemented in common code, so that when you have to fix them, which you will, you only have to fix them once.

Exactly the same thing applies to HTML coding. Web users expect consistency. For example, your website might display a product image with the product name below it, plus various other features: a hover effect with a short description and a hyperlink to the full product page. The important thing is to make sure that every time a product image appears, exactly the same features appear. The best way to do this is to use the same code to generate it every time.

Using an MVC framework lets you use other tools to generate views. There are tools adapted to this specific purpose, such as FreeMarker and Velocity, both of which address the two issues just described, and either of which is a great improvement over using JSPs. Generic, multi-purpose tag libraries such as JSTL and the Struts 2 tag library are a valiant effort to patch up the defects of the JSP system, but even they cannot overcome the most fundamental problems. The JSP system is broken, and there's no longer any need to use it. There are better alternatives.

Tuesday, 25 November 2008

CSS Resources

Learning CSS, and how to structure my HTML to use it properly, has been a long process of trial and error. I've learned some things from books, but mainly it's been websites where I've gleaned the vital information. Here are some of them.

A good starting point for newcomers to any web technology is W3Schools. This amazing site has extensive tutorials for HTML, XHTML, CSS, Javascript, and much else besides. They have a nifty little gadget called the TryIt Editor which displays the text of any example, then lets you edit it and see the effect of your changes. I've used this more for Javascript than CSS, but it's still amazing.

The most convenient reference sites I've found are Brian Wilson's Index DOT Html and Index DOT Css. If I need to know the exact syntax of the CSS background property, that's where I look. The comparative information about which browsers supported what, and how well, used to be really valuable, but these sites haven't been updated since 2003, so they don't have information about current browsers. They are still good on the differences between HTML and XHTML, though.

Another reference site that looks good, and is certainly more up-to-date, is SitePoint.

HTML/CSS design is a lot easier than it used to be, because of the much wider acceptance of standards. Coding for different browsers has not disappeared altogether, unfortunately, but we don't need to do nearly as much as we used to! One man who has done much to promote the acceptance of modern ways of doing things is Jeffrey Zeldman. His book "Designing with Web Standards" has been enormously influential, as have the various websites that he runs. The on-line magazine A List Apart is full of technical how-to articles, and has been responsible for promoting some techniques that have now become widely used, such as the sliding door technique for adjustable backgrounds and CSS-only dropdown menus.

Now that we code with standards, we generally test our pages first in Firefox, and only when they work beautifully in Firefox do we try them out in Internet Explorer. This isn't only because Firefox supports the standards better than IE, although it does; it's because Firefox has Firebug. This amazing tool really lets you see what's going on with your HTML and CSS: exactly how big each element is, where its margins and padding are, and much else besides. Before we had Firebug, the only way to see why your page wasn't laid out the way you expected was to make temporary changes to your stylesheet. If you wanted to see where a particular element reached to, you had to add a background colour or border to it, and re-load the page. Repeat for the next element, and keep going until you've tweaked every element on the page! Firebug has changed all that. You can adjust the CSS property values by hand until your page looks exactly the way you want it, and then copy the values back into your stylesheet. Laying out a web page is much quicker than it used to be!

Monday, 24 November 2008

CSS, Picture Gallery Style


Last week's entry spoke about displaying a list of items with several items across the page. We could call that picture gallery style; it looks rather like the thumbnail view in Windows Explorer. See the picture above.

Given that we're building our web pages in standards-compliant XHTML, positioning everything with CSS and not using tables, how do we lay out the images and their associated text? The obvious way to do this is to place each image and its caption inside a DIV element, and then style the DIVs using float: left. It couldn't be easier to generate the HTML. Each image gets simple markup, like this:

<div class="picture">
<img src="..."/>
<p>The Famous Crack in the Tate Gallery Floor</p>
</div>


and the CSS could hardly be simpler, either:

.picture { width: 150px; float: left; }

This is easy to code, and has the advantage that, if the page layout is liquid and allows the user to change the width, our pictures will move around too, displaying four, five, or more pictures across the width of the page. When you try it out, there are some problems:
  1. floated elements do not force their container to extend its height. If your picture DIVs are enclosed in something with a border, you will have to resort to trickery to get the border to expand around the pictures: either assign an explicit height to the container, or add some dummy content so that you can style it with clear: both.
  2. to make the captions word-wrap at a suitable width, you have to style the picture DIVs with an explicit width, as shown in the example above.
  3. if the picture DIVs have different heights, you may find that they don't stack properly, as shown in this picture:

This happens because the browser thinks that the third and fourth pictures can be flowed around the first two, as if they were text. That's exactly the correct interpretation of float: left, but it's not what we expect for this page. The only answer seems to be to assign an explicit height to each picture DIV, as well as the explicit width. That causes problems of its own in dealing with long captions: either they get truncated, or they overlap the picture below, or you need to allow for scrollbars.

For me, this is a case where an HTML table is fully justified. The only slight difficulty comes in dividing the list of pictures up in to rows, but that's very easy using the Struts 2 tag library, as shown in my previous post. Most systems for generating HTML can do the same thing almost as easily.

The markup for each picture is almost the same. Instead of <div class="picture">, we change the DIV tag to TD, making it <td class="picture">, and the CSS rule becomes this:

.picture { width: 150px; vertical-align: top; }

The resulting page looks like this:

Tuesday, 18 November 2008

Paging, Part 2

Yesterday's article started from a suggested technique using the display tags library, and showed how easily it could be adapted to work in Struts 2. This article shows how the principle behind that technique can be adapted to a different form of presentation.

Using display tags, a list of items is displayed in a table, with one item in each row of the table. Also, when there is more than one page of data, you see a set of links to other pages, like this:

First/Prev 1, 2, 3, 4, 5, 6, 7, 8 Next/Last

For a recent project, a different kind of display was expected. The page was designed to show several items across the page, each item in its own table cell. The links to other pages had to appear in a different format, with the page number in the middle of the page and links to previous and next pages at the right and left, respectively. I was also looking for a general solution that could be applied to various different pages across the site, with different lists of data, displaying the results in a similar format.

The centrepiece of the solution is an abstract action class called PageableAction. It has a property called page, which can be set from a request parameter, to specify which page is being displayed. The key methods are:

public int getNumberOfPages()

which returns the number of pages, and

public List<E> getPageList()

which returns a list of one pageful of items to display. Note that the PageableAction is a generic type, with a parameter indicating the type of items returned. More about this later. PageableAction is designed to operate in either of two modes. In one mode, where a subclass already has a complete list of items in memory, then it overrides the getFullList() method, and the number of pages and the page list are computed by methods in the superclass. The other mode is intended to be used with a source of data that is capable of delivering results one page at a time, such as a Hibernate query. In this mode, the subclass overrides the getPageList() methods, and must also implement the getTotalNumberOfResults() method so that the superclass can calculate the number of pages correctly.

The results of a PageableAction can be displayed using a JSP built with the Struts 2 tag library. The relevent JSP code has two parts: the list of items, and the paging links. The list of items is displayed by iterating over the pageList, using an s:iterator tag, like this:

<table cellspacing="0" cellpadding="0" border="0">
<tr>
<s:iterator value="pageList" status="stat">
<td>
... lots of stuff omitted ...
<s:property value="name" />
...
</td>
<s:if test="((#stat.index + 1) % 4) == 0"></tr><tr></s:if>
</s:iterator>
</tr>
</table>

Note the other Struts tags in this fragment: the s:property tag, used to retrieve a property of the individual list item, and the s:if tag, which starts a new table row after every fourth item.

Below the table of items, the JSP displays the paging links. These are generated by an included JSP, which is used on every page that displays the results of a PageableAction. The included JSP is too big to show here in full, but its most important features are:

1. it uses the page and pageNumber properties from the PageableAction to control the display. The text is included within a single s:if tag, so that if there is only one page, no links are displayed. Here's the tag:

<s:if test="%{numberOfPages > 1}">
...
</s:if>

2. it uses the s:url tag to generate links. Links to other pages have a page parameter set using the s:param tag, like this:

<s:url includeParams='get'>
<s:param name='page' value='%{page + 1}'/>
</s:url>

The s:url tag defaults to the URL of the page being displayed; all we do here is to add or override the page parameter.

This technique allowed me to implement paged lists in a consistent way across the entire site. I'm quite pleased with it, but it leaves one question in my mind: was it helpful to define PageableAction as a generic type? In most cases, the data comes from a Hibernate query. Look at the stages that it passes through to generate the web page:
  1. the Hibernate query
  2. a DAO object
  3. a service object
  4. the action object
  5. the JSP.
There are four movements of data from one level to another, and the Java compiler can only check two of them. The JSP tags and the Hibernate query are interpreted at runtime, so any errors are not detected until you run the code. To get the limited amount of compile-time checking that is available, you have to write code in the DAO, service, and action layers. Perhaps it would be better to create a single set of classes that could handle any Hibernate query, and forgo any compile-time checking at all.

Monday, 17 November 2008

Paging using Display Tags

One problem that crops up over and over again is that of breaking up a long list of items to be displayed into pages. There's a very handy tag library that handles the presentation for you: Display Tags. If you're using Spring and Hibernate, there are a couple of articles that give some detailed code examples of how to link these tags with Hibernate queries: pagingappfuse in GoogleCode, and a blog entry by Ram Gorti.

Using these techniques, it's very easy to create a simple paged and sorted display. The display tags library creates a table with one list item per row, with or without column headers that can be clicked. It generates links to URLs with parameters page (the page number), sort (the field name to sort by), and dir (the sort direction). My project was built using Struts 2, not Spring MVC as in the examples, so I couldn't use them directly, but it was simple enough to adapt. The elements of this solution are:

1. a JSP including the tag library calls to generate the table:

<display:table name="userList" id="element" cellspacing="0"
requestURI="/cms/user/index.html" sort="external">
<display:column property="firstname" title="First Name" sortable="true" sortname="firstname">
... other columns omitted ...
</display:table>


2. a Struts action with page, sort and dir parameters, as described above. It also has a getUserList() method which returns...

3. an implementation of the PaginatedList interface, which populates itself using service layer calls:

public class PagedUserList implements PaginatedList {

private int pageNumber;
private int pageSize;
private String sortCriterion;
private String dir;
private int fullListSize;
private List<User> list;

public PagedUserList(UserService userService, int pageNumber, int pageSize,
String sortCriterion, String dir) {
super();
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.sortCriterion = sortCriterion;
this.dir = dir;
this.fullListSize = userService.getAllUserCount();
this.list = userService.listAllUsers(pageNumber - 1, pageSize, sortCriterion, dir);
}
... getter methods omitted ....

4. service layer methods which simply delegate to DAO methods;

5. A DAO method using a Hibernate Criteria query to retrieve the appropriate data:

public List<User> listAllUsers(int page, int pageSize, String sort, String dir) {
Criteria criteria = getSession ().createCriteria (User.class);

Order nameOrder = "desc".equalsIgnoreCase(dir) ? Order.desc(sort) : Order.asc (sort);
criteria.addOrder (nameOrder.ignoreCase());
criteria.addOrder (Order.asc ("id"));
criteria.setFirstResult (page * pageSize);
criteria.setMaxResults (pageSize);

return criteria.list ();
}

Of course these methods could be generalized to operate on any class, not just a specific class as in this example, and to add some kind of selection to the query, instead of returning all the data. However, for a quick and easy way to display the data, this worked fine.

The next problem was not simply to select data, but to display it in a different way. Isn't it often the case that once a technique has been well enough understood to be codified into a library, users' expectations have moved on, and the technique isn't relevant any more? If you're happy with data displayed in columns, one item per row, with clickable column headers for sorting, then the display tags library does a fine job. However, I needed to create a different kind of page layout, so a slightly different technique was needed. That's the subject of the next article.

Sunday, 16 November 2008

Introduction

Over the last five years, I have worked on a number of web application projects using Java and J2EE technologies. Like everyone working in this space, I spend a lot of time trying not to re-invent wheels. There are so many common tasks, from pooling database connections to managing user logins and building drop-down menus, that whatever you need to do there's a very good chance that an open-source product exists that can do it for you, or at the very least get you a long way towards your goal. This blog is a personal notebook about the software that I have worked with, and about the tricks and techniques that I have found useful. It's partly for my own use, so that I can refer back to things I've done in the past, but it's also meant for other people to use, and to add their own comments and suggestions.

The common factor in all these projects, apart from Java Enterprise Edition itself, has been the Spring framework. Spring is a layered Java/J2EE application platform, based on code published in Expert One-on-One J2EE Design and Development by Rod Johnson (Wrox, 2002). It's designed to make J2EE development simpler, and it does that by providing a common configuration mechanism which lets you wire together different Java objects to build an application. On top of the configuration mechanism, it provides components that you can use directly, for example to interface with a database access product such as Hibernate, and to manage transactions. Once you start using the configuration mechanism, variously described as an inversion-of-control container, a bean factory, or a web application context, all the other parts are optional. You can choose from a wide range of components, some of them provided with Spring, some of them from other open-source projects. Some examples are:
  • database access: either an object-relational mapping tool such as Hibernate or Toplink, or (at a lower level) JDBC access using spring's own tools;
  • web application frameworks, such as Apache Struts 2 and Spring MVC;
  • free-text indexing with Apache Lucene.
Later posts in this blog will discuss some of these components.