Archive for February, 2006

New Wicket downloads available!

Monday, February 27th, 2006

Finally I’ve finished the transformation from the Wicket build to maven 2, though it took the worst parts of my sunday to do so for almost all projects in our core projects. This means that for the first time, we have official builds for the following projects (still development builds):

(the full listing for this snapshot release)

As you can see: a lot of new projects. Please try them out, so we can enter the beta phase of our release calendar soon!
These are still development releases, take care when you try them out!

PS. When the transitive dependencies work in maven 2, they are very helpful!

Maven 2 rant

Sunday, February 26th, 2006

I’m a big fan of maven, but now that I am trying to move the build of Wicket to Maven 2, I’m in a big world of hurt.

First of all, my customized website generation stopped working, because they wanted to move to APT. Now that is excusable, as the custom Jelly script I created for doing this is a lot more magic than the velocity template I now can use. But the stylesheet I have crafted stopped working correctly with some of the automatic generated pages. And I can’t supply my own templates for some of the reports they have. The current dependency report is much too basic in my opinion and I’d rather change it: it takes too much horizontal space.

The assembly plugin is quite promising, as long as you keep to the maven standards. I am able to create a nice packaged source+bin zip file, using the assembly descriptor. This works pretty well, until you want to do the same for a WAR file where you only want to add the direct dependencies instead of /all/ transitive dependencies:

-rw-r--r--   1 martijn  martijn   165119 Feb 12 22:20 commons-collections-2.1.jar
-rw-r--r--   1 martijn  martijn   169763 Feb 12 22:23 commons-lang-2.0.jar
-rw-r--r--   1 martijn  martijn    38015 Jan 29 13:33 commons-logging-1.0.4.jar
-rw-r--r--   1 martijn  martijn   313898 Feb 12 22:27 dom4j-1.6.1.jar
-rw-r--r--   1 martijn  martijn   411014 Feb 12 22:28 httpunit-1.6.jar
-rw-r--r--   1 martijn  martijn  2450757 Feb 12 22:35 icu4j-2.6.1.jar
-rw-r--r--   1 martijn  martijn   181664 Feb 12 22:29 jasper-compiler-4.1.30.jar
-rw-r--r--   1 martijn  martijn    72406 Feb 12 22:34 jasper-runtime-4.1.30.jar
-rw-r--r--   1 martijn  martijn   231706 Feb 12 22:28 jaxen-1.1-beta-8.jar
-rw-r--r--   1 martijn  martijn    30479 Feb 12 22:28 jaxme-api-0.3.jar
-rw-r--r--   1 martijn  martijn   153253 Feb 12 22:29 jdom-1.0.jar
-rw-r--r--   1 martijn  martijn   699081 Feb 12 22:28 js-1.6R1.jar
-rw-r--r--   1 martijn  martijn   137835 Feb 12 22:35 jtidy-4aug2000r7-dev.jar
-rw-r--r--   1 martijn  martijn   121070 Jan 29 13:38 junit-3.8.1.jar
-rw-r--r--   1 martijn  martijn    36572 Feb 12 22:34 jwebunit-1.2.jar
-rw-r--r--   1 martijn  martijn   358085 Feb  9 22:21 log4j-1.2.12.jar
-rw-r--r--   1 martijn  martijn   105672 Feb 12 22:30 nekohtml-0.9.5.jar
-rw-r--r--   1 martijn  martijn   575351 Feb 12 22:31 org.mortbay.jetty-4.2.24.jar
-rw-r--r--   1 martijn  martijn   105883 Feb 12 22:29 pull-parser-2.jar
-rw-r--r--   1 martijn  martijn    19097 Feb 12 22:29 relaxngDatatype-20030807.jar
-rw-r--r--   1 martijn  martijn    77977 Jan 29 13:33 servlet-api-2.3.jar
-rw-r--r--   1 martijn  martijn    25863 Feb 12 22:30 stax-api-1.0.jar
-rw-r--r--   1 martijn  martijn    38025 Feb 12 22:28 tagsoup-0.9.7.jar
-rw-r--r--   1 martijn  martijn   929053 Feb 26 09:52 wicket-1.2-beta1.jar
-rw-r--r--   1 martijn  martijn   274677 Feb 26 09:53 wicket-extensions-1.2-beta1.jar
-rw-r--r--   1 martijn  martijn  3149655 Feb 12 22:37 xalan-2.6.0.jar
-rw-r--r--   1 martijn  martijn   895924 Feb 12 22:32 xerces-2.4.0.jar
-rw-r--r--   1 martijn  martijn  1010675 Feb 12 22:33 xercesImpl-2.6.2.jar
-rw-r--r--   1 martijn  martijn   109318 Feb 12 22:29 xml-apis-1.0.b2.jar
-rw-r--r--   1 martijn  martijn   124724 Feb 12 22:34 xmlParserAPIs-2.6.2.jar
-rw-r--r--   1 martijn  martijn   104102 Feb 12 22:30 xom-1.0b3.jar
-rw-r--r--   1 martijn  martijn    93395 Feb 12 22:29 xpp3-1.1.3.3.jar
-rw-r--r--   1 martijn  martijn   246365 Feb 12 22:34 xsdlib-20030807.jar

How many xml dependencies can you discover here?

The old way of annotating a dependency to be included in your WAR archive was much easier than the soup I’m in now. I have to tag all my dependencies as compile scope, and then exclude the ones I don’t need.

