From looking around at the documentation I cannot figure out a way to do this. The example in this case is that Apache Commons just released Commons Logging 1.1, which is meant to be a backwards compatible maintenance release. I'd like to upgrade the pom that Stripes is inserted into IBiblio with to allow (but not require) commons logging version 1.1, while requiring at least version 1.0.4. But I can't find a way to do it and am left wondering if it's even possible.

If this isn't possible, how do folks resolve the situation where you are using one library that depends on version 1.x of something, and another that depends on version 1.y of something? Does maven already handle this internally, and promote to the more recent version? Do you end up with both in your classpath (yikes - I'd hope not).

I should not that I'm not really a big maven user - I don't even use it to build Stripes, so it's not easy to test this kind of thing out. I just assemble a pom.xml so that Stripes can be uploaded to IBiblio, and other people can grab it with maven.

When I read how, when using EJB3/Hibernate annotations, you only needed to annotate execptions to some basic rules, I thought "wow, finally...that's a great idea". Well, turns out I was wrong!

The way things are setup is that if you have any methods that begin with get, then according to the spec those are persistent properties and will by default be persisted as Basic properties. Now, never mind that any rich-type properties should probably be defaulted to ManyToOne properties...

I'm now coming to the realization that this strategy works really well if you have an anemic domain model. But our domain model is anthing but anemic. Probably over half of the get() methods on our classes compute derived values, or chain through other objects to find the result. So now I find that I have to go and annotate all these other methods with @Transient. Oh well, it's not a huge deal, but it does take some of the shine off.

I guess it's time to go look and see if there's a way to invert the behaviour at a class level so you can have the default be transient for a given class. And before anyone suggests it - yet the methods do need to begin with get because we want to be able to use them as read-only bean properties in all sorts of places.

How, one might ask, does Stripes, a framework that leverages generics, annotations, var-args etc. come to run on JDK 1.4? Have I lost my mind and cut out all the advanced features that leverage these constructs? Is the JDK 1.4 incarnation of Stripes some shadow of the real thing? Well, actually, no.

A new document on the Stripes Website details the process of taking the stripes distribution and using Retrotranslator to make Stripes and your application compatible with a Java 1.4 VM. It's really startling easy - from downloading Retrotranslator to having an assembled war file to run under Java 1.4 took me about 15 minutes.

There are, of course, a couple of minor issues. Retrotranslator doesn't support 100% of the changes between Java 1.4 and Java 5. A couple of very minor changes have been made in Stripes to work around these gaps (specically s/ThreadLocal.remove()/ThreadLocal.set(null)/). The changes are in HEAD in subversion, but are not yet in a public release. So if you're dying to try this out you have to build Stripes from subversion. But give it a couple of weeks and the next official release will include all necessary changes.

I found this quote in the comment section of another blog:

The problem with most frameworks is that most super-hero
programmers are good at all the memory tasks it takes to
program but that makes them tolerant of over-complexity
because they can follow it. They also tend towards
arrogance, not wanting to read other people's documentation
and instead re-inventing the wheel. Being a super-hero
programmer, enjoying reading and writing documentation and
loathing complexity are the three qualities one needs to
build a framework.

I think that's an excellent sumation of why most frameworks sucks, and what it takes to develop a solid framework. Original blog and comments can be found here:

http://jroller.com/page/idealog?entry=sacred_code

For anyone who hasn't heard of it, Gmane is an excellent, free service that archives mailing lists and makes then available in a variety of formats. It even has a mechanism to allow un-subscribed users to post to the list (at the list administrator's discretion of course).

Over the last couple of weeks the Stripes Users and Stripes Development lists have been subscribed to Gmane, and the list archives imported. This means that anyone can:

  • Search the mailing lists through a usable interface
  • Browse and read the mailing list in a threaded web interface
  • "Subscribe" to RSS feeds of the mailing lists
  • Browse and read the mailing lists through any NNTP news reader - and post too!

Links and details are available here. Thanks to the good folks at Gmane, especially Lars Magne Ingebrigtsen.

Stripes 1.3.1 was released over the weekend. It contains fixes for several minor bugs found in the 1.3 release. The full list of bugs fixed is available in the JIRA Changelog. The release is fully backwards compatible and a safe upgrade for all 1.3 users. Download here.

I've been spending a lot of time over the last few months thinking about the fact that good software hides complexity from it's users until they are ready for it. I've talked about this in various contexts, but I've been missing something. Then it dawned on me the other day - what I'm describing is simply a flat learning curve.

Mostly I think about this from a developer's perspective. As a consumer of other libraries/toolkits/frameworks/server products, how usable is a particular thing? The answer is that if it's open source, it's probably terrible. Take a look at the graphic below.

