A maze of twisy little ecosystems, all isolated

dws on 2003-07-29T05:18:59

I've spent a bunch of time over the last two months reading J2EE books--Tomcat and Struts books in particular--looking for "best practices" for assembling an application. My partner is worrying about the database side of things, while I sort through schemes for managing sessions, JSP usage patterns, error handling, templates, unit testing, and overnight build stuff. We had a meeting today to hash out open issues.

In trying to fit together all of the best practice advice we're collecting, it's become pretty clear that many folks in the Java world have gotten so deep into their particular ecosystem that they have forgetten that others exist. Recommendations conflict. One camp rallies around "Use our marvelous class library, and do X, not Y!" (Where Y is something like embedded raw Java in JSPs), and another camp has a wonderful set of data access patterns that, uh, end up requiring intermediate bean objects to avoid putting raw Java in JSPs (thus cancelling out one of the benefits of the patterns). One camp decries putting anything besides cached data in the session object, while another camp has an otherwise marvelous form validation strategy that pretty much requires stuffing form data into the session object. Hello, leakage!

I get the impressions of small groups working in isolation, each clawing through the pain of building J2EE apps, offering up their particular scar tissue as a solution without first stopping to share notes.


Java Strategies

chromatic on 2003-07-29T05:56:26

The nice thing about Java is that BOTH camps have their own STANDARDS!

About half the time I look at a framework like Tomcat or Cocoon, I think, "That's really neat! To do useful things, you only have to implement these methods. All of the hard work's done for you." A few hours later, I realize that actually implementing those methods represents quite a bit of busy work anyway.

Re:Java Strategies

dws on 2003-07-29T06:03:51

And Struts is pretty nifty, until you realize how incredibly messy it can be to handle validation--particularly validation failures--when your form has been generated dynamically. Tabular data? Sure, Struts has tags to make that easy. Tabular forms? Uh... uh...

Just like any other...

lachoy on 2003-07-29T12:49:04

Any moderately complex application development environment is going to inspire the same sorts of camps to form. What struck me about Java web application development is how many similarities there are with Perl web application development. There are a few truths that for me were very consistent (in no particular order):
  • Do not put code in your templates. Ever. Use taglibs (Java) or plugins (Perl/TT) for nontrivial work.
  • Use an intermediate templating language for simple constructs like loops and conditionals. (This wasn't as possible in Java a couple years ago, but JSTL has made this much, much easier.)
  • Templates should never (well, almost never) access the data layer directly.
  • Database information should be brought in via objects rather than data structures. Tools like Hibernate (Java) or SPOPS/Class::DBI/etc. (Perl) make this simple. Passing along Maps/hashes seems very appealing at first, particularly with RowSetDynaBeans (in the commons-beanutils) and DBI's fetchrow_hashref, but you'll eventually want to add calculated fields, or standard formatting, or whatever, and then you'll be screwed because...
  • Code that feeds the data objects to the templates should not do any formatting. This includes pulling data out of objects for 'easier' template access. (Sorry HTML::Template folks...) This also includes summarizing data into separate fields. All the code (usually known as an 'Action') should do is assemble the data and make it available to the template. Anything else will eventually get you into trouble.
  • Formatting code should be centralized so that dates, money, names, etc. all appear the same everywhere.
  • Templates should be reusable for different actions, componentized if possible. That is, if I have a non-editable list of users I want to define it once and pass a collection of users to it from everywhere. (And if they're not componentizable you probably should pick a different templating technology...)

(there are probably a few more but these were on top of my head...)

And finally: a good framework (like Struts, or OpenInteract) should encourage you to do the right things by making all of the above easy.

Re:Just like any other...

dws on 2003-07-29T16:02:13

I'm mostly with you on this. The Struts "tiles" taglib (and the older, deprecated struts "template" taglib) are an elegant way to do templating. But heaven help you if you dare to either construct an <html:form> dynamically, or put multiple forms on a page. Dealing with validation failures becomes a nightmare, unless you're willing to violate another best practice by using the session object to cache everything you need to reconstruct the page that holds the form(s). If the user abandons the form, you've just polluted the session's properties namespace with stuff that might trip you up when they try to use other forms.

Re:Just like any other...

lachoy on 2003-07-29T16:49:05

That's one of the core assumptions Struts makes under the guise of usability. And for the simplest CRUD applications it works fine. But once you build pages with more than one set of data to act on or something similar you're screwed. Super irritating.

This assumption also points out one of the other irritating struts features: passing "the" ActionForm to the execute() method. What's the point? You need to cast it to your own form class anyway, and if you're going to do that you might as well fetch it from somewhere else (e.g., being able to associate multiple ActionForm objects to an action by name). And one of the main reasons for tying the actions to the action forms was to take advantage of object pooling, which has very little benefit on modern JVMs anyway. (Martin Fowler has a doc on this somewhere, filing under the many other premature optimization practices people follow...)

So the lesson: don't tie yourself so closely to implementation details that don't hold all the time. Doing so with the servlet request/response is generally ok, but the ActionForm? Blech.

Regarding the session properties: if it becomes a problem I think you can create a session listener (or something like that) and wipe out old action form objects from the session as necessary. Probably more work than it's worth tho....