Jeff Kunkle

XML
20061129 Wednesday November 29, 2006
Start with Something New

To one extent or another, I‘ve been involved with many projects whose goal was to replace an existing system while adding some new features. On the surface, these sound like rather straightforward efforts. After all, the existing system is the source for all your legacy system replacement requirements, right? Unfortunately, these projects often struggle and many are never deployed. Why? Because they don‘t start with something new.

In my experience, legacy replacement projects first focus on supplanting the features of the old system rather than building new capabilities. In many cases, the legacy system was built over a period of years where new features were continually added and refined. However, new development efforts are rarely given years to write replacement software for the legacy system. The result is usually an initial version that doesn‘t even provide the same capabilities as the old application and adds little or nothing new. Why would a busy user spend their valuable time to learn a new system that provides less functionality than what they have today? In many cases they don‘t and the system is labeled a failure before it even gets rolling.

Why not start by building the new features first? Hook your users with new capabilities they don‘t have today and slowly replace the legacy features until the existing system is no longer needed or used. As a side benefit, your users may decide they don‘t need certain features of the legacy system anymore or that they should work differently based on their experiences with the new capabilities you‘ve given them. At the end of the day, I think you‘ll end up with a more successful application that better addresses users‘ current needs.

Posted by jkunkle Nov 29 2006, 09:25:36 PM EST
20060711 Tuesday July 11, 2006
NotNull Hibernate Annotation Validation Problems

I recently decided to try out Hibernate's annotation-based validation framework. It seems like a great solution for ensuring consistent validation of the domain model regardless of the presentation tier (web interface, web service, etc.). It very much reminds me of the declarative validation available within Rails model objects.

To make a long story short, things did not go as well as I had hoped using a Hibernate Core 3.2.0 CR2 and Hibernate Annotations 3.2.0 CR1 combination. I struggled for hours trying to figure out why I was getting a "not-null property references a null or transient value" error rather than a validation error when attempting to use the NotNull validation annotation. Eventually I discovered the problem was not that the NotNull validation wasn't working properly, but that it wasn't running at all.

In order for the annotation-based validation framework to execute, Hibernate Annotations provides a ValidatePreInsertEventListener and ValidatePreUpdateEventListener to fire the annotation validations prior to persisting any changes to the domain model. "Pre-insert" and "pre-update" events are fired after other events, in this case SaveOrUpdateEvent(s). By default, Hibernate uses the DefaultSaveOrUpdateEventListener, which is an extension of AbstractSaveEventListener. The AbstractSaveEventListener checks for null values corresponding to non-nullable database columns ( AbstractSaveEventListener:284 ) before adding the insert or update events to the execution queue( AbstractSaveEventListener:290 ) responsible for triggering pre-insert or pre-update event listeners. In case that didn't make complete sense, the bottom line is the Hibernate Core checks entities against the null constraints of the database before the annotation-based validation framework has a chance to run.

Luckily, there is a workaround, although it feels like a bit of a hack. As I mentioned previously, the DefaultSaveOrUpdateEventListener gets a chance to run before any "pre-insert" or "pre-update" events so we can use that to our advantage. The following SaveOrUpdateEventListener simply extends the Hibernate Annotations-provided ValidateEventListener and calls the validation method on "save-update" events rather than "pre-insert" and "pre-update" events.


public class ValidationEventListener 
    extends ValidateEventListener 
    implements SaveOrUpdateEventListener {

  public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException {
    final SessionImplementor source = event.getSession();
    final Object object = event.getObject();
    if (!source.getPersistenceContext().reassociateIfUninitializedProxy(object)) {
      // only validate the entity if it has been changed
      final Object entity = 
        source.getPersistenceContext().unproxyAndReassociate(object);
      super.validate(entity, event.getSession().getEntityMode());
    }
  }

}

One extemely important thing to remember when using this workaround is that you must configure the DefaultSaveOrUpdateEventListener as the second "save-update" listener (following the ValidationEventListener) or your objects will never be persisted.

Posted by jkunkle Jul 11 2006, 08:59:58 AM EDT
20060625 Sunday June 25, 2006
XSS Vulnerabilities of JSP 2.0 Expressions

&JSP 2.0 introduced a handy new capability allowing you to use JSP Expressions directly within the template text (i.e. outside of tag libraries or tag files) of a web page. This allows developers to easily expose data and objects stored in application, session, request, or page scope using a simple Ant-style syntax. It allows you to replace this


<table>
<c:forEach var="book" items="${books}">
<tr>
<td><c:out value="${book.title}"/></td>
<td><c:out value="${book.author}"/></td>
<td><c:out value="${book.isbn}"/></td>
</tr>
</c:forEach>
</table>

with this

;code>
<table>
<c:forEach var="book" items="${books}">
<tr>
<td>${book.title}</td>
<td>${book.author}</td>
<td>${book.isbn}</td>
</tr>
</c:forEach>
</table>

As you can see, the syntax in the second example is much cleaner. But, “with great power comes great responsibility.” The chink in the armor that every tutorial I‘ve read (including Sun's Java EE 5 Tutorial) fails to mention is that the expression syntax does not escape HTML characters. Therefore, any web application using JSP Expressions to output unsanitized, user-entered data will be vulnerable to Cross Site Scripting (XSS) attacks.

Unfortunately, the cure for this XSS vulnerability leads us right back to our first example. As section 2.2.2 of the JSP 2.0 Specification reads, “In cases where escaping is desired (for example, to help prevent cross-site scripting attacks), the JSTL core tag c:out can be used.”

My advice is to use JSP Expressions only as tag library attribute values and stick to using JSTL‘s c:out tag for writing text to a page. Deciding which instances of template text expression usage are safe and which are not is simply too error prone and the consequences of a mistake too dangerous.

Posted by jkunkle Jun 25 2006, 03:46:48 PM EDT