The majority of open source software targetted at developers follows a kind of inverted-s learning curve. The four labelled stages can be described as:

  • 1: Struggling to understand the many concepts presented all at once when learning a new toolkit. Having been thrown into the thick of things without good documentation you waste countless hours/days until suddenly you see how all the pieces fit together.
  • 2: The plateau of basic proficiency. Basic tasks can be accomplished without terrible productivity loss. Confidence increases.
  • 3: Attempts to use advanced features or tackle corner cases highlight inconsistencies and lots of tiresome trial and error testing might lead to a solution. This phase is often repeated many times!
  • 4: All the major quirks, defeciencies and workarounds have been learned. The practitioner is now reasonably productive.

This is, I believe, how the more experienced developers in the community live through the adoption of the average OSS library or framework (and some non-OSS software too). More junior developers may never make it out of stage one or two, but simply look to more experienced teammates for solutions.

I'm not going to cite examples; I think most of you are able to think of plenty without my help. In some cases it's the complexity of the domain that leads to a steep learning curve (e.g. O/R mapping) and in these cases even the most talented developers cannot make things as simple as we'd like. But in the majority of cases I believe it comes down to developers who don't understand usability (of software; most developers don't understand end-user interface usability either, but that's another story).

All sorts of things can lead to poor usability and a troubling learning curve. A few examples:

  • Multiple or overly verbose configuration files
  • Forcing the developer to learn additional languages (expression, query, template languages) just to get started
  • Having to implement workarounds for common use cases
  • Poorly designed and poorly-generalized APIs
  • Scant, bad, out of date or factually incorrect documentation
  • High dependency count

"Good" software uses a number of techniques so that both a seasoned veteran and a junior developer can be happy and productive. In many cases these amount to the inversion of the above examples. But by far and away the biggest gain comes from an incremental introduction to complexity. By constructing well designed interfaces, using sensible defaults and providing good quality documentation it is possible for developers new to a tool to become productive quickly, and continue to get more productive as they use the software. The end result is a flat learning curve (like the blue line in the graphic).

In conclusion: well designed software can offer more features in a package that appears simpler to the consumer, and make said consumer many times more productive.

Stripes 1.3 has been released. Stripes is a action-oriented web framework that's intuitive, powerful and even well documented!

Notably this is the first release of Stripes to be distributed under the Apache License (version 2). Previous releases will continue to be available under the LGPL. Thanks to everyone who chimed in with advice on making the license switch.

Major changes in the 1.3 release include:
  • Expression Based Validation: Validations can now be written in the JSP Expression Language (EL). The expression is specified in an annotation along with other validations. E.g. @Validate(expression="this != 5") private long notFive;
  • Flexible Validation Methods: ActionBeans can now have more than one custom validation method, and additional control can be asserted over when the validation is run (by event, by error state etc.). You no longer have to implement an interface, just decorate your validaiton method with @ValidationMethod
  • Validation Filtering By Event: It is now possible to fine tune validations by specifying that a field is required only for a particular event or events, or is required for all events except specified events. A couple of examples: @Validate(require=true) (required always), @Validate(required=true,on={"save","update"}) (required on two specific events), @Validate(required=true,on="!delete") (required on all events except delete)
  • Interceptor System: Stripes now includes a generic Interceptor system. The request processing lifecycle is defined by an enumeration, and it is possible to interceptor around any/all lifecycle stages easily. An example interceptor ships with Stripes that enables before/after methods within ActionBeans.
  • Exception Handling System: A new ExceptionHandler interface is used to handle any unhandled exceptions raised anywhere in the application. The primary benefit of this system is to be able to execute arbitrary java code on exceptions instead of simply rendering a view.
  • URL Alternatives: It is now possible to specify fully qualified class names or provide Class objects almost anywhere the system expects a URL. While not everyone will like this it provides significant flexibility to change URL strategies without impacting other classes and views.

The announcement and full list of chances is available on the official website. The release can be downloaded here.

Being able to create new EL functions for access in JSP EL is pretty useful. With the new JSTL tags and the EL it's often more fitting to provide functionality as an EL function than as a custom tag. As an example, someone on the Stripes list asked for an easy way to determine if a field has errors (they wanted to add some style to a container around the field, not just the field itself). You can do this already using EL, but it's a bit on the noisy side:
<div class="input ${empty(actionBean.context.validationErrors['someField']) ? '' : 'error'}">
  <stripes:label for="someField"/>
  <stripes:text name="someField" id="someField"/>
</div>
Yikes! Of course if you tend to have this fragment frequently you could wrap it up in a tagfile or a layout component, but you still end up having the big ugly EL expression in there. So I started thinking, wouldn't it be nicer to be able to write:
<div class="input ${stripes:hasErrors('someField') ? '' : 'error'}">
  <stripes:label for="someField"/>
  <stripes:text name="someField" id="someField"/>
