Tag Archives: sucks

/usr/lib/cups/backend/ipp failed

This one time, right, I printed something using CUPS on a Linux box, right…and it actually printed!

No, really!

I didn’t have to rsync the file across to the Mac and print it from there. Printing on Linux actually worked. I swear I’m not making this up.

(And yes, I’ve tested the printer URLs, and they’re correct.)

Things that suck about Java

  • Many common tasks take an absurd amount of code. For example, try producing a date in RFC2822 format, in the local time zone. Isn’t Java supposed to be a good language for Internet programming?

  • What’s with the special types that aren’t objects, like int? I just want to have integers, and leave the compiler to determine the appropriate implementation. In the worst case, I don’t mind specifying how wide I want my integers in advance, but please, can we have them act like proper objects (i.e. everything else)?

    I mean, it’s not like anyone is going to be using Java for systems programming, and need access to raw machine words, especially since there are no unsigned integer types available. (Bytes are signed?!)

    In Java 1.5 they try to make it less ugly by having the compiler automatically wrap primitive types in object wrappers when necessary. Which is still ugly.

  • Why must arrays be unlike every other type? For instance, array objects use variable.size() to find out their upper bounds, but arrays use variable.length. They’re not like the other special types either, because they can’t be converted.

  • A related gripe is that a little more consistency in method naming would be nice. As it is, Strings have a .length(), while arrays have a .length, Arrays have a .getLength(), and ArrayLists have a .size().

    The class library is riddled with these kinds of little inconsistencies that make it difficult to remember how to use everyday objects. To pick another example, “HashMap” is camel-cased, but “Hashtable” isn’t–and of course, fussy Java will complain if you capitalize differently.

  • Apparently too little thought has been put into doing things right the first time. That makes for a horribly bloated and messy API. So we have arrays, Array objects, ArrayList objects, and Vector objects, all solving the same problem in subtly different and incompatible ways. Ditto Hashtable and HashMap.

  • No integer overflow detection. For a language designed to be safe that forces me to pick a size of integer in advance, that’s pretty stupid.

  • No abstract local functions. I happen to find map operations very useful at times.

  • Some arguments are passed by value, some are passed by reference; it depends on their type.

  • Similarly, the types that would be passed by value are copied during assignments, the types passed by reference are not. Hence, assuming you remember something has been passed in by reference and want to copy it, you specifically have to clone() it to make a copy–and if it’s in an array, you have to clone each dimension of the array manually.

  • Comparing pass-by-reference variables checks if they’re references to the same thing, rather than checking if they’re the same value. To check if they’re the same value, you have to remember that they’re ‘special’ and that you have to use .equals() instead of ==. Except it doesn’t work on arrays.

  • Constructors have their own special unique syntax. The compiler spots immediately if I don’t use the special syntax, therefore it clearly knows that the method is the constructor anyway, therefore it’s just arbitrarily making me jump through hoops for it.

  • You have to include constructors in subclasses, even if the code is identical to that in the parent class.

  • Importing packages doesn’t import dependencies. For instance, org.xml.sax.XMLReader is no use without org.xml.sax.helpers.XMLReaderFactory, so why make me import them separately?

  • There’s no way to break string literals across lines, so you have to concatenate them at run time.

  • Some of the documentation is really awful. I mean, does anyone understand RuleBasedCollator? Quote: “& Indicates that the next rule follows the position to where the reset text-argument would be sorted”. Is that even English?

    There’s also an unfortunate tendency for people to assume that JavaDoc is documentation. Often, it’s more like an adventure game, where you click around in a maze of twisty turny JavaDoc pages for hundreds of classes, hoping that at some point you’ll find some documentation that actually tells you how to perform some task you need to perform, rather than just telling you what lots of random methods do.

  • Startup times are terrible. They have been improved in Java 5 and improved further in Java 6, but they’re still bad compared with pretty much any other commonly used language, even interpreted ones like Ruby.

  • Exceptions are a pain. The ability to throw and catch exceptions is a good thing in any language; the problem with Java is the insistence that every exception be explicitly dealt with or thrown up the chain.

    In J2EE code, for example, we have the SQLException. It either indicates a syntactic error in the SQL code, or that the connection to the database is broken. There’s really nothing the application can usefully do with SQLException except report an error and die; yet because of the explicit exception rules in Java, code ends up bloated with repeated catching and rethrowing of SQLExceptions.

    It’s not clear to me that forced exceptions do anything to make programmers deal with possible problems anyway; try running Azureus and watch how many stack traces it craps to the console. Good programmers don’t need to be force-fed exceptions, and bad programmers just catch and ignore the exceptions anyway.

    The other side of the problem: if you’re implementing an interface that doesn’t declare any exceptions, you have to eat any exceptions that occur, no matter how deadly.

    I’m not sure what the solution is, but with Java I get the feeling that the cure being tried is of marginal effectiveness, and possibly worse than the disease.

  • Generics were added too late. Now we’ve got a massive class library full of unnecessarily ugly APIs.

  • Convenient iteration syntax was added too late as well (in Java 6). There are all kinds of classes which sound like they ought to be iterable, but aren’t. Like Arrays, for example.

  • String and StringBuffer make straightforward string handling unnecessarily painful. You can split a string, but you can’t modify it. You can find a string within a StringBuffer, but only in case-sensitive fashion. You can’t search a StringBuffer for a regular expression; you have to convert it to a String first–but to modify what you find, you have to convert back to a StringBuffer again, or create a new String (and pay the cleanup costs).

    So in typical input parsing, you end up repeatedly converting between String and StringBuffer objects. Even assuming that’s what the compiler would have to do anyway, why should I be forced to do it all explicitly? And if “replace string” is only available for StringBuffer, how come “replace regexp” is available for String? The whole division between the two has long ceased to make any sense.

  • In Java, null is a primitive value. But, as mentioned above, primitives like ints aren’t objects, and so neither is null. Which, in turn, means you can’t use null for null objects (for example when making objects optional)–you need to clutter the API with more methods, create empty objects, or implement a null object class.

  • IO is ugly. To do the normal “buffered write to a file”, you have to create a FileWriter object, wrap it in a BufferedWriter object to add buffering, then wrap that in a PrintWriter object to get a stream you can print to. That is:

    PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(new File(filename))));

    And don’t forget to explicitly flush and close the PrintWriter, or you’ll lose data. So much for safety! Input is just as bad. Is it too much to ask that the 90% of cases (stream-based reading and writing of text) be optimized with some kind of 1-step BufferedPrintToFileFlushOnDispose class?

  • I find the use of “static” to indicate “class scope” unnecessarily confusing. To put it another way, I find it hard to remember that “final” means “static” (unchanging) and “static” means “class”…

    Of course, the reason why “static” is used for class methods is that Java doesn’t really have class methods; static methods are static in the sense that they’re really global functions that can’t be overridden and are shared between all objects of that class. Perhaps the word “shared” would have been less confusing?

  • The insistance on a separate file for each class fragments the source code and makes it harder to keep track of where things are–or alternately, encourages the “one huge class” antipattern. The insistence on making the directory structure match the package naming adds the annoyance of having to navigate in and out of directories multiple layers deep even for a trivial project.

  • Date and time handling is broken (it uses POSIX epoch values internally), and the methods and classes are confusingly named. For example, Calendar.getTime() returns a Date, because Date objects are actually date and time objects.

