20050929 Thursday September 29, 2005

The Seven Stages of SOA Asceticism

If there is one severe risk in the SOA space, then it is probably the chance that people expect SOA to be a free ride. They assume that your architecture will transmogrify into a Service Oriented Architecture, as long as they have the right middelware and tools.

That, of course, sounds too good to be true. And it isn't. SOA doesn't come for free. SOA does not automatically fit into the existing architectures, and getting it right requires dedication and a contemplating lifestyle in which you refrain from some of the worldly pleasures introduced to the Software Development community in the past.

(Uh, well, I'm not sure there are exactly 7 stages of course - there are probably more - but 7 just sounded right.)

1. Refrain From I in ACID

If you have been working in a distributed object computing world, then you probably already know the meaning of the ACID acronym; it means Atomic, Consistent, Isolated, Durable. Those are the properties of the transacation model that most of us have gotten used to in the past. In database terms, it effectively means you can't screw up your database consistency if you have multiple clients trying to access the database at the same time.

The cool thing about these kind of transactions is that you basically don't have to do a lot to get this working. In fact, it is the de facto standard in the RDBMS world. And it's the standard in J2EE environments. So even if you didn't know the acronym, then - my friend - you have have been doing it without being aware of it.

So my first message to all of you is that you should get used to refrain from it. You wonder why? Well, the problem is "I". (What do you know; I'm starting to sound more like a guru with every line.) I don't mean you, I mean "I", not me.

In a SOA world, a business process might take some time to complete. And "some time" can be anything between a couple of seconds between a couple of weeks or more. Even if you would rely on some kind of optimistic locking mechanism, then you would still need the explicit consent of all services participating in the transaction. And during this time, all of your data sources would need to be locked in order to guarantee "Isolation" semantics.

The Isolation property of ACID transactions guarantees that the transation does not affect or is affected by other transactions. This basically implies locking the resources involved for a short period, but you can't do that if the short period expands to a couple of minutes or more. It would effectively lock up your data source forever.

Another problem is the transaction manager. If you decide to open up your services to the outer world, then there must be something coordinating the transactions between your services and your client's services. In the end, you want a consistent state in all of your databases, right? The question is: which transaction manager. Your customer probably doesn't trust yours and you don't trust your customer's. There is no third party out there on the Internet that you could trust. (Not entirely true in all cases, but let's keep things simple.)

So how do we compensate for missing ACID semantics? It may sound silly, but the answer is: with compensation. It means designing your services in such a way that you can always "roll back" manually. The archetypical example is compensation in a flight booking business process. If I book a flight, then the seat will be reserved for me. But if I don't confirm the reservation in time, then the flight booking system will simply "undo" the reservation. It didn't have a transaction that spanned the entire time that I needed to figure out if I wanted to fly or not. It simply defined a "compensating" message allowing them to get rid of my reservation.

WS-BPEL recognizes the need for compensation scenarios and has it built into the language.


( Sep 29 2005, 01:40:13 PM CEST ) Permalink Comments [1]
20050927 Tuesday September 27, 2005

Big Freaking Numbers III

Remember that I talked about the different flavors of ExpressionBuilders in project BigNumbers a while ago? At this stage, there are two of them. One implementation turns the String expression into an Expression implementation that is interpreted for every evaluation. The other implementation took a different (and pretty fancy) approach by compiling the String expression into a full-fledged Java class on the fly.

Today, I did a benchmark to see which one would be more performant. The results are slightly dissapointing. I was kind of hoping that the JIT-compiling version of the ExpressionBuilder would outperform the other one, but it doesn't. *sigh* I expected the interpreter to outperform the other ExpressionBuilder in case of ad-hoc expressions, so I wasn't too surprised when that turned out to be true. However, the JIT-compiling version of the ExpressionBuilder only starts to outperform the interpreter version after 3000-4000 evaluations. And then only by microseconds.


( Sep 27 2005, 03:15:42 PM CEST ) Permalink Comments [2]

BigNumbers -> Maven Beta 2

I just moved project BigNumbers to Maven 2 Beta 1. There are a couple of things that you can expect to occur during the next few weeks:

  • A couple of tests to verify the performance of the different Expression implementations.
  • A refactored project structure that needs to be a little bit more friendly for CVS.
  • A better interpreter. (One that the stuff used by the JIT compiling implementation.)
  • A better parser. (One that doesn't choke on "4 -a".)
  • Power function support.
  • A new release.
( Sep 27 2005, 12:51:21 AM CEST ) Permalink Comments [0]
20050926 Monday September 26, 2005

Maven 2 Gone Beta

It's hard to admit, but Gero Vermaas had to bring to my attention that Maven 2 has gone beta. During the last few months, I've probably been hitting the Maven 2 site a couple of hundred times a day, just to find out about it's latest status. And then, when I least expected it, it arrives...

Let's find out if the wagon-ftp FTP support has been fixed. (And the dreaded bug that prevented me from uploading a project site from Maven 2 using SCP.)

( Sep 26 2005, 08:38:43 PM CEST ) Permalink Comments [0]
20050924 Saturday September 24, 2005

Mixed Integer Programming

After I retrieved the sources of the piece of software that I've been blogging about during the last couple of days, I'm now also able to give away the Mixed Integer Programming models behind it. Explaining it all in detail would cause this entry to grow beyond a couple of pages, so I will stick to some examples.

Let's start with the tiles presented in the first figure. This case, Jummikub already generated an optimal solution, assuming that we want to maximize the number of tiles in the final solution. The next figure shows Jummikub's solution in case we're maximizing the total value of all tiles in the solution.

In the first case, the MIP model generated looks like this:

max: -d_red_01 -d_red_02 -d_red_03 -d_red_04 -d_red_05 -d_red_06 -d_red_07 -d_red_08 -d_red_09 -d_red_10 -d_red_11 -d_red_12 -d_red_13 -d_black_01 -d_black_02 -d_black_03 -d_black_04 -d_black_05 -d_black_06 -d_black_07 -d_black_08 -d_black_09 -d_black_10 -d_black_11 -d_black_12 -d_black_13 -d_yellow_01 -d_yellow_02 -d_yellow_03 -d_yellow_04 -d_yellow_05 -d_yellow_06 -d_yellow_07 -d_yellow_08 -d_yellow_09 -d_yellow_10 -d_yellow_11 -d_yellow_12 -d_yellow_13 -d_blue_01 -d_blue_02 -d_blue_03 -d_blue_04 -d_blue_05 -d_blue_06 -d_blue_07 -d_blue_08 -d_blue_09 -d_blue_10 -d_blue_11 -d_blue_12 -d_blue_13 +c_red_01 +c_red_02 +c_red_03 +c_red_04 +c_red_05 +c_red_06 +c_red_07 +c_red_08 +c_red_09 +c_red_10 +c_red_11 +c_red_12 +c_red_13 +c_black_01 +c_black_02 +c_black_03 +c_black_04 +c_black_05 +c_black_06 +c_black_07 +c_black_08 +c_black_09 +c_black_10 +c_black_11 +c_black_12 +c_black_13 +c_yellow_01 +c_yellow_02 +c_yellow_03 +c_yellow_04 +c_yellow_05 +c_yellow_06 +c_yellow_07 +c_yellow_08 +c_yellow_09 +c_yellow_10 +c_yellow_11 +c_yellow_12 +c_yellow_13 +c_blue_01 +c_blue_02 +c_blue_03 +c_blue_04 +c_blue_05 +c_blue_06 +c_blue_07 +c_blue_08 +c_blue_09 +c_blue_10 +c_blue_11 +c_blue_12 +c_blue_13;
r_1 -a_red_01 +a_red_02 > -0.0
r_2 -a_red_01 +a_red_03 > -0.0
r_3 -a_red_01 +a_red_02 > -0.0
r_4 -2.0 b_red_01 +b_black_01 +b_yellow_01 +b_blue_01 > -0.0
r_5 +a_red_01 +b_red_01 -d_red_01 -c_red_01 = 0.0
r_6 +c_red_01 < 0.0
r_7 -a_red_02 +a_red_03 > -0.0
r_8 +a_red_01 -a_red_02 +a_red_04 > -0.0
r_9 +a_red_01 -a_red_02 +a_red_03 > -0.0
...

Again, I don't have the time to explain it all in detail, but the thing to take away from this is that the number of available tiles of a certain type influences the factors and RHS's of the constraints (as far as I recall), and the strategy determines the function to optimize, which becomes pretty clear if you look at the different strategies offered in Jummikub:

The first strategy (maximizing the number of tiles in the solution, the solution in the first figure) is represented by the following goal function:

max: -d_red_01 -d_red_02 -d_red_03 -d_red_04 -d_red_05 -d_red_06
-d_red_07 -d_red_08 -d_red_09 -d_red_10 -d_red_11 -d_red_12 -d_red_13
-d_black_01 -d_black_02 -d_black_03 -d_black_04 -d_black_05
-d_black_06 -d_black_07 -d_black_08 -d_black_09 -d_black_10
-d_black_11 -d_black_12 -d_black_13 -d_yellow_01 -d_yellow_02
-d_yellow_03 -d_yellow_04 -d_yellow_05 -d_yellow_06 -d_yellow_07
-d_yellow_08 -d_yellow_09 -d_yellow_10 -d_yellow_11 -d_yellow_12
-d_yellow_13 -d_blue_01 -d_blue_02 -d_blue_03 -d_blue_04 -d_blue_05
-d_blue_06 -d_blue_07 -d_blue_08 -d_blue_09 -d_blue_10 -d_blue_11
-d_blue_12 -d_blue_13 +c_red_01 +c_red_02 +c_red_03 +c_red_04
+c_red_05 +c_red_06 +c_red_07 +c_red_08 +c_red_09 +c_red_10 +c_red_11
+c_red_12 +c_red_13 +c_black_01 +c_black_02 +c_black_03 +c_black_04
+c_black_05 +c_black_06 +c_black_07 +c_black_08 +c_black_09
+c_black_10 +c_black_11 +c_black_12 +c_black_13 +c_yellow_01
+c_yellow_02 +c_yellow_03 +c_yellow_04 +c_yellow_05 +c_yellow_06
+c_yellow_07 +c_yellow_08 +c_yellow_09 +c_yellow_10 +c_yellow_11
+c_yellow_12 +c_yellow_13 +c_blue_01 +c_blue_02 +c_blue_03 +c_blue_04
+c_blue_05 +c_blue_06 +c_blue_07 +c_blue_08 +c_blue_09 +c_blue_10
+c_blue_11 +c_blue_12 +c_blue_13;

The other strategy (maximizing the total value of tiles in the solution, the solution in the second figure) is represented by the following goal function:

max:
+c_red_012.0c_red_023.0c_red_034.0c_red_045.0c_red_056.0c_red_067.0c_red_078.0c_red_089.0c_red_0910.0c_red_1011.0c_red_1112.0c_red_1213.0c_red_13
+c_black_012.0c_black_023.0c_black_034.0c_black_045.0c_black_056.0c_black_067.0c_black_078.0c_black_089.0c_black_0910.0c_black_1011.0c_black_1112.0c_black_1213.0c_black_13
+c_yellow_012.0c_yellow_023.0c_yellow_034.0c_yellow_045.0c_yellow_056.0c_yellow_067.0c_yellow_078.0c_yellow_089.0c_yellow_0910.0c_yellow_1011.0c_yellow_1112.0c_yellow_1213.0c_yellow_13
+c_blue_012.0c_blue_023.0c_blue_034.0c_blue_045.0c_blue_056.0c_blue_067.0c_blue_078.0c_blue_089.0c_blue_0910.0c_blue_1011.0c_blue_1112.0c_blue_1213.0c_blue_13;

Hmmm, the second goal looks a little odd. I think this is a bug in the printing functionality of the LP solver that I'm using. Anyway, it's clear that there is a difference, right?

You can download the LP files here (first LP model) and here (second LP model).

( Sep 24 2005, 06:06:29 PM CEST ) Permalink Comments [1]

Found it!

Remember that I said I lost the sources of a project that I had been working on forever? Well.... I retrieved the sources this morning. I don't know if it is the latest version of the project, but the archive seems to date back from somewhere in 2004, and I can't remember having worked on it since a couple of years ago. So that sounds good, right?

It seems this version is still running, so I will make some modifications in order to print out the Mixed Integer Programming model. Sit tight...

( Sep 24 2005, 11:04:31 AM CEST ) Permalink Comments [0]
20050921 Wednesday September 21, 2005

Jummikub

In the spirit of this company I decided that I would do some more sharing. This time, it is about a project for which I think I no longer have the sources: my home CVS server crashed, and I can't find a backup. (The good thing about that is that it also saves me from a couple embarrassing moments when you would take the opportunity to look at the code.:^0

The live demo is running here.

History

This project started when I was about 15. I'm aware of the fact that it sounds a little pathetic (...), but at that time I was obsessed by the fact that it should be possible to have an algorithmic solution for Rummikub problems. I remember locking myself in my room for the entire afternoon, working on it from different angles and trying to get my MSX computer to come up with a solution. But I couldn't figure it out.

Until a couple of years later. I was doing an internship at the University, and working on a class of problems that we tried to solve using mixed integer programming techniques. I remember that - on a sunny autumn afternoon - I sat in the basement of the building, and it suddenly hit me that I could use the same technique to solve my Rummikub case. Eureka! That night, I wrote the mathematical model down on a piece of paper, with the intent to turn it into a piece of software somewhere soon.

It never a happened. During the years that followed, I repeatedly lost and retrieved this piece of paper, but never found the time to work on it. Six years later, when I returned from my holiday, I finally decided that I would give it a try and program it in Java. Four years have now gone by after I deployed the bits to my server at http://www.agilejava.com/rummikub/.

What does it do?

If you know Rummikub, then you know that it is basically just a combinatorial problem. There are 106 tiles, in which every tile combines a certain number (1-13) with a certain color (red,blue,black,yellow). These tiles must be combined in color sets or number sequences. And the general goal is to - well - get rid of your own tiles as fast as possible. You can reshuffle the entire collection of sets and sequences produced by others to get rid of your own, and there are also a couple of Jokers that can be a substitute for any tile you need.

The picture above shows you the opening screen of the webapp. It's just a table, allowing you to select the number of tiles that you want to be part of the solution. Apart from that, it allows you to choose between two possible strategies (this is up to your preferences). If you hit the only button on this screen, it will try to combine the choosen tiles into the optimal collection of sets and sequences, as you can see below.

If you change the parameters, for example by adding two jokers, then the solution is completely different, as you can see below.

How does it work?

I already alluded to the fact that this has something to do with mixed integer programming, so - well, that's basically how it works. I will see if I can dig up the mathematical model somewhere and post that here as well. But basically, every request coming from the first screen will be turned into MIP model. The servlet will then pass this model to a Java based MIP solver (downloaded from sourceforge). The solver returns the optimal solution, and the servlet translates this optimal solution back to a series of sets and sequences.

Where can I get it?

You can download the war file here.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.

( Sep 21 2005, 08:13:40 AM CEST ) Permalink Comments [0]
20050919 Monday September 19, 2005

Xalan Text Extension

Just added another example to the Xalan Text Extension that I recovered this weekend. I rememembered that I wanted to use this tool for generating script as well (make sure that the comments are formatted correctly), but I never actually gave it a try. It appears that I needed another feature, so I decided to add that, while I was at it. (You can download the latest version of this tool here.

This is an example showing how it works. The file below is an XML vocabulary to specify a launcher for your Java program. It's actually based on a subset of a DTD that I used in the past to generate Windows .cmd and Unix .sh scripts. The main difference is that this one is extremely simplified; in fact, it doesn't serve any purpose at all, since it assumes that all of the required jars are in the CLASSPATH environment variable. (Duh.)

<?xml version="1.0"?>
<!DOCTYPE launcher [

<!ELEMENT launcher (description?, copyright?, mainClass)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT copyright (year+, holder)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT holder (#PCDATA)>

]>
<launcher>
  <description>This is just an example of a script file, to show how
    the Xalan text extensions might help you to generate script from
    XML; not that generating script is very hard with XSLT, but it can
    be tricky to make sure that it looks acceptable. So we don't want
    to use comment lines of more than 75 characters. Let's see if we
    can somehow accomplish that.</description>
  <copyright>
    <year>2005</year>
    <holder>Wilfred Springer</holder>
  </copyright>
  <mainClass>com.agilejava.foobar.main</mainClass>
</launcher>

Anyhow, the real question is how we can convert this into a script, that looks as if it was written by hand. The XSLT isn't really that hard, but formatting the comments can be tricky. However, with the Xalan Text Extensions it becomes pretty easy:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xalan="http://xml.apache.org/xalan"
  xmlns:text="xalan://com.agilejava.xalan.text.TextExtension"
  extension-element-prefixes="text"
  version="1.0">

  <xalan:component prefix="text"
                   elements="indented">
    <xalan:script lang="javaclass" 
                  src="xalan://com.agilejava.xalan.text.TextExtension"/>
  </xalan:component>
  
  <xsl:output method="text"/>
  
  <xsl:template match="/">
    <text:format break-after="true">#!/bin/sh</text:format>
    <xsl:call-template name="newline"/>
    <xsl:apply-templates select="launcher"/>
  </xsl:template>

  <xsl:template match="launcher">
    <text:format break-after="true" prefix="# " cols="75">
      <xsl:value-of select="normalize-space(description)"/>
    </text:format>
    <xsl:call-template name="newline"/>
    <text:format prefix="# " break-after="true">
      <xsl:apply-templates select="copyright"/>
    </text:format>
    <xsl:call-template name="newline"/>
    <xsl:text>"$JAVA_HOME"/bin/java </xsl:text>
    <xsl:value-of select="mainClass"/>
    <xsl:call-template name="newline"/>
  </xsl:template>

  <xsl:template match="copyright">
    <xsl:text>Copyright (C) </xsl:text>
    <xsl:for-each select="year">
      <xsl:if test="not(position()=1)">
        <xsl:text>, </xsl:text>
      </xsl:if>
      <xsl:value-of select="text()"/>
    </xsl:for-each>
    <xsl:text> </xsl:text>
    <xsl:value-of select="holder"/>
  </xsl:template>

  <xsl:template name="newline">
    <xsl:text>
</xsl:text>
  </xsl:template>
  
</xsl:stylesheet>

If we would apply this template to the file above, then the output would look like this:

#!/bin/sh
 
# This is just an example of a script file, to show how the Xalan text
# extensions might help you to generate script from XML; not that
# generating script is very hard with XSLT, but it can be tricky to make
# sure that it looks acceptable. So we don't want to use comment lines of
# more than 75 characters. Let's see if we can somehow accomplish that.
 
# Copyright (C) 2005 Wilfred Springer
 
"$JAVA_HOME"/bin/java com.agilejava.foobar.main

Note that - in order to have wordwrap for the description - there wasn't actually much I needed to do: I simply generated a text:format element, and added the output of the XPath normalize-space(description) expression as a child. The text:format tag element translates its content into a formatted block of text, making sure that the line length does not exceed 75 characters, and prefixing it with "# ".

<text:format break-after="true" prefix="# " cols="75">
  <xsl:value-of select="normalize-space(description)"/>
</text:format>


( Sep 19 2005, 02:52:21 PM CEST ) Permalink Comments [0]
20050917 Saturday September 17, 2005

More on Annotations in JSF

During the last few days, the JSF community seems to be collectively turning its eyes towards annotations. Duncan Mill blogged about it as a response to Ed Burns' blog and a discussion on TheServerSide.

The whole idea of adopting annotations in JSF definitely makes a lot of sense. First of all, annotations and wide addoption of IoC/dependency injection came about at approximately the same time. JSF has always supported the idea of IoC and dependency injection to some extent, and Shale takes it even further by adding support for Spring. It seems only logical that it would only be a matter of time until the JSF community would turn their eye towards the other software trend that crossed the chasm. Apart from that, almost all of the latest JEE specs are considering annotations, so why would JSF be any different?

An application of annotations in JSF that hasn't been mentioned yet is using annotations to configure validators and converters for backing bean attributes. I would love to have that, and it probably wouldn't be hard to do at all. Simply define a couple of annotations that map to the standard validators and converters, add them to your backing bean and rely on JSF to tie all of the relevant objects together at runtime. It would certainly ease development of the JSP pages. Apart from that, it seems like better object oriented design to keep the knowledge about the meaning of attributes with the object, instead of embedding it in the presentation components layered on top of that.

( Sep 17 2005, 04:12:45 PM CEST ) Permalink Comments [1]

Cleaning Up the Attic

Once in a while, I all of a sudden run into projects that I haven't touched for ages. Today I had such an experience. While thinking about a way to pretty print DTDs using XSLT, I realized that it would be impossible to have word-wrapped comments without either using some very complicated XSLT constructions, or a dedicated XSLT extension. EXSLT doesn't really provide anything that I can use out of the box, and apart from that, EXSLT is not entirely implemented in Xalan.

When I thought about a solution, I suddenly realized that - more than a year ago - I had been working for half a day on something that might come in handy now. If stuff is hanging around on your hard disk for over a year without ever being touched, then it's definitely ready to be either open sourced or to be moved to /dev/nul. I decided to go for the former option, so I quickly added some LGPL references and Copyright statements and uploaded it to the Web, just a minute ago.

Just see for yourself if it comes in handy. I of course do not accept any responsibility whatsoever for any damage this tool does to your products or customers. (I would however be curious to find out what it is :^)

You can dowload a binary version of the Xalan extension here. I will package the sources in a day or something. (It's just one source file, so it can't be that hard...)

CC-GNU LGPL
This software is licensed under the CC-GNU LGPL. ( Sep 17 2005, 03:22:59 PM CEST ) Permalink Comments [0]
20050915 Thursday September 15, 2005

Building Shale JavaOne Demo

If you have read my recent blog entries, then you will probably have begun to see pattern in each of these entries. I have been devoting my precious time to building early Shale products. (Mabye that's a little sad. I suppose it is. Let's try to find some bigger theme next week. I've heard rumours about the "Java World Peace" JSR. I think I will work on that next week.)

Today is not going to be any different. Yesterday I blogged about the use cases web application found in the Shale source code repository. Today, I'm going to build the other Shale demo that has been around for a while: this is the demo used by David Geary and Craig McLanahan at JavaOne.

The original source code of the demo can be downloaded from www.jsfcentral.com. Unfortunately, it doesn't come with a prebuild war file, but the intent of this blog entry is to change that.

What did we just download?

The jar file that is provided by jsfcentral.com contains all of the sources and an Apache Ant build.xml file. Unfortunately it doesn't ship all of the required libraries, so if you really want to build the demo using Ant, then you should 1) download a lot of stuff manually and 2) modify a hurendous number of properties. Does that sound boring? In that case, you may want to choose to use Maven instead. (In fact, I don't leave you much of a choice. The remainder of this page assumes that you prefer to go the Maven way as well.)

The Way of the Maven

The demo obviously doesn't come with all of the different Maven files, but I composed a zip file that you can unzip in the root directory of the unzipped demo jar. After unzipping it, you can move into the "Shale Demo" directory, and build the war file like this:

maven [-Dmaven.proxy.port=... -Dmaven.proxy.host=...] clean war

I didn't actually bother to find out if there would be a way to deploy the war file automatically. I think the build script has something on board, but since you will probably run the application on Jakarta Tomcat 5.*, you can also copy it in the $CATALINA_HOME/webapps directory. You can download the complete WAR file here.

What Did Just Happen?

Basically, if you would have done it yourself, then you would have run into a couple of things that you would have to solve yourself. Let's find out what they are:

Dependencies

First of all, you would have been required to resolve all of the dependencies. In this case, all of the dependencies have been explicitly listed in the project.xml file. The only exception to this rule is the tiles-core.jar file, residing in the lib/ directory. Although that file is listed as a dependency in the project.xml file, it's location is overridden in the project.properties file. If you ever feel the need to build it to a more recent version of Tiles, then this is the thing you should be aware of.

Make War

The next problem is to recreate the war in Maven. You don't really need to know this, but it might be interesting to know a little more if you feel like adding a couple of new files to the war. In that case, you should check out maven.xml. This file contains a postGoal war:webapp, copying all of the files that could not be pinpointed by the war plugin to the relevant build directory. (This includes almost all of the static resources, since the directory structure of the demo war is quite different than the Maven project model.)

Shale Dependencies

Since Maven is trying to dig up the jar file on which the project depends automatically, it will also try to resolve some Shale specific libraries. These libraries do not yet exist in the Maven ibiblio directory. The easy way out is to build the Shale libraries yourself as well. (Return to one of my previous blog entries to figure out how.)

MyFaces vs. JSF RI

This one is particularly tricky. You can use the JSF RI application to build the demo application, but you can't use the RI to run the application. (Huh?!) If you would use the JSR RI, then you would find out immediately that the sample application is trying to access a variable called users that it cannot find. The trouble is that the sample application is using the Shale Spring enhancements and tries to load the bean from the bean definition in applicationContext.xml. In this case, the JSF RI breaks its own specification, causing the DelegatingVariableResolver to fail. As a result, the JSF implementation simply reverts to the default configuration mechanisms (faces-config.xml) and this file does not define a bean called users.

Find Bug

If you have done all of the above, everything seems just fine. That is, it displays the page that I expected. Aparently, this is applications exists with the sole purpose to create users. So let's give it a try. The application takes me to a number of screens without any problems. Just when you thing that everything is fine, and hit the "Finish" button to complete the registration sequence, it fails with an exception...

java.lang.IllegalArgumentException: Position[dialogName=Create Account,stateName=Create User],outcome=finish
	org.apache.shale.dialog.faces.DialogNavigationHandler.transition(DialogNavigationHandler.java:484)
	org.apache.shale.dialog.faces.DialogNavigationHandler.action(DialogNavigationHandler.java:236)
	org.apache.shale.dialog.faces.DialogNavigationHandler.preprocess(DialogNavigationHandler.java:353)
	org.apache.shale.dialog.faces.DialogNavigationHandler.postprocess(DialogNavigationHandler.java:326)
	org.apache.shale.dialog.faces.DialogNavigationHandler.handleNavigation(DialogNavigationHandler.java:207)
	org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:84)

Looking at the source code, it appears that the application is running into problems when trying to find the next transition, based on the outcome of the processing the previous action. (Line 479).

479   Transition transition = state.findTransition(outcome);
480   if (transition == null) {
481       transition = state.getDialog().findTransition(outcome);
482   }
483   if (transition == null) {
484       throw new IllegalArgumentException
485         (status.peek().toString() + ",outcome=" + outcome);
486   }

So it can't find a transition for the incoming outcome value. That is, after completion of the accountPage.finish() method, it wants to go somewhere else. That's funny. If you look at the code of the dialog-config.xml file, there isn't any definition of a potential transition at all. And the "Create User" state has not been defined to be an endstate. As a result, Shale gets so confused that it falls apart.

...
<action name="Create User"
        method="#{accountPage.finish}">
</action>
...

The solution, (and really the only solution I could think of) is to add the transition. It appears that the accountPage.finish() operation returns "finish" in case of success. So the solution is to simply change the dialog-config.xml file as mentioned below. The zip file with Maven artifacts also contains a patched version of the dialog-config.xml file, that looks like this:

...
<action name="Create User"
        method="#{accountPage.finish}">
  <transition outcome="finish"
              target="Exit"/>
</action>
...
( Sep 15 2005, 03:42:25 PM CEST ) Permalink Comments [1]
20050914 Wednesday September 14, 2005

Running Shale Samples

Today, I set off to get a Shale sample up and running on my laptop. Shale sounds too good to be true, so I figured that I'd better find out if is real. A couple of weeks ago I had been working on building Shale from scratch. I may have missed it at that time, but it appears that there are now nightly builds available. So I decided to give it a go and look at a nightly build instead.

You may already have been aware of it, but Shale comes with a sample application, illustration most its features. This is the application that I'm going to install; it's called struts-shale-usecases.war.

In the good old hacker tradition, I decided to skip the readme (DRTFM) and - what the heck - deploy the war file included in the nightly build to a couple of J2EE servers.

Attempt 1: Sun Java System Application Server 8.1 Q2

Attempt 1, deploying it to a default installation of the Sun Java System Application Server 8.1 Q2. After deploying the war file trough the console, I enter http://localhost:8080/struts-shale-usecases/ in my browser. Nothing happens. The application server tells me that the application is not deployed. What the...?! Maybe I didn't have enough coffee this morning. Let's try that again..... Nope, it keeps telling me that it doesn't exist.

Let's look at the log files. Ah, there it is. There's a class that cannot be found:

java.lang.ClassNotFoundException: org.apache.shale.dialog.impl.DialogImpl
        at org.apache.commons.digester.Digester.createSAXException(Digester.java:2540)
        at org.apache.commons.digester.Digester.createSAXException(Digester.java:2566)
        at org.apache.commons.digester.Digester.startElement(Digester.java:1276)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:485)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:799)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:845)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1563)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:341)

