Filling in my No Fluff dance card

Today begins the fall session of the Northern Virginia Software Symposium put on by No Fluff Just Stuff (Jay Zimmerman and crew). That means I have to decide which one of the six concurrent sessions to attend in each time slot. That means I have to decide which of five sessions to miss during each time period.

Today has three time slots in the afternoon, followed by an after-dinner keynote by pragprog co-founder Andy Hunt. For the 1:15 p.m. session, I'd like to attend Stuart Halloway's "Ajax Architecture" session, Brian Goetz's "Java Performance Myths" session, and Venkat Subramaniam's "Open Source Tools for Agile Development" session. I'm not a web UI designer, but knowing the browser's asynchronous JavaScript abilities would help on a current project. We want to add dynamic page updates to an existing web application. The design of the server code I'm working on will be affected by what services the client needs. Brian Goetz's session promises to show how common Java idioms we use, thinking it helps the Java compiler optimize our code, actually make it harder for the JIT compiler to figure out how to optimize. Venkat Subramaniam will recommend open source tools he finds most useful to develop code and improve its quality. The open source world changes so fast, it would be good to get these tips from the good doctor.

See how hard Jay makes it to decide which session to attend? I'm leaning toward Stuart's Ajax session just because it's the area I know the least about. I'd like to know what cool features Ajax libraries Prototype and Scriptaculous provide.

Later in the afternoon, Venkat has sessions on test-driven design for Spring applications and working with rules engines. But these sessions conflict with sessions on how Acegi supports JavaScript for better user authentication interaction, and a session on Jini (the technology whose coolness keeps it alive despite being almost wholly ignored for years). Decisions, decisions.

I plan to blog more this weekend on the sessions I attend and what I learn.

java.util.concurrent backport to Java 1.4

When I blogged in September about using the Java threading classes introduced in Java 1.5, I didn't know a similar library was available in Java 1.4. It is, courtesy of the backport-util-concurrent package maintained by Dawid Kurzyniec at Emory University.