</div>
With a function like that you could use it in EL ternaries like above, in c:if/c:when tags etc. The only problem is that EL functions have to be public static functions, and don't have any built in way to access any useful state information, like the PageContext, Request, Response etc. This seems like quite an oversight to me, because it means that as an EL Function author I either have to require the PageContext or Request to be passed in, e.g.
${stripes:hasErrors(pageContext, 'someField')}
and that that just feels plain awkward, or provide myself with access in some other way. Since my functions will ship as part of Stripes, a web framework, I have the opportunity to grab the request/response and put them somewhere functions can access them later, but that won't work for everyone. This seems like a fairly obvious omission to me. I've looked at the spec, hoping beyond hope, to find a paragraphs that says something like "if a parameter is of type '../../page/javax.servlet.js', 'javax.servlet.ServletRequest' or 'javax.servlet.ServletResponse' it should not be exposed to the JSP author, but will be supplied by the container at invocation". No such luck. An even better approach (IMHO) would have been to provide an interface like:
public interface ELFunctor {
    void init() throws JspException;
    void release() throws JspException;
    void setPageContext() throws JspException;
}
Doing something like this would have allowed the use of non-static methods, on objects that could cache expensive objects, and given the objects a well defined lifecycle and access to the page and request information. Oh well.
Looks like it's official this time. Different suitor, same dance. You can find the news on the JBoss Homepage, and in the Red Hat Press Release. It'll be interesting to see why this is a "good thing(tm)" for both sides, other than the usual expected "synergy".

The first beta of Stripes 1.3 has been released. This release includes some fairly major improvements:

  1. The ability to attach validations to specific events within an action
  2. The ability to write validations using EL expressions
  3. A new Interceptor system to allow injection of behaviour into the request processing flow
  4. New @Before and @After annotations to specify methods to be run before and after events
  5. Ability to use class names or class objects almost everywhere URLs are used

As well as lots of smaller improvements and bug fixes. The full list can be found on the Stripes Roadmap in JIRA.

It should be noted that this is a beta release and as such:

  1. The documentation website is not yet up to date (though javadoc and taglib doc is)
  2. The sample applications have not been updated to take advantage of new features
  3. The release has not undergone wide-spread testing and will contain bugs

All of this will be rectified during the beta period, which is expected to last 1-2 weeks. The release can be downloaded from SourceForge here:

  1. http://sourceforge.net/project/showfiles.php?group_id=145476

It seems like every time I read or hear about Seam Gavin is going on about how most web applications don't support multi-tasking and how Seam kicks ass because it does. What this boils down to is the fact that Seam doesn't go chucking everything in session, so you can pop open a second window and have two windows in the same session that don't clobber each other.

But I have to say, I really don't like the way Seam manages this. Having tackled this problem many times, it's easy to see the solution Seam went with. Frankly it's not new, and I personally don't think it's the best solution. Effectively Seam traps the beginning of a new "conversation" and stores state for it in a scope that is walled off from other conversations. I worked on a framework that implemented this in 1999. We called it "Chapter Scope" because it usually covered a bunch of pages (get it?), and we eventually decided it wasn't the way to go. In both cases a conversation/chapter id needs to get passed back and forth in every request and the framework needs to be able to figure out when a new conversation begins.

The problem I have with this is that while it is multi-window safe, it's also overly restrictive. Example: try doing the following at both amazon.com and the Seam DVD store demo:

  1. Open the homepage
  2. Search for something (anything)
  3. Shift/Cmd click on the next-page link to open a new window
  4. In the original window enter something new in the search box
  5. Page around in both windows

This, or course works seamlessly at amazon. But on the Seam DVD store demo you get bounced back to the homepage when you try to open the next page of search results in a new window. Why? Because the next-page link uses JavaScript to ensure that you don't open it in a new window. And it does that because then it would get confused because you'd have two windows open in the same conversation and things would go just as whacky as if you were storing things in session.

So basically Seam allows multi-window operation, but you can only fork windows in certain ways because Seam has to be able to figure out when a new conversation starts. This doesn't seem like the free-wheeling multi-tasking web that Gavin likes to talk about.

Compare this to the approach I've been using for years, and is now codified in the wizard support in Stripes. It may not look as shiny or have as many big words around it, but it's the same solution that amazon uses and it covers all the bases. You write hidden fields into each page containing the input (or necessary state) from the prior interaction; enough to tell the server what the right thing to do is. This way you can open up a new window anywhere, and the state gets "copied" by virtue of the way the browser works, and if the state changes in one window it doesn't affect any of the others. This can be a pain to do manually, but Stripes will do all this for you. So not only can you multi-task in an application built on Stripes, you can do it in more places than one build on Seam!