Checking the struts-shale-usecases.war reveils that the class resides in shale-core.jar, so it does exist. Looks like a classloading problem, caused by commons-digester living somewhere else in the chain of classloaders. (And so it does: commons-digester appears to be part of appserv-rt.jar. Hmmmmmm.) Let's forget about this for a while, and try something else.

Attempt 2: Tomcat 4.1.30

That was a little disapointing. Maybe I should have read the readme. (Quickly skimming trough its content now. Nope it doesn't tell me anything about the support for SJAS8.1.) Let's try this again, but this time using Tomcat 4.1.30, which I also already had running on my system. Simply copy the war file into the webapps directory and type ./startup.sh. Typing http://localhost:8080/struts-shale-usecases/ in my browser, and - nothing, again. This time the server doesn't give me any clues at all. It just returns a blank page.

Searching the war file for some piece of content that I can try to retrieve directly - just to see if the application was actually deployed - reveils that there is a index.jsp file. So I go and type http://localhost:8080/struts-shale-usecases/index.jsp. Ah, that's better. A stack trace:

org.apache.jasper.JasperException: This absolute uri (http://java.sun.com/jsf/core) cannot be resolved in either web.xml or the jar files deployed with this application
	at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:105)
	at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:430)
	at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:154)
	at org.apache.jasper.compiler.TagLibraryInfoImpl.(TagLibraryInfoImpl.java:159)
	at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:354)
	at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:381)
	at org.apache.jasper.compiler.Parser.parseElements(Parser.java:795)
	at org.apache.jasper.compiler.Parser.parse(Parser.java:122)

