a little madness

A man needs a little madness, or else he never dares cut the rope and be free. -Nikos Kazantzakis

Zutubi

Archive for the ‘Java’ Category

Maven – Pain = Gradle?

Being in the continuous integration game, it’s part of my job to keep an eye on build tools and technologies. Occasionally I hear of something interesting enough to try out, so when I next start a small project I’ll give it a go.

This time it is the turn of Gradle. From the Gradle website:

Gradle is a build system which provides:

  • A very flexible general purpose build tool like Ant.
  • Switchable, build-by-convention frameworks a la Maven (for Java and Groovy projects). But we never lock you
    in!
  • Powerful support for multi-project builds.
  • Powerful dependency management (based on Apache Ivy).
  • Full support for your existing Maven or Ivy repository infrastructure.
  • Support for transitive dependency management without the need for remote repositories and pom.xml
    or ivy.xml files (optional).
  • Ant tasks as first class citizens.
  • Groovy build scripts.

Build tools that leverage scripting languages such as Groovy, Ruby and Python are all the rage. This is undoubtedly a useful feature, but so common these days that it is not a differentiating factor. After all, just adding a more concise way to write procedural build scripts is not a big win. The focus needs to be on making builds as declarative as possible.

The current king of declarative builds in the Java world is undoubtedly Maven. However, as I have said in a previous post, the current implementation of Maven leaves a lot to be desired. Still, the Maven idea of build-by-convention is still a good one if it can be achieved in a flexible way. This, then, is what attracts me to Gradle — its specific goal of providing build-by-convention without the lock-in.

Installation

To begin, I set myself the lofty goal of writing a “Hello, World” build script. This gets me to the point where I have a working gradle installation. As I already had a JDK installed (the only external dependency), installation was as simple as:

$ wget http://dist.codehaus.org/gradle/gradle-0.4-all.zip
$ unzip gradle-0.4-all.zip

$ export GRADLE_HOME=”$(pwd)/gradle-0.4″
$ export PATH=”$PATH:$GRADLE_HOME/bin”
$ gradle -v
Gradle 0.4
Gradle buildtime: Tuesday, September 16, 2008 9:20:38 AM CEST
Groovy 1.5.5
Java 1.6.0_06
JVM 10.0-b22
JVM Vendor: Sun Microsystems Inc.
OS Name: Linux

Gradle build files are named “build.gradle”, so next I created a trivial example as follows:

createTask(‘hello’)
{
    println ‘Hello, world!’
}

The above is normal Groovy source code, executed in an environment provided by gradle. It defines a single task which is gradle’s equivalent of a target (almost like the combination of an Ant task and target). Executing this task gives:

$ gradle -q hello
Hello, world!
$

Note that the -q flag suppresses some gradle output.

A Simple Java Project

To test gradle’s claims of build-by-convention, I next put it to work on a simple Java project. Gradle’s build-by-convention support is implemented as “plugins” for different languages, with Java and Groovy plugins provided out of the box. The project to be built is a JavaDoc doclet, so the build just needs to compile Java source files into a single jar. To make life a little interesting, the project does not fit gradle’s default conventions in two ways:

  1. It should not be named after the containing directory.
  2. The source is located under “src/java”, not “src/main/java”.

These are truly simple customisations — so you would expect them to be easily configured. And indeed they are, as shown in the build.gradle file:

name = archivesBaseName = ‘com.zutubi.xmlrpc.doclet’
version = ‘0.1′

usePlugin(‘java’)
sourceCompatibility = 1.5

targetCompatibility = 1.5
srcDirNames = [‘java’]

The first line customises the project and jar file names, and the last line is used to override the default location for Java source files. With this build file in place, I can build the jar as follows:

$ gradle -q libs
$ ls build
classes com.zutubi.xmlrpc.doclet-0.1.jar reports test-classes test-results

That was pleasantly simple! The Java plugin also gives me a bunch of other tasks for free:

$ gradle -qt
**************************************************
Project :
Task :archive_jar [:test]
Task :clean []
Task :compile [:resources]
Task :dists [:libs]
Task :eclipse [:eclipseCp, :eclipseProject]
Task :eclipseClean []
Task :eclipseCp []
Task :eclipseProject []
Task :eclipseWtpModule []
Task :init []
Task :javadoc []
Task :libs [:archive_jar, :test]
Task :resources [:init]
Task :test [:testCompile]
Task :testCompile [:testResources]
Task :testResources [:compile]
Task :upload [:uploadDists, :uploadLibs]
Task :uploadDists [:dists]
Task :uploadInternalLibs [:libs]
Task :uploadLibs [:libs]