I know it is hard for projects to write documentation when you have so much coding to do. Heck, even Wicket is a victim of the too many programmers, too few writers syndrome. I have a lot of respect for what the maven guys have accomplished in documenting so far, but it is still too scattered, too little and confusing. The user mailinglist of maven is such high traffic, my google mail can’t even keep up.

In the very least make sure the documentation doesn’t contain errors. I had a blast figuring out why the changes plugin (now part of codehaus, instead of the default maven distro?) didn’t want to execute. Turns out that the documentation tells you to add a dependency on the SNAPSHOT version of the plugin, instead of the final (i.e. BETA) version of the plugin. Fortunately I have about 100000 user mailinglist messages in my google mail account, so googling on the error showed a message from several weeks ago that the SNAPSHOT string had to be removed.

Even the pom.xml hasn’t been documented properly, and this is the most fundamental artifact of a maven project. I see a lot of concepts there that don’t have an explanation anywhere. execution, modules?

The maven team has created a bohemoth to maintain, and I pity them for that. There was a lot of work to be done, but I think the move to maven 2 was too soon and too drastic. The complexity they have added to a build system may be necessary but then I think very good and complete documentation is also necessary.

Wicket group at Frappr

Sunday, February 19th, 2006

I just created a Frappr group for the Wicket project. Feel free to add yourself to the group if you feel connected to the Wicket community.

The best thing I like about a Frappr map is to see how diverse the community is of Wicket. I know that we have quite a following in the far east, and it would be nice to see the dots on the world map and discover the global diversity of our community.

Currently there is only one member (myself), but I hope to see the group growing quickly! Join me, it is lonely out there!

var frappr_mapheight = 300;
var frappr_mapwidth = 500;
var frappr_maplat = 52.2501255;
var frappr_maplon = 6.2266935;
var frappr_mapzoom = 15;
var frappr_host = “http://www.frappr.com/”;var gid = 594439;

Eclipse BIRT

Wednesday, February 15th, 2006

Currently I’m figuring out whether the BIRT is a gift from heaven, or a one way trip to hell. At the moment, I think the roadsigns lead me into hell, instead of the start of the rainbow.

My first pet peeves:

  • the dataset editor is a modal dialog. This inhibits looking at your mappings in your Java classes, hibernate mapping files, etc. Why couldn’t this be just an editor window in the usual Eclipse style of editing?
  • dragging columns in the dataset editor is no help at all. It prefixes the schema name, table name and column name on the place where the cursor is in the editor window. It doesn’t add a from clause, nor does it have any intelligence on foreign key relationships.
  • the scripted dataprovider/dataset is a drag in working with Java, when you have a coding problem, it only shows up when previewing, and it doesn’t provide you with a sensible error message: “The value of the property ‘keyExpr’ is required”. I tried looking for this property in the xml definition of a valid report, but couldn’t find one. How am I supposed to know where and how to set this?
  • you can only see the report working when you copy your classes into the report viewer plugin’s web directory. Why isn’t it possible to have it use the classpath of your current project, giving it the full capabilities of hotswap?
  • In order to have the previewer pick up changes in my Java code, I had to restart my workspace every time
  • It is very easy to have it take 100% of CPU and make your machine come down to a crawl, making you kill the Eclipse process. This problem did go away with an update of the EMF/GEF feature through the update manager.

As you can see, I am not enthousiastic about the BIRT offering. It sure doesn’t feel like a 2.0 release, more like a 0.1 development snapshot.

Wicket goodie: Hibernate Versioned Form

Monday, February 13th, 2006

Last week I had the pleasure to add optimistic locking to our web application, using automatic versioning in Hibernate. What we want is to detect a stale object when a form is submitted and displaying the new representation from the database, overriding the submitted data.

So when two people open an edit form for the same contact, and the first to submit renames the contact from ‘Foo’ to ‘Bar’, the database will be updated, changing the name from ‘Foo’ to ‘Bar’. When the second user tries to save the contact, changing the name from ‘Foo’ (that was the last information he got) to ‘John’, we want to show him that the data has been changed by someone else, and show him the new information, disregarding his change to ‘John’.

Now, how would you do this for all your forms in your application without resorting to the usual hidden field option? Wicket has allowed me to do such a thing without much trouble. Here’s a short description.

public class VersionedForm extends Form {
    private Long version;

    public VersionedForm(String id, IModel model) {
        super(id, model);
        version = getVersion();
    }

    protected void validate() {
        Long newVersion = getVersion();

        if(!newVersion.equals(version)) {
            // new method in 1.2
            clearInput();

            // detaches the model of the page, and evicts the
            // object from the hibernate session
           ((MyPage) getPage()).reloadModel();

           // copy the new version onto the form
           version = newVersion;
           error("Someone else modified the object already, try again");
        } else {
           // do the default form processing.
           super.validate();
        }
    }
    private Long getVersion() {
        // get the version of the model object
        // either through reflection or just a cast to your base object
        return ((MyBaseObject)getModelObject()).getVersion();
    }
}

Here you see three important steps:

1. set the current version in the constructor
2. check the version in the validate() method
3. reload the object when it is not valid, and clear the user input

Retrieving the version can be implemented using reflection, searching for the @version annotation, or by implementing a custom interface IVersioned, or something to your liking.

The reloading of the object and evicting it from the Hibernate session is something we implement at the page level, as we always put the object that is edited into the page model.

The best part is that in any edit page we have, we now just have to subclass our forms from VersionedForm, and we have instant optimistic locking.