I've been starting to rethink the license for Stripes. When I first released it, LGPL seemed like a reasonable license to me. But recently I had an experience which is making me question that decision.

Specifically I came across a tool I'd like to use, that is licensed under the regular GPL. It's a filter that does some nice things for a web application. To use it I'd have to download a jar and configure it in my web.xml. Now, I wouldn't be extending the class, nor would I even be linking with it. I'd just be using it in my Servlet container. But on the other hand, my application would start to rely on it, and would cease to function should it be removed.

My interpretation of the GPL here is that it's fine to use it, and it would not imply I would have to release my application code. Just as if I chose to deploy my application on linux, I'm using the software, but not extending or modifying it. However from reading the website and mailing list archive for said piece of software the author offers "commerial licenses", which would seem to contradict my take.

My point in all this is simply that it's confusing and I'm spending way too much time worrying about the license instead of using the software! Folks "who know better" know that the LGPL is a more permissive license. But I'm starting to wonder if other people have a similar reaction to the LGPL that I had to the GPL in this instance. Or simply see the letters GPL in the license and run the other way.

In short, the 1.3 release of Stripes is coming up quite soon and I'm considering changing the license to an apache or BSD style license. Do you think that the license for a framework like Stripes is important? Do you think this would be a good/bad move?

I frequently hear the sentiment that JSP isn't all it's cracked up to be, and that alternatives like Freemarker, and to a lesser degree nowadays Velocity, are "better". Now I know that back in the dark days of JSP 1.x it wasn't a wonderful environment. But with JSP 2.0, the built in expression language etc., it's really come a long way and is now a relatively sane view technology IMHO.

I read up a little bit on Freemarker this weekend to see what I was missing. First impression was great. It's a single jar (no dependencies anywhere), which makes it trivial to download and start using. Hooray. Secondly, and this is big, there is a way to make JSP taglibs work as Freemarker macros. So if I'm interested in supporting Stripes+Freemarker I shouldn't have to perform a major reworking of the stripes tags just to provide support for both environments.

I also ran into a couple of problems trying to port the Stripes sample application to Freemarker. It boiled down to two things before I gave up for now. One: freemarker doesn't allow hyphens in tag names, and Stripes uses hypens in some tags. Two: freemarker doesn't seem to like the way the Stripes layout tags include other templates. I found a workaround for the first, and could probably do the same for the second if I spent some time.

But I'm not yet sure I see the major advantage of Freemarker as a view technology for the web. It's sure handy for generating dynamic emails, offline documents etc. but what are it's killer features for web development? I'm particularly un-enamored of the fact that the syntax doesn't produce validatable markup, so without an IDE plugin I've been making a lot more template errors!

So here's the million dollar question: would you be more likely to adopt Stripes if it had support for Freemarker or another template system other than JSP? If it's a significant barrier to adoption I'd be happy to spend some time either making Stripes more Freemarker friendly or vice versa (assuming I can).

Our group at work has recently decided to adopt Stripes as our web framework of choice, and to migrate away from Struts. We're not going to be converting our applications wholesale, but will be converting pieces in a "if you need to fix/add/modify something, convert it first" approach. When we hit some threshold, we'll probably spend a day or two converting everything else.

What's interesting is how this came about. The group I work in is about 15 developers strong. We develop and maintain LIMS (Laboratory Information Management Systems) for three different genotyping platforms and a DNA resequencing platform. We also maintain systems for centralized project management and biological sample tracking across these platforms. These are not your average simple UI in front of a single database ;)

A few months ago a new system started development. The goal: to manage sample registration, qc and tracking across the institute. I work at one of the "big three" sequencing centers in the US, and this new platform is a Big Freakin Deal(tm). The developer in charge knew he didn't want to spend his days using Struts and started looking for a different framework. I gave him an overview of Stripes , he played with it a big and decided to give it a shot. Said developer and his teammate have been exceedingly happy with Stripes. I've gotten very few requests for help (maybe 4-5 over the whole development cycle which is amazing considering I sit right down the hall), and have been told on numerous occasions things like "Stripes does make doing AJAX stuff pretty easy" :)

I actually contract at the institute, and as such am employed more as a "high powered developer" than in any kind of leadership roll. So, about a month ago my team lead comes back from the leads' meeting and announces "we've decided to move the whole group to Stripes". Giggity giggity, ohhh-riiiight! I had nothing to do with the decision, which is what makes it so sweet.

In the last couple of weeks we've starting moving our team of four which manages the resequencing platform over to Stripes. The team are constantly surprised at how much easier development is in Stripes and what it can do for them. We've refactored several pages and actions over now and are operating in hybrid mode with no problems. And we're kicking out new functionality much quicker. Work just got a whole lot more fun!