Things I really like about Java

  • Unicode everywhere, no special effort required.
  • It’s pretty much portable between Linux and OS X, without having to worry about contortions like autoconf.

I don’t include automatic memory management in the list, because that ought to be a given for any modern programming language.

I should also point out that for all its faults, Java is still better than C++.

GNOME vs KDE

Fedora Core 1 died, so I installed the latest rev of the corporate desktop based on something else… which means I’m stuck with GNOME, as there aren’t any working KDE installs I can find.

With KDE it was really easy to install fonts. Almost Mac-like, in fact. Open the fonts window in Konqueror, drag the TrueType and Type 1 font files in, drop. Done.

In GNOME, I open my directory of fonts. The file manager previews them for me. I can double-click them to see them previewed larger. However, the preview doesn’t have any kind of install button, nor does the contextual menu for the files have an install option.

GNOME doesn’t seem to have any kind of font installer either. The “Font” control panel lets you select rendering options and which fonts to use for the UI, but it doesn’t actually tell you how to install fonts. The system Control Center doesn’t include anything for installing fonts either, though it does helpfully include an icon to open itself from within itself. Aaargh.

The GNOME help is useless too. It has four entries for “font”. One is about how to import fonts into Ghostscript, two are about importing and exporting TeTeX fonts, and the fourth one suggests that the way to install fonts is to edit /etc/fonts/fonts.conf

So I tried that, and discovered that the file had a comment saying no, don’t edit /etc/fonts/fonts.conf, instead edit /etc/fonts/local.conf. So I tried that, only to find that it was a mostly empty raw XML file. In particular, it didn’t mention any of the additional fonts the system already had installed, so it was clearly the wrong place.

So I tried Google and searched for an FAQ on how to install fonts in GNOME. First up was the GNOME end-user documentation on fonts. It talks about “subpixel decimation” and “GASP tables” and how to access someone’s CVS server to download a font viewer, but totally fails to mention how to install a font. At the very bottom of the page it finally mentions that GNOME’s font selection is handled by something called fontconfig.

So, off I go to the fontconfig site, and to what they laughably call their user documentation. Hey, look, it’s that fonts.conf man page again.