Conclusion

So far, gradle looks very promising. The example above is too simple to judge how it would fare on a larger, more challenging build, but it shows the basics are right: at least a simple case is simple. I hope to give it a try on a larger code base soon.

At the moment the gradle project is still in its infancy, so I’ll be keeping a keen eye on its development. Indeed, if it can achieve its stated goals it will become a build tool to reckon with, and a tough competitor for Maven.


Zutubi Pulse: Continuous Integration made easy
Does your project have a pulse? Try it for free

Checked Exceptions: Failed Experiment?

Checked exceptions is one of those Java features that tends to work up a lively discussion. So forgive me for rehashing an old debate, but I am dismayed to see continued rejection of them as a failed feature, and even more so to see proposals to remove them from the language (not that I ever think this will happen).

In the Beginning…

Most would agree that mistakes were made in the way checked exceptions were used in the early Java years. Some libraries even go so far as doing something about it. However, an argument against the feature itself this does not make. Like anything new, people just needed time in the trenches to learn how to get the most out of checked exceptions. A key point here is that checked exceptions are available but not compulsory. This leads to a reasonable conclusion, as made in Effective Java:

Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

The key point here is recoverable. If you can and should handle the exception, and usually close to the source, then a checked exception is exactly what you need. This will encourage proper handling of an error case – and make it impossible to not realise the case exists. For unrecoverable problems, handling is unlikely to be close to the source, and handling (if any) is likely to be more generic. In this case an unchecked exception is used, to avoid maintenance problems and the leakage of implementation details.

Continued Criticism

None of the above is new, and to me it is not contraversial. But the continued attacks on checked exceptions indicate that some still disagree. Let’s take a look at some common arguments against checked exceptions that still get airtime:

Exception Swallowing/Rethrowing

Some argue that the proliferation of code that either swallows checked exceptions (catches them without handling them) or just rethrows them all (“throws Exception”) is evidence that the feature is flawed. To me this argument carries no weight. If we look at why exception handling is abused in this way, it boils down to two possibilities:

  1. The programmer is too lazy to consider error handling properly, so just swallows or rethrows everything. A bad programmer doesn’t imply a bad feature.
  2. The programmer is frustrated by a poorly-designed API that throws checked exceptions when it shouldn’t. In this case the feature is an innocent tool in the hands of a bad API designer. Granted it took some time to discover when checked exceptions were appropriate, so many older APIs got it wrong. However, this is no reason to throw out the feature now.

You need well-designed APIs and good programmers to get quality software, whether you are using checked exceptions or not.

Maintenance Nightmare

A common complaint is how changes to the exception specification for a method bubbles outwards, creating a maintenance nightmare. There are two responses to this:

  1. The exceptions thrown by your method are part of the public API. Just because this is inconvenient (and when is error handling ever convenient?) doesn’t make it false! If you want to change an API, then there will be maintenance issues – full stop.
  2. If checked exceptions are kept to cases that are recoverable, and usually close to the point when they are raised, the specification will not bubble far.

Switching every last exception to unchecked won’t make maintenance problems go away, it will just make it easier to ignore them – to your own detriment.

Try/Catch Clutter

Some argue that all the try/catch blocks that checked exceptions force on us clutter up the code. Is the alternative, however, to elide the error handling? If you need to handle an error, the code needs to go somewhere. In an exception-based language, that is a try-catch block, whether your exception is checked or not. At least the exception mechanism lets you take the error handling code out of line from your actual functionality. You could argue that the Java’s exception handling syntax and abstraction capabilities make error handling more repetitive than it should be – and I would agree with you. This is orthogonal to the checked vs unchecked issue, though.

Testing Is Better

Some would argue that instead of the complier enforcing exception handling in a rigid way, it would be better to rely on tests catching problems at runtime. This is analogous to the debate re: static vs dynamic typing, and is admittedly not a clear cut issue. My response to this is that earlier and more reliable feedback (i.e. from the compiler) is clearly beneficial. Measuring the relative cost of maintaining exception specifications versus maintaining tests is more difficult. In cases where an exception almost certainly needs to be recovered from (i.e. the only case where a checked exception should be used), however, I would argue that the testing would be at least as expensive, and less reliable.

Conclusion

