Why I hate ant


$ strace -f ant > out.txt 2>&1
$ grep "stat.*java" out.txt | wc -l
32933

WTF? No wonder our build times suck. I still have yet to hear a rationale for the existence of ant that had any more substance than “but make uses tabs!”

I hate you, Sun.

Is it too much to ask of a compiler that if it decides to blare warnings at you for no reason at all, that you can turn the !@#$ thing off? In a move that rivals the stupidity of certain gcc warnings, we have this:

[javac] file: java:519: warning: com.sun.rowset.CachedRowSetImpl is Sun proprietary API and may be removed in a future release

Well, hey that’s a nice heads-up to give me 600 times when compiling our tree. Let me go find the non-com.sun equivalent of that. Oh wait, there isn’t one! And, the freaking javadoc even tells you to do it that way. Okay, well, maybe @SuppressWarnings({"deprecation"}) will work? Nope, haha! Sigh. Time for a wrapper script.

Request of persons who wish to write a better javac: can I have plugins that let me muck with the AST? Custom static checking would be nice…

I dislike Java.

Dear lazy web,

It would be nice if you could tell me a non-hacky way to do progress dialogs from within the event-dispatch thread in Swing, where all of our application logic happens to reside.

This doesn’t work:
display modal dialog
start worker thread
(won’t run because event thread is blocked)

Nor does this:
start worker thread
display modal dialog
(race condition hiding the dialog)

Joining in the event thread won’t work because it blocks updates. Using a non-modal dialog and passing the bottom-half of the rest of the event thread to the worker thread to execute at completion will work, but is obscenely messy. Or, one can spin in the beginning of the thread waiting for the modal dialog to appear to avoid the race condition, but that is still gross. One could subclass Dialog and have it also signal a condition variable once it blocks… ugh.

JAXB sucks

Allow me to enumerate the many ways I hate JAXB. JAXB is an XML data binding tool for Java; that is, it generates code to make using XML more Java-like. This is great in concept. In reality it is not so great:

  • Two days away from your project due date, JAXB lets you know that it isn’t mindful of the method size limits in the JVM. Javac tells you: “code too large.”
  • There’s a limit to method sizes in the JVM?
  • Upon examining a generated class, you discover 25k lines of utter garbage. Things like the same if-then clause being repeated twice in a row.
  • Turning off generation of the validator, or the unmarshaller, or the validating unmarshaller does have the effect of reducing code size, at a cost of generating code that doesn’t compile.
  • Or if it compiles, it throws a runtime exception when you use it.
  • The object hierarchy is all screwed up, such that a concrete implementation type may implement a (JAXB internal) interface that is not also implemented by the corresponding abstract interface (the two are supposed to be interchangeable).
  • You have to do naughty proprietary things to make type substitution work.
  • Creates a new namespace prefix for practically every element even though I only use 3 namespaces in the entire document.

I only just learned about XMLBeans. Dammit.

What is wrong with Java part 200

Here is what Java really lacks: a shell.

Bear with me on this one. I’m not talking about something to replace bash in day to day work. But there needs to be a way to get java applications up and running with less work. Practically every time I have to run a standalone java application, step one is grepping through several directories of jars to find the ones with the magic name that satisfy runtime requirements (and hope that each jar thus found represents an implementation and not a set of interfaces). Step two is writing a shell script that creates a huge classpath of said jars, then has a command line like java -cp $STUPID_CLASSPATH org.foo.some.really.long.path.to.the.ClassToRun. These command lines have to die. I can’t believe this language has been around for 8+ years and no one has come up with something better.

So here is what I suggest. First, there’s an interactive shell, like perl without arguments, which starts or attaches to an existing running VM and lets you run snippets of Java code as you like. Like the JS interpreter that comes with Rhino. Second, there is a versioning system applied to jars, much like the SONAMEs in shared libraries. This would only be a hint to the VM that you could override if you wanted to, but in the default case it would specify the version of a given named jar that you would like to load. Third, there would be a place to put all your library jars, like jre/lib/ext but smarter. Next, there’s an easy way to find all of the executable classes within a jar (i.e. ones that have a main function). Finally, there’s some meta data in the manifest that lets you give user-friendly (all lowercase) names to various classes.

Once this framework is in place, the user experience would be something like: 1. put newly downloaded jar in $apps or $lib. 2. go to the java shell window and type “some-app-name”.

I guess this is a pretty unix-centric way of organizing things, but hey, unix works. The classloader would be the hardest part (witness all the problems with JBoss’ unified classloader) but, ya know, wouldn’t it be nice to not have 20 copies of log4j.jar on your hard drive and to be able to run Java apps without reading the instructions to find out what exceedingly.long.reverse.domain.TheClassUses.

After we do this, we get rid of ant.