You know. There was a time when I really enjoyed writing Java code. Indeed, if that weren't the case I'd hardly have invested the time I did writing Rox.
But these days I'm finding myself resenting it more and more (although to be honest I don't think Java's directly to blame).
If you've ever had to spend any time with JAXB, Axis, WSS4J (or WS-Security in any form) then perhaps you'll understand where I'm coming from. Part of it is the HammerFactoryFactory syndrome, which seems to proliferate in particular amongst the XML related Java libraries.
However, I think the rabbit hole goes deeper. Many of the Java XML related APIs are chasing some of the most "flexible" (which is usually just a synonym for complex) specifications ever produced. WS-Security and XML-DSIG with the associated XML canonicalization are cases in point. XML Schema is another. The latter is so complex that one XML.com article (which ranks pretty high on Google searches relating to XML Schema) suggests restricting your use of it to a substantially smaller subset. And at least one of the arguments for not using a particular feature (extension by type restriction) is based around the fact that that part of the specification is so complex that no validators (at the time of writing) enforce it. Anyone else hearing warning bells?
WS-Security is another great example. The idea is a single, well defined, approach to logically signing or encrypting XML documents. The idea is that you should be able to do this at the logical level, freeing systems from dealing with nasty things like encodings. Unfortunately, this means everyone has to agree on what the XML looks like before they can process it correctly. Enter XML canonicalization. Take a look at the spec. Now granted, this deals with dozens of difficult edge conditions introduced because you're dealing with XML, which means you're dealing with Unicode. But I'm yet to be convinced that this obeys the 80-20 rule. Sure, there are potentially cases where this is necessary, but the common cases would be well served by far, far simpler solutions. And given the complexity of implementing some of this stuff (or just figuring out how to use libraries that all to often reflect the underlying complexity in their own APIs) most are: eventually you stop, realise it will take an hour to roll your own solution versus a couple of days to get the "correct" solution working, and you give up and go trail blazing.
At the end of the day it all boils down to one thing. These "technologies" sound good on paper but break down in practice. Why should you have to spend days, or weeks getting the basic infrastructure for a web service working? Why should you have to ship a few megs of libraries in your client just to construct signed requests? What, in all honesty, are you winning?
I'm betting at least one person reading this is thinking something about interoperability, or reuse, or some such nonsense. Sure, in theory a shared, language and platform neutral specification means interoperability. But I'll tell you what happens in reality. In reality, these specifications are so overly general, so complex, that there's either no implementation for your language of choice, or there's only one or two.
Which means one of two options: stay with your language choice and roll your own, or switch to a language which has an implementation. The latter tends towards homogenous systems (at least at the language level) at which point interoperability becomes a moot point.
And anecdotal evidences suggests that the implementations of these specifications tends themselves to become monsters. Apache WSS4J (an implementation of WS-Security) is a great example. I challenge you to figure out how to use this to produce a SOAP request that's unencrypted, signed using an RSA private key, and includes the X509 certificate in the request in anything under a day. Even with Google handy. (And once you've done that swallow the fact that you can only make a single request with given credentials at a time because, guess what, credentials are static members.)
That last point deserves to be expanded on. Another reason I'm hating writing anything in Java right now probably has something to do with the frequency with which I've been forced to deal with Apache libraries. I cannot convey what a steaming pile of shit these libraries generally consist of. I'll leave it to Hani to do that. Some of the most blatant evils these libraries are guilty of include:
- Relying on external files for configuration. This forces you to cart these files around in some form within your own applications, often all sharing the root directory (assuming the library's even using the ClassLoader to load these files). Often these files are just an excuse to use XML somewhere. This makes it almost impossible to produce a clean API. Sun's JWSDP is guilty of this in a number of places too.
- Singletons/shared static data preventing multithreading. This comes up in a number of libraries and isn't limited to WSS4J. When I discover stuff like this I check Google to see if the community is up in arms about the kind of shit they're subject to. It's sad how often they haven't even noticed. A thread started by someone who did notice the WSS4J limitation I mentioned earned a response of "Try our latest release, we've done some refactoring and maybe this has been addressed" as if shifting some code around might somehow magically address bad design.
- A complete and utter lack of any useful documentation. Sure, this isn't limited to the Apache projects, way too many open source libraries suffer here, but the Apache libraries' APIs are so utterly beyond comprehension in so many cases that you're forced to go looking for docs (because trust me, you don't want to spend any time in their source code).
But desipte the fact that the Apache APIs are generally terrible, they seem to have won the Java community over (I'm not really sure what that says about the Java community; nothing good I'm afraid) so you're forced to drag commons-cli, commons-logging, commons-discovery, commons-httpclient, commons-kitchen-sink etc along with you. And they tend to depend on one another so that if you're forced to swallow one or two you often end up gagging on the whole caboodle.
So right now I'm not enjoying writing Java code. Give me Ruby. Hell, give me Python, Common Lisp, OCaml you name it. Anything that doesn't expect me to pass an XML configuration file to the HammerFactoryFactory component before I've even started.