Tuesday, December 28, 2010

Is it time to switch back to IntelliJ?

I've been trying to stick with Eclipse now for a while. I switched from IntelliJ 8 to Eclipse because IntelliJ stopped working for Tapestry (I still don't know why) and because my fingers were getting tied in knots switching between IntelliJ and Eclipse. I have to switch back and forth because my Tapestry training uses Eclipse and I got a lot of negative feedback the times I tried to get people to use IntelliJ as part of the training.

In any case, I've been gritting my teeth against the travesty that is Eclipse; the inconsistent behaviors, the needless complexity, the lack of sense in much of the UI. I often wonder what IDE the Eclipse developers use, because it couldn't possibly be Eclipse itself, or they would have fixed some of the more brain-damaged stuff years ago.

One thing that is currently killing me is that Eclipse has no concept that some source folders contain production code and some contain test code. Because of that, when I collect coverage, EMMA instruments the test code as well as the production code. That not only throws off coverage figures, but breaks some of my tests (advanced ones about bytecode manipulation, that are sensitive to when EMMA adds new fields or methods to existing classes).

Fortunately, EMMA has an option to restrict its instrumentation (though it a global preference, and not configurable for individual projects) ... but shouldn't Eclipse understand this distinction natively? IntelliJ does, and it helps prevent a lot of problems, not just with coding, but with testing as well.

I keep hoping that there's a better, faster, simpler solution out there ... something that is elegant and precise. Eclipse is dumb as a sackful of hammers, and IntelliJ is almost fractal in its complexity, and ugly to boot.

I haven't found my perfect IDE yet. Maybe it's NetBeans?

Thursday, December 16, 2010

Announcing Tapestry 5.2

I'm very proud to announce that the next major release of Tapestry, release 5.2, is now available as Tapestry version 5.2.4.

This is the first stable release of Tapestry since 5.1.0.5 (back in April 2009), which is far too long a cycle. You might wonder: what's been the holdup? The answer, for myself personally, is that I've been using Tapestry on two very, very different applications for two very, very different clients and I've been updating Tapestry to embrace the real world concerns of both of them. At the same time, I've done about a dozen public and private Tapestry training sessions and gathered reams of input from my students.

Let's talk about some of the major enhancements in this release:

Removal of Page Pooling

Prior versions of Tapestry used a page pool; for each page, Tapestry would track multiple instances of the page, binding one page instance to a particular request. This was an important part of Tapestry's appeal ... all the issues related to multi-threading were taken over by the framework, and you could code your pages and components as simple POJOs, without worrying about the threading issues caused by running inside a servlet container.

Unfortunately pages are big: it's not just one object but instead the root of a large tree of objects: components and templates, bindings for component parameters, component resources, and all the extra infrastructure (lists and maps and such) to tie it together. Some of the largest Tapestry projects have hit memory problems when they combined deeply componentized pages with large numbers of parallel threads.

Tapestry 5.2 rewrites the rules here; only a single page tree is now needed for each page; the page and component classes have an extra transformation step that moves per-request data out of the objects themselves and into a per-thread Map object. Now, any number of requests can operate at the same time, without requiring additional page instances. Even better, the old page pooling mechanism included some locking and blocking that also gets jettisoned in the new approach. It's just a big win all around.

Live Service Reloading

People love the ability to change page and component classes in a Tapestry application and see the changes immediately; prior to 5.2 the same people would be disappointed that they couldn't change their services and see changes just as immediately. Tapestry 5.2 eliminates that restriction in most cases.

This is super handy for services such as DAOs (data access objects) where it is now possible to tweak a Hibernate query and see the results as immediately as changing some content in a template. This is another Tapestry feature that you'll find you can't live without once you use it the first time!

ClassTransformation API Improvements

At the heart of Tapestry is the Class Transformation API; the extensible pipeline that is the basis for how Tapestry transforms simple POJOs into working components. Prior to 5.2, if you wanted to do any interesting transformations, you had to master the Javassist psuedo-Java language.

Tapestry 5.2 reworks the API; it is now possible to do all kinds of interesting transformations in strict Java code; Javassist has been walled off, with an eventual goal to eliminate it entirely.

Query Parameter Support

Tapestry traditionally has stored information in the HTTP request path. For example, a URL might be /viewaccount/12345; the viewaccount part of the URL is the name of a page, and the 12345 part is the ID of an Account object. Tapestry calls the latter part the page activation context (which can contain one or more values).

That works well when the a page has a fixed set of values for the page activation context, but not so well when the values may vary. For instance, you may be doing a search and want to store optional query parameters to identify the query term or the page number.

Tapestry 5.2 adds the @ActivationRequestParameter annotation that automates the process of gathering such data, encoding into URLs as query parameters, and making it available in subsequent requests.

Testing

A lot of work has gone into Tapestry's testing support, especially the base classes that support integration testing using Selenium. The new base classes make it easy to write test cases that work independently, or as part of a larger test, automatically starting and stopping Selenium and Jetty as appropriate. Further, Tapestry expands on Selenium's failure behavior, so that failures result in a capture of the page contents as both HTML and a PNG image file. It is simply much faster and much easier to write real, useful tests for Tapestry.

JSR-303 Support

Tapestry now supports the Bean Validation JSR, converting the standard validation annotations into client-side and server-side validations.

Documentation

Tapestry's documentation has always been a challenge; for Tapestry 5.2 we've been doing a massive rework; doing a better job of getting you started using Tapestry; it's still a work in progress, but since it's based on a live Confluence wiki (and no longer tied to the release process) the documentation is free to quickly evolve.

Better yet, you don't have to be a committer to write documentation ... just sign your Apache Contributor License Agreement.

And in terms of exhaustive guides ... Igor Drobiazko's book is being translated from German to English as Tapestry 5 In Action.

Summary

I'm very proud of what we've accomplished over the last 18 months; we've added new committers, new documentation, and lots of new features. We even have a fancy new logo, and a new motto: Code Less, Deliver More.

Tapestry 5 was designed so that it would be possible to make big improvements to the internals and add new features to the framework without impacting existing users and applications; Tapestry 5.2 has validated that design and philosophy. It delivers a lot of punch in a non-disruptive way.

So, if you are looking for a high-productivity, high-performance web framework that doesn't get in your way, it's a great time to take a closer look at Tapestry!