I have been doing Tapestry 5 work for about a year now, and I’m definitely still learning, but I think I know my way around fairly well. I really (mostly) like it, and I think it is way easier to use than Tapestry 4, as well as many other frameworks. It also results in a nice clean code base which isn’t too difficult to approach. There are, however, a couple of areas that I really just find confusing. Some of them aren’t too bad once you get to know them, but they are hard to learn. I think it is important for most aspects of the framework to be easy to learn/use, because if people encounter pain during their initial impression stage, they will abandon the framework and use something else.
The first issue I have is with the way that the Select component works when you want to have a dynamic model for the list. I think this is a common requirement for applications, so it is something people will most likely encounter fairly quickly. For complex models, it is usually necessary to implement two interfaces: SelectModel and ValueEncoder. The interfaces make sense once you get to know them, but I think the learning curve is quite steep for such a common task. I’m not sure how this could be solved, but it seems like Tapestry 4 may have had a more simple system (though I’m sure it had some problems which led to it being redone).
The second issue I have is with page context. Often times in standalone web applications, I have created pages which take query string parameters. These can be referenced by external apps or pages, and used to link between pages of an app. Tapestry’s equivalent is the page context, which can be used to pass contextual data between pages. There are two problems that I’ve encountered with page context. First, it is limited in what data it can represent. It is generally just a list of nameless parameters. This makes it difficult to pass only certain parameters or parameters with names. Second, the format for the URL is not a part of the spec (correct me if I’m wrong), so it can only reliably be used via other Tapestry pages. This makes it difficult to pass data in to a Tapestry page from an external place.
So to sum it up, I’d like to reiterate that I really do like Tapestry 5 and hope for its widespread adoption, but it has a few points that are difficult to deal with. If these issues were addressed in a future version, I think it would help ease a new developer’s adoption of the framework.
I got really sick of Firefox hogging all of the memory on my laptop (it has 4 gigs), and I thought it would be fun to drive my coworkers nuts by reporting bugs specific to an exotic browser, so I started checking them out the other day. I started with Amaya because I remember it being really crappy back in like ’98. Unfortunately it still is. So, I tried Opera and it is actually pretty nice. The interface is a little ugly, but it seems to be way faster than Firefox. It also has this cool speed dial thing that comes up whenever you open a new tab that shows you all of your favorite web sites, and it shows them as pictures, which I think is really cool. So far it is pretty much able to keep up with FF on ajaxy web sites, although I have noticed a few issues with facebook. It also works with this web site I use that has a complicated Java applet. Pretty cool.
My new group at ASU is loosely standardizing on Tapestry, so I’ve been spending some time learning it. We are officially using 4.1, I think, since it’s the latest official release, but I decided to go all rogue style and switch to 5.0 after spending some time on 4.1. From the noise on the web, it sounds like Tapestry gets completely rewritten for every new version, so 5.0 is pretty different from 4.1. Anyway, it seems much better, but there are still some weird problems. Here are some of the interesting things I’ve run into:
- If you need to call some Tapestry page from an outside app with data, you can simulate Tapestry’s “activation/passivation” by building URL strings which will feed your onActivate method. They look like this: http://localhost:8080/app/page/param1/param2, where param1 and param2 will be passed in a List (not an array, as I found out the hard way) to onActivate. I’m not sure if this is the best way to do it.
- If you loop through a list of items and want to be able to edit those items (like by having a checkbox), you pretty much need to set up a PrimaryKeyEncoder, otherwise it will serialize/deserialize stuff and all your changes will be lost. This was very hard to figure out.
So far I’m only moderately impressed. There seem to be too many assumptions that don’t fit the model of my first app very well, but we’ll see how it goes once I get better at it.
So, I am trying to jump into Sakai development by writing a tool that can keep a log of email conversations between instructors and students. Since I’m new to Sakai, I will probably end up starting over a few times before I figure out the best way to develop. I decided, at the advice of a coworker to start using RSF and the App Builder plugin. So far, it’s pretty intimidating. I started by doing a full CRUD framework, since that is one of the options for the plugin. I think digesting RSF and the way they set up their Hibernate stuff at the same time is a bit much, so I’ve gone backwards to starting with their hello world app, which I’m going to try to convert into a number guessing game to give me a handle on session management, RSF, etc. It seems like there is a pretty serious lack of any tutorials that go beyond modifying the hello world to say something different. The whole video tutorial thing is pretty cool, so maybe I’ll make one if I get far enough along. But for now, I can recommend starting with hello world if you don’t know RSF already. I can also say that RSF looks pretty nice so far. Much simpler than JSF but some of the same good ideas.