I am yet to hear an argument against checked exceptions that I find convincing. To me, they are a valuable language feature that, when used correctly, makes programs more robust. As such, it is nonsense to suggest throwing them out. Instead, the focus should be on encouraging their appropriate use.

Q: What Sucks More Than Java Generics?

A: Java without generics. Yes, there are many problems with the Java generics implementation. And I seriously hope that the implementation is improved in Java 7. However, it occurs to me that the problems can generally be worked around by either:

  1. Not using generics where the limitations make it too difficult; or
  2. Using unsafe casts.

In both cases, you are no worse off than you were pre-generics, where you had no choice! Despite their limitations, generics have done a lot to reduce painfully repetitive casting and mysterious interfaces (List of what now?). They also enable abstraction of many extremely common functions without losing type information. In these ways I benefit from generics every day, enough to outweigh the frustrations of erasure.

Phrases You Should Never See in an FAQ

Today’s phrase of choice is “you don’t need”, with the word of the day being “never”. Consider this entry in the Hibernate FAQ:

The hibernate.hbm2ddl.auto=update setting doesn’t create indexes

SchemaUpdate is activated by this configuration setting. SchemaUpdate is not really very powerful and comes without any warranties. For example, it does not create any indexes automatically. Furthermore, SchemaUpdate is only useful in development, per definition (a production schema is never updated automatically). You don’t need indexes in development.

What’s the problem with this? The FAQ answer is saying (in a round about way) that you should not ask this question, as you don’t need an answer. Telling your users what they need is a good way to alienate them. If this question is common enough to warrant an entry in the FAQ in the first place, aren’t your users telling you that they do need this functionality? This doesn’t mean you have to jump to implement it – just don’t patronise your users by telling them you understand their needs better than they do.

Personally, I was looking at this entry because we use Hibernate for persistence in Pulse. In Pulse, there is a built-in upgrade framework that updates the schema automatically for you when you install a new version. So much for the assertion above that “a production schema is never updated automatically”. While recently adding an upgrade that required new indices, I also certainly did “need indexes in development” because I want my development environment to match production as closely as possible (not to mention the fact that they saved hours in testing time against large data sets).

The most interesting underlying thing is that the existence of this (and similar) FAQs seems to be indicating to the Hibernate team that the simple SchemaUpdate code could actually be the beginnings of an extremely useful tool. Too few applications have decent upgrade capabilities: our users are often pleasantly surprised by what we have been able to build with considerable help from SchemaUpdate to simplify their upgrades. Maybe the Hibernate team are underestimating the potential of their own tool?

The Problem With Maven

Various times during the recent CITCON, the discussion turned to build tools. With lots of Java developers present, Maven turned up in most of these discussions. Like every build tool, there are things that people love and hate about Maven. The interesting trend in every Maven discussion is:

  • The people who love Maven love the theory. Maven defines and implements a highly-standardised build process so that if you are willing to follow that process you get a lot of stuff for free (plus the inherent consistency). This is a Good Thing, somewhat reminiscent of the in vogue “convention over configuration” mindset. Smart teams standardise their build process anyway, so why not take advantage by sharing as much of the implementation as possible?
  • The people who hate Maven hate the reality. The implementation just leaves a lot to be desired. Granted, taking on a larger scope than most build tools makes an ideal implementation more difficult. However, there are a couple of key implementation issues that cause headache after headache. First, there is a lack of flexibility. Small tweaks to the standardised model can be infuriatingly difficult to apply — frequently the only answer is to write a plugin. Second, there are major stability issues with plugins that are available. Some core plugins have historically been left in an unstable state for months.

Of course this split also creates many users that have a love/hate relationship with Maven: they love it when it works, and loathe it when it doesn’t. Users also spend a great deal of effort controlling their own Maven repositories to avoid some of the implementation headaches.

I don’t want this post to be taken as purely Maven bashing. The theory behind Maven is a valid one, and with some steps to resolve the implementation issues the project would attract and keep a lot more happy users. In my opinion, the project needs to immediately address the implementation concerns. Some ideas that come to mind:

  • A process needs to be put in place to control the stability of plugins. This must be a lightweight process that allows problems to be fixed and new versions delivered more quickly than in the past. Users also need more protection from unstable versions. If a new version is found to have a bug, wind back to a stable version so that the default plugin downloaded actually works.
  • The project could consider providing stable Maven “distributions” as pre-packaged downloads. Wrap these up out of battle-tested plugin versions.
  • Introduce at least one level of flexibility between “this is a simple config option” and “you’ll have to write a plugin”. I don’t pretend to have a magical answer for this problem: it is no easy task. But when a new user is trying Maven and finds some tweak will require them to write a plugin, it is a major turn off.