OK, back to Google. I find a reference to gnome-font-install. Sensible name, but (a) it turns out to be something specific to printing, and not actually a font installer; and (b) it isn’t on my system according to locate.

Time for a different approach. I search for how to install fonts for xfs (the X font server) instead, and find out that there’s a tool called chkfontpath, which actually installs fonts in the font path rather than only doing what its name suggests. So, I pull up the man page. Looks good. % chkfontpath -a /opt/coolfonts.

chkfontpath: error opening /opt/coolfonts/fonts.dir, unwilling to add path

Back to the man page. Yes, chkfontpath needs some sort of special fonts.dir file, says right there at the bottom, before completely failing to mention what the file should contain. Is there a man page for fonts.dir? No. Is the file fonts.dir even mentioned in the xfs man page? Is it fuck.

Finally I find a web page that explains the hoops you have to jump through to install fonts in GNOME. First you have to use ttmkfdir to prepare the directory containing your fonts. Obviously I didn’t find this in my searches, because it has no fucking manual page.

Having done that, you can then run mkfontdir to generate the mysterious undocumented fonts.dir file. Obviously I didn’t find that either, because it doesn’t show up on man -k fonts.dir. Yes, I know, it’s unreasonable of me to expect that a program whose sole purpose is to generate a file fonts.dir should actually mention fonts.dir in its man page index.

Having done that, it was indeed trivial to go back and run chkfontpath and actually install the fonts.

I now understand that when people say Linux isn’t ready for the desktop, it’s because they run GNOME.

It’s not just the lack of a friendly installer that makes me angry; it’s the fact that at every step of the way, the documentation is utterly useless at describing how to do the most basic task a user needs to do, yet describes itself as user documentation.

Eclipse and SWT: What’s missing

The Eclipse project has developed a toolkit which allows you to write Java applications via an application toolkit called JFace. This in turn uses a toolkit called SWT to provide native user interface objects to your Java program. End result: native look and feel, faster applications.

So, if you’re a software developer, go take a look at the Eclipse web site. See if you can spot what’s missing.

Hint: It’s something incredibly important. So important that it ought to be on the main navigator. Yet incredibly, it isn’t.

OK, I’ll tell you what’s missing from the Eclipse project.

There’s no fucking documentation.

Sure, there are a bunch of articles they link to. But an article in Java Programmer Monthly does not constitute an API reference manual.

Nor do the crappy comments extracted from the source code via JavaDoc. Yet as far as I can tell, that’s all the documentation that exists for the entire project inside or outside IBM.

Yes, there are third party books, or at least there will be soon. But third party books aren’t a good substitute for actual documentation either, because (a) they’re usually out of date by the time they’re printed, (b) they’re often written by someone with appalling programming habits, and (c) in this case the authors of the books are likely having to guess what the hell the code does as well.

Lack of documentation is a defect. It indicates crappy development practices. Any time someone suggests that you use a particular toolkit, ask to see the documentation. If it isn’t clear and well-indexed, run like hell in the other direction, because it’s a fairly safe bet the code will be even worse. (Hello, Struts.)

My top ten reasons why RedHat sucks

  1. Shoddy workmanship. RPM was discovered to be broken in 2002; it would regularly corrupt its own databases and lock up in such a way that it couldn’t be killed. In spite of that, RedHat went and made two major releases with a broken RPM.

  2. Bad packaging. The RedHat 8 release of libgcj (the libraries for the GNU Java compiler) puts a broken version of jar into /usr/bin, destroying any working version you have installed. They’ve known about the problem since 2002, but left it broken into 2003. What the hell is a jar binary doing in a libraries package anyway?

  3. RPM. If you think RPM is a reasonable piece of software design, I can only assume you’ve never used Portage, APT or BSD ports. I still have to keep a “cheat sheet” of the bizarre invocations necessary to make RPM perform basic tasks. Then there’s the fact that you can’t just install an RPM; no, you need to find the right RPM for your specific version of RedHat, assuming one exists. And if that’s a pain for you, imagine what a pain it is for developers.

  4. Broken SMP. Not a big deal for home users, but RedHat target the enterprise. Yet threading is broken on SMP systems.

  5. Bad advocacy. Standing up and telling people that they should run Windows, not RedHat, is not just a dumb move from a marketing point of view—it also infuriates the very developers they rely on for the products they repackage and sell.

  6. Broken UTF-8. Try echo redhat sucks | grep [A-Z] and see. Works on every other Linux distribution, broken on RedHat. Furthermore, man pages show up as garbage in PuTTY because nroff’s VT102 sequences get hosed. It’s possible to fix it by turning off Unicode support, but is it too much to expect that RedHat get basic stuff like terminal I/O right?

  7. X dependencies. RedHat is for servers, right? Who needs X on a server? Well, you do, if you want to run RedHat’s emacs-nox package. Want to install without X? Tough luck, their “text mode” installation still uses it.

  8. Broken Perl. Perl has its own package management system called CPAN. It’s a hell of a lot more friendly, easy to use and helpful than RPM. I do not want to manage my Perl packages with RPM. However, even if I did, I’d be out of luck, because RedHat don’t provide a complete set of CPAN libraries in RPM format, and the ones they do provide aren’t kept up-to-date. End result: Before installing any Perl library I have to check to see if there’s an RPM version. If there is, I install it and then delete it manually and install it properly using CPAN.

  9. Painful upgrades. Want to upgrade from RedHat 8 to RedHat 9? Good luck, you’ll need it. Even upgrading from 7 to 8 is a “start from scratch” affair. Compare to upgrading debian or Gentoo and it’s clear that RedHat is designed for people who never upgrade. Which wouldn’t be a problem, except that RedHat don’t support old releases any more. If you’ve got an old RedHat system, you have to reinstall anyway, so do yourself a favor and install a different distribution.

  10. Unnecessary software. When I install RedHat, I always do my best to cut down the bloat to a bare minimum. Yet somehow, I always seem to end up with iptables and ipchains. Now, in what universe does it make sense for your installer to install both of those?