The package provides versions of most of the java.util.concurrent classes, but converted to Java 1.4. The key feature missing is the ability to use generics. For example, using Java 1.4, you can't define a Callable anonymous inner class using syntax like:
void showSearch(final String target) throws InterruptedException {
Future<String> future = executor.submit(new Callable<String>() {
public String call() { return; }
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
to specify the call method returns a string, as in the above code excerpted from the Java 1.5 API for the Future interface. And, of course, you can't define a Future of type string that would be returned from the ExecutorService's submit method, as shown above. Without generics, you're confined to returning Objects and casting them to the expected type. You don't get the compile-time validity checking provided by Java 1.5 generics, but most Java developers are used to using narrowing casts like this.

This backport of the concurrent package came in handy this week when I wanted to use its features on a project that had to run in Java 1.4. It seems a lot of code from Java 1.5 has been backported to earlier Java versions, like Java annotations. Thank you, Dawid and Emory, and thank you for releasing the code into the public domain so the code may be "may be freely reproduced, distributed, transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial."

UPDATE 7 hours later:

I should mention that some of the code for the backport, as well as much of Java 1.5's java.util.concurrent package, came from Doug Lea's util.concurrent package. I woke up this morning and realized I had neglected to mention where the initial ideas for the Java 1.5 concurrency classes came from. Professor Lea, from the State University of New York at Oswego, created most of the ideas and code behind the improved multi-threading techniques that made it into Java 1.5. He also is a co-author of Java Concurrency in Practice, which Stuart Halloway recommended in my September 27 blog as being a great source to learn the effective use of the Java 1.5 concurrency package (and thus the backported version).

The benefit of favoring the Emory University backport over Doug Lea's original code is that code using the backport allows a smooth transition to Java 1.5. The transition mostly would involve renaming your imports. The backport's class names and APIs are identical to what's in Java 1.5. Doug Lea favors using the Emory backport over his older util.concurrent package.

Replacing Tomcat’s ROOT index.jsp page

Apache Tomcat comes with a simple ROOT webapp that is nothing more than a precompiled index JSP page. The text of this JSP page warns users not to bother trying to edit this index.jsp page in the $CATALINA_HOME/webapps/ROOT directory. If you try, then reload the http://localhost:8080/ page, your changes won't be reflected because the index page was precompiled into a JAR file. Nowhere in the Tomcat HowTo page did I see a quick pointer to changing the contents of the index.jsp page so Tomcat beginners can experiment quickly with Tomcat and JSPs. The closest I could find was a How To that tells users they can write an index.html page and have that override the index.jsp page.

So here's my quick pointer instructions. For those of you familiar with Tomcat and servlets, you will see nothing new here. But for Tomcat and J2EE beginners, I hope I'll save you a few minutes digging through the ROOT webapp's configuration files if you want to start playing with JSPs soon after installing Tomcat 5.5.

How do I edit the default JSP home page loaded by Tomcat?

The contents of the default Tomcat home page comes from the ROOT webapp servlet called org.apache.jsp.index_jsp. The page that you see in $CATALINA_HOME/webapps/ROOT/index.jsp has been precompiled into a class file (org.apache.jsp.index_jsp.class) stored in a JAR file (catalina-root.jar) in the ROOT webapp's WEB-INF/lib directory. Because of this servlet, Tomcat will not look at the contents of the ROOT web application's index.jsp file if you change it.

The easiest way to change the contents of the index.jsp page is to remove this index_jsp servlet from the ROOT webapp. Once you remove the index_jsp servlet and restart Tomcat, Tomcat will see the index.jsp file in the ROOT directory and compile it on the fly into a class file. You now will be able to edit the ROOT/index.jsp file and have those changes take effect immediately by reloading the http://localhost:8080/ page.

To remove the index_jsp servlet, edit the ROOT web application's configuration file, $CATALINA_HOME/webapps/ROOT/WEB-INF/web.xml. Comment out the definition of the servlet and the servlet mapping, so that section of the file will look like this (changes in red):
<!-- JSPC servlet mappings start -->
<!-- Disabling the index_jsp servlet
<!-- JSPC servlet mappings end -->
Once you disable the index_jsp servlet and restart Tomcat, how does Tomcat know to compile the index.jsp page in the ROOT web app's directory? Easy. First, when you request the default page of a web application, Tomcat (like every servlet container) will look for a welcome file. The default welcome files are defined at the bottom of $CATALINA_HOME/conf/web.xml. This web.xml file acts as a global web.xml file used for all web applications installed in Tomcat. The default welcome file list includes index.jsp, which means Tomcat will try to load that file (if found) in order to display it. Second, the $CATALINA_HOME/conf/web.xml configuration file also defines a servlet called simply jsp. This section of the web.xml file:
<!-- The mapping for the JSP servlet -->
maps all *.jsp and *.jspx pages to the jsp servlet. The jsp servlet performs the work of compiling the source JSP file into a servlet and then executing the servlet. The JSP servlet, by default, will check the JSP source page every time it is requested to see if it was modified since the last time it was compiled. If the page changed within 4 seconds of the last time it was compiled, the servlet will recompile the source JSP page before running it. The behavior of the jsp servlet is quite configurable. You can see all its options defined in the $CATALINA_HOME/conf/web.xml configuration file.

I've added the above instructions to the Tomcat HowTo wiki in the hope it helps Tomcat newcomers find their way around the server.

Updated 2007-7-11:
  • Fixed typo in XML comment tag. Thank you Peter Fischer for pointing this out.
  • Note: Tomcat 6 simplified its ROOT webapp index page, so these instructions don't apply.

Concurrency the Java 1.5 way

I attended a talk tonight on Java concurrency presented by Stuart Halloway at the Northern Virginia JUG that provided a refresher on the java.util.concurrent package. Stuart is one of the founders of Relevance, author of Component Development for the Java Platform, a frequent speaker at technical symposiums, co-author of Rails for Java Developers, and a great technical speaker.

Stuart Halloway
Stuart Halloway
Stuart spent the first few minutes telling us why he now focuses more on Ruby and Rails than on Java. Paraphrasing the title of a Java book written by his Relevance partner Justin Gehtland and Bruce Tate, Stuart says, "We can go even 'betterer,' 'fasterer' and 'lighterer' with some other technologies" like Rails and the Streamlined framework. However, when multithreading and concurrency are needed, Java way outshines the current state of Ruby and Rails, he said.

When considering multi-threading in order to increase the speed of a process, it is important to consider whether the slowness is due to the application being suspended while waiting for an external resource (e.g. a database, user input, disk), or whether the process is suspended while waiting for free CPU cycles. If the process is waiting for an external resource, Stuart said, the language and the number of CPUs won't matter much. "Java, assembly language and PHP all wait at the same speed," he said.

Stuart's talk covered:
  • Threads
  • Tasks and scheduling
  • Locking
  • Concurrent collections
  • Alternatives to threads
The key point to remember about Java threads is they share code, data, resources, and heap storage. They contain their own instruction pointer and stack. Threading isn't often needed in server-side programming because components like EJBs and JEE container services abstract the multi-threading away from the developer. But threading is often needed when you need to:
  • Keep a user interface responsive (think Swing)
  • Take advantage of multiple processors in compute-heavy applications
  • Simplify code that would otherwise need to keep checking if other tasks need to be performed (implementing their own task-scheduling loop)
Before Java 1.5, the Java language used Thread objects as the main way to achieve concurrency. Developers would write a class that implements Runnable and pass an instance to a Thread. Two of the shortcomings of the Runnable interface is its single method, run, doesn't return anything and it isn't declared to throw an exception to indicate anything went wrong. "It's completely wrong," Stuart said.

Java 1.5 introduced higher-level classes to allow more abstraction away from Thread objects. It introduced the Callable interface, whose call method does return something and is declared to throw an Exception. Programmers write Callable classes and pass instances to one of the three ExecutorService classes obtained by the Executors Java factory, or perhaps from an external library. The ExecutorServices provided by the Executors factory provide single-theading execution, and execution by two types of thread pools, a cached, expandable thread pool or a fixed-size thread pool.

When you give a Callable to an ExecutorService, you get back a Future object containing the results of the Callable's execution. The result can be an object or an exception that will be thrown. Stuart demonstrated code that exercised the new threading objects and shows how to use them. The code and the slides from his presentation is available online.

The Need for Locking

You don't need locks if you're just telling separate tasks to run concurrently. You need locking code when multiple threads access the same data at the same time. Java provides lock support with the:
  • synchronized keyword and blocks
  • Java 1.5 Lock interface objects, which offer an improvement over a straight synchronized block because you can tell the code to give up its attempt to acquire a lock after a timeout period expires.
  • ReadWriteLock interface, which offers separate locks for whether the process needs to read data or alter the data.
If you want, you can tweak how the ReadWriteLock operates, such as defining whether readers or writers get lock priority.

Concurrent Collection Options

Strategies and the implications of using concurrent collections: strategy and implications:
  • Do nothing
    It's fast, simple, but not thread-safe
  • Fail-fast iterators (introduced in Java 1.2)
    Fast, not thread-safe. Misuse of concurrent access probably will cause a fast failure. Fail fast uses optimistic locking: It assume everyone can access a shared resource and uses clean-up code if something goes wrong with multi-threaded writes. Java collections implement the fail-fast strategy by using version numbers that iterators use to see whether the collection has changed.
  • Lock the entire collection
    Simple, slow, might be thread-safe (like Hashtable)
  • Lock partial collection
    Complex, maybe faster, maybe thread-safe.
  • Copy on write
    Fast read access, may read stale data. When you write to a collection, you get new copy, so your write can proceed. Iterators for reading threads point to older collection, so data can be stale.
  • Immutable
    Fast, simple, thread-safe, cannot change objects.
  • Application-controlled locking
    Difficult, allows any combination of the above strategies.
Java Collections Design Choices

Collections and strategies
  • Legacy (pre-Java 1.2): Lock entire collection
  • Collections (1.2) API: Lock none, fail-fast iterators
  • Synchronized wrappers (1.2): Lock entire collection
  • ConcurrentHashMap: Lock partial collection
    Uses "lock-striping" to allow uses of different buckets in a hash.
  • CopyOnWriteArrayList: Copy-on-write
    Very expensive if using big arrays that are written to regularly. Every write to the collection copies it again. Only advantageous if data is read-mostly.
  • String: immutable
Alternatives to Threads

Alternatives, pros and cons:
  • Container-managed threads: Simple. inflexible
    Like J2EE containers. You write applications as if you are the only user of the object. Scales well because most data in server side is in the database. The DB controls concurrency.
  • Non-blocking I/O: Do work when available. Con is it as complex as using threads
    For example, the java.nio (1.4) package. Pro: Do multiple operations and notify me when done. Con: As complicated as threads. Oriented around blocking waits. Tends to get ignored when you're coding on the server-side.
  • Use multiple processes: Pro: simple. Con: inflexible
    When you need to perform more work, start more processes.
  • Event-driven code: Con: as complex as threads
  • Do nothing: Pro: simple. Con: slow (but performance might not matter for the application)
    "Probably more time has been wasted by optimizing code that doesn't need to be optimized."
Stuart also discussed the double-checked locking Java anti-pattern and why it is a problem. Heck, the perils surrounding the use of double-checked locking in Java have been known since what, 1997, when I think Java Developer's Journal published an article on it. But I've seen wickedly smart developers insert this potentially evil anti-pattern into their code out of ignorance of the subtle problem. I'm glad Stuart mentioned it as a reminder.

For Java developers interested in learning more about programming using concurrency, Stuart recommended Java Concurrency in Practice by Brian Goetz. The book mixes academic rigor on threading with practical implications for Java developers, he said.

Stuart also will be in town Wednesday night to speak at the Northern Virginia Ruby User's Group. He'll be talking about the Streamlined framework for rapidly developing CRUD applications in Rails.

JNDI error with Roller weblogger on Fedora Core 5

While planning my upgrade from Roller 2.1 to 2.3, I ran into an unexpected snag in Tomcat 5.5 running on Fedora Core 5. After I installed Roller 2.3 on my Fedora server and upgraded my database, Tomcat couldn't seem to create the <Resource> for the JDBC datasource. My catalina.log file had this unrevealing (to me) error:
Sep 22, 2006 9:23:29 AM org.apache.catalina.core.NamingContextListener addResource
WARNING: Failed to register in JMX: javax.naming.NamingException: Cannot create resource instance
Sep 22, 2006 9:23:47 AM org.apache.catalina.core.StandardContext start
SEVERE: Error filterStart
Sep 22, 2006 9:23:47 AM org.apache.catalina.core.StandardContext start
SEVERE: Context [/roller] startup failed due to previous errors
Exception in thread "Thread-9" java.lang.NullPointerException
The "Error filterStart" message seems to be Tomcat telling me that it couldn't start one of Roller's servlet filters after WorkerThread threw the NPE. Nowhere was Tomcat telling me, however, what resource it was trying to add at the time.

The messages in the roller.log file showed more helpful information. Roller obviously couldn't pull the DataSource from JNDI using the naming context java:comp/env/jdbc/rollerdb:
INFO  2006-09-22 09:23:30,239 RollerConfig:<clinit> - successfully loaded default properties.
INFO  2006-09-22 09:23:30,293 RollerConfig:<clinit> - successfully loaded custom properties file from classpath
INFO  2006-09-22 09:23:30,297 RollerConfig:<clinit> - no custom properties file specified via jvm option
WARN  2006-09-22 09:23:30,347 RollerContext:upgradeDatabaseIfNeeded - Unable to access DataSource
javax.naming.NamingException: Cannot create resource instance
[stack trace]
[Hibernate logging statements]
INFO  2006-09-22 09:23:41,904 NamingHelper:getInitialContext - JNDI InitialContext properties:{}
FATAL 2006-09-22 09:23:41,914 DatasourceConnectionProvider:configure - Could not find datasource:
javax.naming.NamingException: Cannot create resource instance
[stack trace]
ERROR 2006-09-22 09:23:41,928 RollerFactory:setRoller - Error instantiating
[stack trace]
Caused by: org.apache.roller.RollerException
... 31 more
FATAL 2006-09-22 09:23:41,938 RollerFactory:setRoller - Failed to instantiate fallback roller impl
java.lang.Exception: Doh! Couldn't instantiate a roller class
Still, the log messages weren't pointing me to why the datasource wasn't getting registered. I checked and double-checked the spelling from my Tomcat roller.xml context file and couldn't find any typos or bad configuration settings:
My roller configuration seemed correct. My initial Google search didn't turn up a solution, and neither did my search of the Roller FAQs or the Apache roller-user mailing list. But I did notice that if I google the exact string, "WARNING: Failed to register in JMX: javax.naming.NamingException: Cannot create resource instance," from the Tomcat log, the two search returns both mentioned Fedora Core. My environment:

O/S: Fedora Core 5 (Linux kernel 2.6.17)
Server: Tomcat 5.5.15 (from FC5 "core" repository)
JVM: Sun's Java 1.5 (build 1.5.0_07-b03)
Database: MySQL 5.0.22 (from FC5 repository)

I thus shortened some of my search terms and added "Fedora Core 5" into the search, and came across this message from PKR Internet's task list for its "Taskjitsu" product that pointed right at the problem. According to that message, Tomcat 5.5 is built so the default datasource naming factory is org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory from the naming-factory-dbcp.jar JAR file. But the Fedora Core install package for Tomcat 5.5, tomcat5-5.5.15-1jpp_6fc, does not ship that JAR or its factory class in any other JAR file.

There are two ways to solve the problem. The first is to add a factory attribute to the Roller webapp's roller.xml context with a <Resource> element that defines the Jakarta commons DBCP BasicDataSourceFactory class:
The second way is to grab a copy of naming-factory-dbcp.jar from a binary distribution of Tomcat 5.5 and install it in Fedora Core's Tomcat common/lib directory (default /usr/share/tomcat5/common/lib). I don't know if one solution is preferable to the other. Both solutions work, and the latter solution probably will resolve the same issue for other web applications. However, it seems adding two JARs that might share some of the same classes could lead to future ClassCastExceptions if for some reason the order of the JARs change in a classpath search. This event doesn't seem likely, though, as long as Tomcat controls the search order for classes in common/lib. Comments appreciated on whether one solution is better than the other.

After I found these solutions, I was going to post it as an FYI to the roller-user mailing list. Before I did, I poked again through the list archives to see if someone else already mentioned it. Sure enough. I found this email from Conor P. Cahill, posted July 6, by searching for fedora. Conor's subject line was "MySQL Database connector problems," which is why I think I missed it on my first search.

His email detailed the problem and proposed adding the factory attribute to the <Resource> element.

Since I didn't find Conor's email on my first search for a solution, I thought I'd post the problem and solution here, with the log errors, in the hope it helps other Fedora Core users.

JWSDP naming conflict with wscompile

I got an obscure error message and stack trace from Sun's Java Web Service Developer Pack 1.6's wscompile tool. I tried to generate the server-side artifacts for a JSE web service using the following wscompile configuration file:
<configuration xmlns="">
Running wscompile from Ant with -verbose and -Xprintstacktrace would display the methods of the endpoint interface, then come up with an exception and stack trace.
[wscompile] command line: wscompile C:\apps\j2sdk1.4.2_08\jre\bin\java.exe -classpath ... -d generated\wscompile -features:rpcliteral -gen:server
-keep -model generated\wscompile\model.xml.gz -mapping generated\wscompile\event-mapping.xml
-s generated\wscompile -verbose -Xprintstacktrace wscompile-config.xml
[wscompile] [creating model: MyService]
[wscompile] [creating service: MyService]
[wscompile] [creating port:]
[wscompile] [creating operation: method1]
[wscompile] [creating operation: method2]
[wscompile] [creating operation: method3]
[wscompile] [creating operation: method4]
[wscompile] Naming conflict occurred: []
[wscompile] at com.sun.xml.rpc.processor.generator.nodes.TypeVisitor.preVisit(
[wscompile] at com.sun.xml.rpc.processor.model.ExtendedModelVisitor.visit(
[wscompile] at com.sun.xml.rpc.processor.generator.nodes.JavaWsdlMappingNode.write(
[wscompile] at com.sun.xml.rpc.processor.generator.JaxRpcMappingGenerator.buildMapping(
[wscompile] at com.sun.xml.rpc.processor.generator.JaxRpcMappingGenerator.perform(
[wscompile] at com.sun.xml.rpc.processor.Processor.runActions(
[wscompile] at
[wscompile] at
[wscompile] at
[wscompile] java.lang.RuntimeException: Naming conflict occurred: []
[wscompile] at com.sun.xml.rpc.processor.generator.JaxRpcMappingGenerator.buildMapping(
[wscompile] at com.sun.xml.rpc.processor.generator.JaxRpcMappingGenerator.perform(
[wscompile] at com.sun.xml.rpc.processor.Processor.runActions(
[wscompile] at
[wscompile] at
[wscompile] at
[wscompile] error: java.lang.RuntimeException: Naming conflict occurred: []
The only mention of this error I could find was a June 14th posting on a JBoss forum. The posted solution from Thomas Diesler of JBoss was to rename the service endpoint interface. That solution, inexplicably, worked.

After playing around for a few minutes, I found a better solution, at least for the above problem: The naming conflict seems to be between the service name given in the wscompile configuration file and the class name of the SEI. They were both named MyService. My easier solution was to give the service a different name in the config file, for example: <service name="MyService_Service" ... >

I still don't know what causes the name conflict. I'm guessing the wscompile tool writes some artifacts using the service name, probably using a package name derived from the packageName or targetNamespace. I could find no documentation on wscompile on what it generates based on the service name from the configuration file. In looking at the classes wscompile generated, none seemed to conflict based on the service name. Is it generating an implementation of javax.xml.rpc.Service using the name attribute to the <service> element? If so, I couldn't find any such generated class.

Please leave a comment if you have knowledge of what artifact wscompile produces that cause the name conflict with the SEI. I figure I'll post this problem in case anyone else hits this "naming conflict" error.

Failed to install Tomcat service: solved

I spent about a frustrating half-hour solving this one. Tomcat 5 has such a nice Windows installer, and good integration with Windows services, so I hate to rag on it. But for such a common situation, it seems this is a vast oversight in the Windows Tomcat installation program.

The problem was with installing Tomcat 5.5.9 on a Windows XP system. I'd run the Windows installer and get this error dialog:
Failed to install tomcat 5 service
Check your settings and permissions
Abort Retry Ignore
The above is accompanied by a warning to select Ignore at your own peril. I googled around and none of the suggestions worked. The most common situation that results in that error is not being logged in with administrative privileges, since the Windows installer installs Tomcat as a service. That wasn't my problem. My login privileges was the first thing I checked after the "check your settings and permissions" message. I even checked the Tomcat bugzilla site and got the "Zarro Boogs found" when looking for my particular problem.

It seems the problem was having Tomcat 5.0 installed on the box. It appears that the 5.5.9 installer tries to install Tomcat as a service using the same service name, and gets an error from Windows that a service with that name exists. Either that, or the installer tries to create a Windows registry key that already was in use by Tomcat 5.0. At least these are my guesses, because uninstalling Tomcat 5.0 made the 5.5.9 installer happy. After the Tomcat 5.0 uninstall, everything worked OK.

It seems too bad I can't have both versions installed at the same time, at least by using the Windows installer.

IBM and the Meaning of The

IBM says it is "making a major commitment to Apache Geronimo as the Open Source application server of the future." Sounds good. But what is the meaning of the?

If I said The Hitchhiker's Guide to the Galaxy is the movie of 2005, you might assume I'm recommending it, using the movie as a shorthand to mean "the best" movie. Is that what IBM means by "the Open Source application server of the future"? Or does IBM mean Geronimo is the open source application server of the future? That is, IBM will work to ensure Geronimo is never quite finished or stable so as not to eat into sales of WebSphere Application Server Express.

I'm sure IBM realizes its purchase of Gluecode Software last week -- and thus its acquisition of Gluecode's five staffers who have been key architects and contributors to Geronimo -- fomented discomfort in the open source community. IBM is the 500-pound gorilla. Geronimo contributors and potential Geronimo users are wondering just what are IBM's intentions toward Geronimo. Even Gartner said "some users will ... suspect IBM of attempting to control the open-source community" with its Gluecode purchase.

As of today, IBM has been mostly silent on its intentions. Last week, IBM said it will:
  • Donate an Eclipse plugin to help developers target Apache Geronimo as their J2EE server
  • Devote an unspecified number of IBM employees to work on Geronimo
  • Keep the former Gluecode developers working on Geronimo
In addition, IBM has released some documentation aimed at Geronimo. These actions all benefit the Geronimo open source community.

On the optimistic side, IBM's goals for Geronimo will mesh with the goals of the current team of Geronimo developers and its users -- to create the best available open source J2EE application server. IBM will devote smart developers to working full-time on Geronimo, and Geronimo's features and capabilities will outshine the other two open source J2EE servers, JBoss and JOnAS. Many developers and companies would like an alternative to JBoss Application Server, especially those concerned about JBoss's restrictive license, so IBM's commitment to Geronimo could end up being beneficial to everyone, except perhaps JBoss Inc.'s consulting services.

On the pessimistic side, IBM could use its Gluecode brain trust to swing Geronimo in a direction that benefits IBM and not average users. IBM now controls, through its new Gluecode employees, about half of the active committers to the Geronimo project. The chairman of the Geronimo Project Management Committee, Geir Magnusson Jr., is one of the new IBM employees. The Geronimo PMC controls the direction of the Geronimo project, deciding what features are added and who may contribute to the project.

I think we all want to assume IBM's involvement will benefit all users, not just IBM customers. I think we all want to assume IBM wants Geronimo to be the best open source J2EE server on the market, not the best server for IBM Global Services consulting income. I think we all want to assume IBM will allow the former Gluecode employees to continue their excellent work on Geronimo.

To allay concerns, the solution for IBM is to announce just what it wants to do with Geronimo and what influence it will try to wield over the project. Do they plan to fork the Geronimo project to create a separate version aimed at IBM customers? Will IBM's commitment to Geronimo fade over time, similar to IBM's previously strong commitment to Apache Axis? Do they plan to create add-on tools to make Geronimo easier to use and deploy in the enterprise, and make them available only to IBM customers who purchase 1-year support contracts? Do they plan to restrain its employees from adding powerful features to Geronimo that would make it a WebSphere competitor?

If IBM is truly committed to open source software, it would do the open source community a favor by announcing its Geronimo strategy with a clearer statement. Saying IBM is committed to Geronimo as "the Open Source application server of the future" hasn't done much to quell unease.

Maven 2 will hurt Maven’s adoption

I think it's fair to say that Maven has yet to catch fire among Java developers. Maven is complicated to learn and its documentation is lacking. Most Java developers who are using Ant probably have heard of Maven and its promise of easier automated builds. In fact, a fair number of Ant users probably have it on their To Do List to check out Maven to see whether it will save them time.

But the Maven team's technology preview release last month of Maven 2.0 almost certainly will hurt Maven's adoption, at least in the short term. Maven 2 will slow Maven's adoption probably for at least six months, and probably into 2006 as the new Maven stabilizes.

Why my pessimism? Maven developers shot themselves in the foot by scrapping the goal of Maven 2's backwards compatibility with Maven 1, and introducing new technologies just as obscure as Maven 1's technologies. Barriers for Ant users to adopt Maven have always been Maven's steep learning curve, its scripting language (Jelly), and its semi-enforced ways of organizing a project's files. Now, Maven 2 will change Maven in drastic ways. Maven 2 scraps Jelly in favor of (I'm not kidding) Marmalade. And the favored way of writing Maven 2 plugins will be Mojos, which seems to be Java classes that get inserted into a Maven 2 Plexus IoC container. Not only does Maven 2 introduce an IoC container, it uses one that almost no one has heard of.

In short, why would an Ant user today even considering switching to Maven? If you aren't using Maven today, going to the trouble of learning Maven 1, only to be left with a tool that quickly becomes outdated as Maven developers leave it in the dustbin, would be a waste of time. For those who hate Maven to the point of bile or poetry, Maven's slower adoption won't mean anything. But for Ant users interested in learning Maven today, the Maven team seems to be saying "don't bother, wait for Maven 2."

If you think I'm exaggerating, here are quotations about Maven 2 from the Maven web site: On the positive side of Maven 2, once it matures it might help solve the complexities and slowness in Maven 1 and eventually win over more Ant users. That is, maybe they must kill Maven in order to save it.

JUG Serendipity: Finite State Machines

I checked to see what the next talk was going to be at my local Java Users Group (the Denver JUG) and saw that Eitan Suez was going to be presenting on The State Machine Compiler. My first reaction was, "What the heck is that?"

So I spent a few minutes reading about state machines and realized again why going to JUG meetings is great: JUG Serendipity. By attending JUG meetings, I learn about development tools and technologies I normally would never hear about.

Eitan will talk next Wednesday about the State Machine Compiler, a Java open-source (Mozilla Public License) project to automate creating classes that implement the Gang of Four State pattern. SMC allows you to define a "state machine" mapping file that defines the states your object can be in, what transitions trigger movement between states, and actions that should occur upon state transition. Then, in your Java code, you use a generated state Context object to change states when needed. The generated code handles the work of invoking methods to perform the actions and track the state transition.

By keeping the state definitions and transition logic in a separate file, you remove all the ugly switch and if-then-else state transition logic from your Java code. The down side is you have to learn a new notation to represent the state machine. Fortunately, the syntax defined by SMC isn't overly complex. And it's not XML!

SMC apparently was written originally by Robert C. Martin, then picked up and expanded by Charles W. Rapp. (Apparently not the same Charles Rapp agency that manages Nipsey Russell.) Uncle Bob still has a Java version of SMC available, but without source code.