Make the reality smoother, and more people will buy into the theory.

Java 1.6: Easier Thread Dumps For All

Thread dumps are an invaluable form of debugging, especially something running at a remote site. When you have no idea what is going on inside your application, a thread dump can be a life saver. However, depending on the operating system and method of launching the application, it can be difficult to get a thread dump by the traditional method (SIGQUIT on Unix and Control+Break in the console on Windows). Either it is difficult to find the right Java process (pre-NPTL Linux), it is difficult to find where stdout is going (when running as a service) or it is impossible to hit Control-Break (no console!).

Well, a couple of tools that first arrived in Unix 1.5 JDKs solve this problem. And now, in Java 1.6, they are available on Windows too. Those tools are jps (a ps for Java processes) and jstack (a tool to dump the threads of a specified Java process). Shipped with the JDK, these tools make getting a thread dump child’s play:

jsankey@pal:~$ jps -l
8328 com.zutubi.pulse.command.PulseCtl
5310 org.tanukisoftware.wrapper.WrapperStartStopApp
4306 org.apache.tools.ant.launch.Launcher
8729 sun.tools.jps.Jps
8350 org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner
jsankey@pal:~$

There you have the PIDs for all Java processes running as the current user, with the name of the main class. To dump the threads, pass the PID to jstack:

jsankey@pal:~$ jstack 8328
Attaching to process ID 8328, please wait…
Debugger attached successfully.
Client compiler detected.
JVM version is 1.5.0_08-b03
Thread 8581: (state = BLOCKED)
– sun.misc.Unsafe.park(boolean, long) @bci=0 (Interpreted frame)

Voila! Of course, if you have a graphical environment available, you can get all the goodness of jconsole too.

java.blogs Updates

Well, if I’m going to whinge when I don’t like changes to java.blogs, then I feel it’s right to also give credit when it’s due. The latest round of updates have addressed the usability issues, and I personally much prefer the new look. So, to the devs at Atlassian: well done, and thanks.

The Rise of OSGi

There is a lot of talk buzzing around about OSGi, the “dynamic module system for Java”. Most famously, an implementation of OSGi forms the basis of the plugin system in recent versions of Eclipse.

So what is OSGi? If you head to the official website for the answer, you could be forgiven for thinking you had stumbled on a game of buzzword bingo. The terms “universal middleware”, “service oriented” and “component based” show up in the first couple of sentences! Putting marketing-speak aside, however, OSGi turns out to be a mature standard for dynamic modules (read: plugins) for Java. Despite the buzzwords, it is also pleasantly simple at its core (plugins are just Jar files with metadata in the manifest). If you’re looking to create a plugin-based application, or to add a plugin system to your existing application, then you should look into OSGi.

In our case, we are adding a plugin system to the next major version of Pulse. We have decided to go with OSGi for a variety of reasons:

  • A robust standard for the basic requirements of a plugin system: such as plugin metadata, dependencies, classloading, service management, dynamic loading/unloading and so on. Why reinvent a less complete system?
  • A simple core: OSGi plugins (known as bundles) are just plain old Jar files with some metadata. This simplicity will make our life much easier.
  • Existing open source implementations: we have chosen the Eclipse foundation’s Equinox implementation, but there are others such as Felix, Knopflerfish and Oscar.
  • Eclipse tooling support: as Eclipse uses OSGi under the covers, the Eclipse Plugin Development Environment has tool support for creating and managing OSGi bundles. One of our goals is to make the lives of plugin authors as simple as possible: tool support helps achieve this.

Of course, it is not all good all of the time. There are some challenges we face along the way:

  • Lack of documentation: it is seriously difficult to find good documentation about OSGi and the implementations, apart from the standard itself (which happily is reasonably readable). The saving grace is having the Equinox code and a helpful development community.
  • Embedding Equinox: the Equinox framework, as part of the Eclipse project, has a certain bias towards being used as part of the larger Eclipse platform (and Rich Client Platform). This is changing over time, but we are finding some interesting challenges embedding Equinox in Pulse.
  • Impedence mismatches between Pulse and OSGi: at times the default OSGi behaviour is at odds with how we would like plugins to act in Pulse. For example, OSGi mandates that the state of plugins is persisted by the framework, whereas we want Pulse itself to have control over their state.