Huh? Is this an XML parser problem? I takes me a while to realize that this is the reference to the tag library. It seems to resolve this URI into a tag library descriptor. Strange. On inspection, it appears that the tag libraries are not specified in the web.xml file. Maybe this has something to do with different fallback mechansisms in JSP 1.2 and JSP 2.0. The jsf-impl.jar file does contain a .tld file, but somehow the container doesn't pick it up, or fails to interpret it correctly.

Attempt 3: Tomcat 5.0.28

Assuming that all of the above had something to do with the version of the required versions of the Servlet/JSP spec, I'm moving to Tomcat 5.0, since it supports JSP 2.0. (Stubborn as I am, I'm still refusing to read the readme, but I'm tempted to. Instead I decided to take a look at http://struts.apache.org/shale/, to see if there's anything on deployment there, and yep, there is something in the Foundation section. It appears that you can deploy Shale in a JSP 1.2 Servlet 2.3 container, as long as you modify the deployment descriptors properly.

Being the lazy guy I am, I don't want to go down that path, so Tomcat 5.0 might be the alternative that works. And it works:

( Sep 14 2005, 01:29:49 PM CEST ) Permalink Comments [0]
20050905 Monday September 05, 2005

Strong Typing is for Programmers Who Like Refactoring

I somehow prefer this vision on strong typing in favor of the old dynamic language mantra "Strong Typing is for Programmers with Weak Memories", or "Strong Typing is for Wussies". This weekend I read "Programming Ruby". I like Ruby. It's simple. It seems to be pretty fast. It's objects all over the place. It feels like Smalltalk for Java programmers, in the sense that you don't have to deal with an image, like in Smalltalk. It's all plain text.