J2EE in a nutshell

J2EE specifies Enterprise Java Beans for handling data, where the data and the client accessing it may or may not be on the same system. Entity beans are used to encapsulate the data in the database—instead of accessing the database directly, you create an entity bean to do it for you. That way the client can use the entity bean and not need to know about SQL.

However, the person writing the entity bean doesn’t really want to have to know about SQL either. That database stuff makes writing an entity bean a pain, so container-managed persistence was introduced. This allows you to let the EJB container (part of your J2EE server) handle the messy database stuff for you, and you don’t have to know any SQL at all.

Of course, SQL allows you to do a lot of useful things, such as querying databases in complex ways. It turned out that doing those things by fiddling around with container-managed entity beans was a real pain in the ass. So in EJB 2.0, Sun added EJB QL, the Enterprise JavaBean Query Language. It’s just like SQL, only slightly different, and not as powerful.

Of course, performance was getting pretty crappy by this point, so to improve things, EJB QL can be compiled into SQL.

So to summarize, here’s the old ugly way of doing things:

  • Client program connects to database server.
  • Client program sends SQL query to database server.
  • Client program gets back data from database server.

Now here’s the new, improved way of doing things:

  • Client program connects to J2EE server.
    • J2EE server instantiates entity bean.
    • Entity bean opens connection to database.
  • Client program sends EJB QL query to J2EE server.
    • Entity bean compiles EJB QL into SQL.
    • Entity bean sends SQL query to database.
    • Entity bean gets back data from database.
    • Entity bean passes back data to J2EE server.
  • Client program gets back data from J2EE server.

Obviously this is a big improvement. What’s more, because of the use of EJB, all of the J2EE entity bean stuff can be placed on a separate machine from the client and the database server. In fact, for performance reasons you’d be well advised to do so.

So, before: client system, database server. After: same client system, huge $20,000 server running $50,000 of J2EE application server software, same database server. Now your client software can send queries that look just like SQL, and get back results exactly as if they came from a database server—but instead, they’re coming from a box with that wonderful Java technology.

Learning J2EE, continued

I’ve just successfully written an EJB, deployed it, and called it from a servlet and some JSP.

Right now, it looks like the EJB specification has the highest complexity-to-benefit ratio I’ve ever encountered in a programming API. Sure, I’m a beginner to J2EE, but I’m an experienced software developer, and over the years I’ve developed an intuitive ability to recognize a pile of steaming crap when I see one.

Up and limping with J2EE

Today I decided that writing my own application deployment descriptors was unnecessary drudgery, so I tried out xdoclet. It doesn’t work, I get various stupid error messages that I see (from the mailing list) have been reported by other people too. I strongly suspect crapulence on xdoclet’s part, since its API changed between release 1.1 and 1.2, and will change again completely for 2.0, which is a complete rewrite. (A lot of Java projects are like this.)

Oh well. Maybe one day they’ll integrate the functionality into ant where it belongs.

J2EE is teh suck

21:32:26,041 ERROR [Server] start failed
org.jboss.deployment.DeploymentException: Could not create deployment: file:/opt/jboss-3.0.6_tomcat-4.1.18/server/default/conf/jboss-service.xml; – nested throwable: (java.lang.AbstractMethodError: org/jboss/deployment/scanner/AbstractDeploymentScanner.scan) at org.jboss.deployment.MainDeployer.start(MainDeployer.java:835)
[…etc etc…]

Stock JBoss/tomcat downloaded 10 minutes ago, stock RedHat 8, Java 1.4.0.

You know, J2EE really sucks dog balls. Every J2EE environment I’ve tried to get working has had some massive brokenness about it. Does anyone have any suggestions?