As we continue the implementation of a plugin system for Pulse, I’ll post more about the particular things we learn along the way. Hopefully this information will help fill the documentation black hole, particularly in a new area for Equinox: embedding in a standalone application.

How Not to Use “AJAX”

Once a technology reaches buzzword-compliance, it starts to pop up in the least appropriate of circumstances. The current manifestation of this is the “improvement” of favourites management on javablogs.

Let’s review favourites as they were. You have the ability to add a chosen blog to your “favourites” list. You can also choose to ignore a blog, so that entries from that blog are hidden. To do this previously, you simply clicked on a “+” or “x” icon next to the header of any entry from the blog:

Simple, and effective. Now, swept up in the hype of AJAX, the mechanism for managing favourites has been updated. The same “+” and “x” icons still appear, but they no longer take direct effect. Instead, they pop up a dialog:

Wow, a nice piece of eye candy that serves no purpose whatsoever. The dialog gives exactly the same options as were available before. The text description of the actions could more appropriately be added as tooltips for the icons. To add insult to injury, you can’t even click on the text, but only the icons on the left. I can see the tagline now:

“Favourites management: Now with extra click!” :)

Strictly speaking, the dialog itself is not AJAX at all, just plain old Javascript/DHTML. The adding of favourites, though, does happen without a full refresh, which is an improvement.

Now, javablogs is not alone in this gratuitous use of new technology, it just happened to be right in my face today. Please people, remember: the goodness of AJAX (and more use of Javascript/DHTML) is in improving usability. Think before you code, and keep your AJAX tasteful.

Java 1.6: Finally Integrating With The Underlying Platform?

We all know the Java promise, Write Once Run Anywhere. And we all know some things are too good to be true. On the one hand, there are those features that don’t quite work the same on different platforms. That’s just a fact of life in portable programming, which I can deal with. On the other hand, there is the lowest common denominator syndrome. Important features that are only available on some platforms are non-existent in the Java APIs. The excuse for the absence of such APIs is, of course, that they can’t be implemented on all platforms. This I can’t stand1. I don’t expect every platform-specific API to be exposed, but some are just too important to ignore. Unfortunately for Java programmers, Sun has managed to ignore several for quite some time, for example:

  • Unix style file permissions: applications that work with Files (yes, there are a few of them) often need access to the read/write/execute permissions. I have seen (and written) plenty of ugly workarounds to use the stat/chmod commands to achieve the desired result. A request for this functionality can be found in the bug database from as early as 1997. Sure, the permission systems are different on other platforms (notably Windows), but you can cover a huge percentage of use cases with a small amount of work. Finally, in Mustang, we have the ability to get and set the permissions.
  • Free disk space: those applications working with the file system may also want to make sure they don’t fill it. It is a lot easier to prevent disk exhaustion than to recover from it. Looking back, poor Java developers have been hoping for this ability since 1997. Finally, Mustang delivers.
  • Masked command line input: the primitive Java APIs for command line interaction make it near impossible to create a usable command line interface. An example of something simple which you cannot do without crazy workarounds is prompt for masked input, e.g. to get a password. yep, you guessed it, there is a request from way back in 1997. Finally, in Mustang, we have the new java.io.Console class that provides a readPassword method.
  • System tray icons: many applications that wish to integrate with popular desktops on both Windows and Unix need the ability to use the system tray. It’s an expected part of the user’s desktop experience. The earliest request I found for this one is from 2000. The nice part is the Mustang support grew from an external project, so in this case the users were a bit more empowered.

It’s quite sad that Java developers have had to wait a decade for such commonly-required and relatively simple APIs. No wonder Java has had trouble getting a foothold on the desktop when it has been so difficult to make an application that integrates well with the underlying platform. I just hope the arrival of this new functionality in Mustang is a sign of a new attitude towards such features. No more hiding behind the platform independence argument, time to just get on and give people the tools they need to get the job done.


1: It’s worth noting that this sort of attitude is not restricted to the Java community. I can’t count the number of times that I have seen people in the C++ community reject ideas for additions to the standard library because “C++ runs on platforms that don’t even have a file system”. Who cares when 90% of C++ code runs on systems that could use this functionality!


Interested in automated builds? Pulse 1.2 is now in Early Access Release. Check it out!