But I also remembered some conference sessions on dynamicly typed languages that I attended in the past. None of these sessions ever mentioned the fact that refactoring tools can be so much more powerful if the type is known before runtime. Renaming an operation in a large codebase would be practically impossible. Tracing the usage of a class would be equally hard.

( Sep 05 2005, 08:19:20 AM CEST ) Permalink Comments [1]
20050902 Friday September 02, 2005

Emacs + Xrefactory

This morning when I woke up, I realized that it was about time to get out of the closet and confess to the world that I'm an addicted Emacs user. I gotta say that I did use a couple of IDE's in the past few months, but really nothing gives me that same sense of being in control of the universe as when I use Emacs. Face it: Emacs is like Cocaine for programmers.

There used to be a time in the past when support for Java wasn't really that great. But over the past few years, I started to use a tool called Xrefactory. This is the only IDE for which I actually ever payed money. (If I remember well, it was about 30 bucks.) And it was worth every penny.

So I'm telling you this today because Emacs is - as we speak - indexing a source directory that simply broke every other IDE, and I know from experience that Xrefactory used to be able to deal with such large code bases. Apart from that, it's just good to know that whenever you feel like using Emacs in a software development project, take a look at Xrefactory.

( Sep 02 2005, 09:43:27 AM CEST ) Permalink Comments [0]