this is totally gonna work… » Java

What Jersey Means To Java

March 4th, 2009

In the last few days at work I’ve been migrating a home-grown REST framework over to the Jersey project (the reference implementation of JSR-311 or, JAX-RS). Previously I had done some work moving JRuby into the VM and launching Merb. It was satisfying to figure out how to do that, but involved an awful lot of wiring and special-casing.

As anyone who has read this blog recently knows, the luster is coming off of Java for me in a big way. These days my goals are simply to co-exist with it in a way that keeps me happy. I’m not going to be able to toss Java overboard so my working-life becomes a question of how to be happy with the situation.

While our home-grown framework has worked well for us, I’d much rather see us using something with wider adoption and use. So I took a look at Jersey and came away pretty impressed. Looking at how the API is built and what you need to do to build REST-ful web services in Java I couldn’t help but feel like Java has learned some lessons from the rest of the world.

The original Servlet API is what could be termed a “classic” Java API, wherein consistency and type-safety are the rules. In the Servlet API, you interact with requests and responses as monolithic objects. Each type of HTTP method (i.e. GET, POST, PUT and DELETE) has their own method which takes a ServletRequest and a ServletResponse object.

It’s a reasonable first solution, but it breaks down quickly. The primary issue is that by packing all possible request-related data into a single request object, and all possible response-related data into a single response object the classes themselves start to feel bloated. A more sinister second-order effect is that these classes, especially the response object, have some hidden state and “gotchas” because they are so general.

As an example, consider the case where you want to return a response with a non-200 response code, an entity body and some headers. The order in which you set these on the response object is important because of how it’s implemented. You need to set the status and headers before you write any output to the stream. This make sense because you want a stream-oriented interface which means not storing the entire response in memory and then flushing. But, due to the strict order of HTTP response messages, you need to flush the header information prior to sending the body. It’s not a particularly difficult thing to remember, but it is unnecessary mental overhead that is an artifact of the implementation.

The request object is its own special brand of fun to deal with. Again its broad coverage makes for a rather clunky API to deal with. You want request parameters? You have to grovel through String arrays if you want to capture all of them. When implementing a Servlet, often what you want is some combination of request parameters, cookies and header; rarely do you need all of them at once. However what you get is one big über-object that has everything. Enjoy!

One final beef with the ServletRequest class is that getting path parameters out is an absolute nightmare. If you’re building REST resources you really really care about the path as it is the way to identify resources. The poor support the ServletRequest class provides for this is simply shocking. Here’s a String — you parse it and figure out what the hell the segments are.

In contrast, Jersey has a much looser philosophy with how requests and responses are handled. First, the monolithic request and response objects go away. Instead your methods provide the narrowest possible interface, expressing only what they need in exacting terms. This is done by making extensive use of Java annotations to mark up simple method parameters. For example, if you have a resource that needs a request parameter, use the @QueryParam annotation. Need a header? Just use @HeaderParam. Interested in cookies? Use the @CookieParam annotation. Here’s an example:

1
2
3
public MyResult getMyResult(@QueryParam("name") String name) {}

This does away with a tremendous amount of “busy-work”. You want the “name” parameter? By god you’re going to get it—no intermediate objects to reach into and pull stuff out of.

A really nice side-effect of this is that writing tests for your resources become so much cleaner than using the more general Servlet API. Instead of setting up the monolithic request and response objects, you simply pass in the bits you want.

What about the response side? I think that it’s in this area that we really see a fundamental philosophical shift emerge. In an earlier time the textbook answer to how to design an API like this would be to have each request method return some kind of superclass or interface. This would allow us to use polymorphism to vary the response, but keep our type-safety.

Jersey takes a different approach based on real-world needs. Whereas the Servlet API is intended to keep everyone equally happy by making sure everyone suffers the same amount of pain, Jersey lets you vary what you return—no special markers, no special configuration. If you have a simple case where you want to serialize an object as the entity response, just return the object.

What if you need to fiddle with the response some more? Maybe set some headers or alter the status code? In this case your method returns a Response instance. Now this may sound monolithic and perhaps, under the covers, it is. What saves it from degenerating into the Servlet API is the fact that you build a Response object with only as much as you need.

In the Servlet API you might have to set a moderately complicated response like this:

1
2
3
4
5
6
7
8
9
10
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
  // do some stuff
  resp.addHeader("Expires", computeExpires());
  resp.setStatus(201);
  writeResponse(resp.getWriter(), new MyStuff());
}
 
private void writeResponse(Writer writer, MyStuff stuff) {
  // do whatever you have to do to serialize your object
}

In Jersey it looks like this:

1
2
3
4
public Response getMyStuff() {
  MyStuff stuff = new MyStuff();
  return Response.created(stuff).expires(computeExpires()).build();
}

The amount of code probably comes out to be the same, but the fact that you can build the response in a single line feels really good to me. The amount of vertical space dedicated to response-building is much more proportional to it’s conceptual space in the method in Jersey than the Servlet API.

Now I realize that comparing Jersey to the Servlet API is perhaps unfair. The Servlet API is really designed to operate a layer below where Jersey plays. But I think the same arguments apply to a majority of the other popular web frameworks. The models are all essentially the same.

So here’s where the philosophical sea-change comes in. To vary the response type to do the right thing means that after a decade of existence, people are finally embracing Java’s reflection capabilities. Up until pretty recently this was considered the domain of the lunatic fringe.

The primary argument against reflection has always been that it’s too slow. While it’s true that their can be a penalty under certain circumstances, the modern perspective is that it’s an acceptable price to pay for a kinder, gentler API. Simply put, this level of dynamism is essential for reducing the amount of boilerplate and busywork.

I think if other frameworks like Rails, Django and Merb hadn’t gained so much traction in the last few years Java would have continued on it merry way. However I think the popularity of those alternatives has forced the Java greybeards to learn a thing or two. Strict static type-safety can become a burden and using reflection to vary behavior instead of polymorphism can make for some very clean APIs.

After spending a few days with Jersey I find myself a little re-energized to work with Java again. We’re even considering Groovy as a way to cut down Java’s chubby syntax for another small productivity win. Of course, my personal preference would be to do this JRuby since I, personally, don’t find Groovy to be terribly compelling on its own. But since Jersey is so dependent on annotations, using JRuby is a non-starter.

Who knows? This could be a complete fiasco and another frustrated attempt at tilting windmills. I’m already a little suspicious of the “enterprisey” way this thing gets configured. However if nothing else, it’s refreshing to see some new ideas make their way into Java after all these years.

Posted in Java, REST | No Comments »

You Put Merb In My Jetty!

February 11th, 2009

In the latest update of The Chronicles of Stuff Alex Figures out at Work, our intrepid hero figures out how to run Merb inside an embedded Jetty instance!

Now you may ask yourself, “for the love of God, why would you want to do something like this?” Well, at work we do a lot of internal web services. For my particular team, we’ve found a real sweet-spot by using an embedded Jetty server sitting right next to a BDB instance. There are no extra processes or packages to manage (e.g. apache or a RDBMS). However we were becoming dissatisfied with our current web layer which is a homegrown REST framework that sits on top of the Servlet API. So in a fit of rage, I decided to see if I could stuff Merb in the middle of this mess.

You may also be asking yourself, “why not use the jruby-rack gem directly?” The answer is that the jruby-rack gem makes a lot of assumptions about how you want to run your application. First it assumes that you’re cool with packaging things up as a WAR (which I’m not) and, secondly, that your application is primarily a Rails/Merb application. In my case, for better or worse, our app is really a BDB application with a Merb app glommed onto the side for web visibility.

The Solution

I can’t take complete credit for this solution. If I hadn’t found Jan Berkel’s post on putting Rails in Jetty I would have never figured out how to stuff Merb in there. To give yourself some context, take a look at that post first. Then take a look at the “Merb-ified” version of the same recipe below. Both solutions assume that you’re configuring Jetty within JRuby.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server = org.mortbay.jetty.Server.new
thread_pool = org.mortbay.thread.QueuedThreadPool.new
thread_pool.min_threads  = 5  # adjust as needed
thread_pool.max_threads  = 50
server.set_thread_pool(thread_pool)
context = Context.new(nil, "/", Context::NO_SESSIONS)
context.add_filter("org.jruby.rack.RackFilter", "/*", Handler::DEFAULT)
context.set_resource_base(Environment.resolve)
context.add_event_listener(MerbServletContextListener.new)
context.set_init_params(java.util.HashMap.new('merb.root'=>; Environment.resolve,
    'merb.environment' => 'production',
    'public.root' => Environment.resolve('public'),
    'gem.path' => Environment.resolve('gems'),
    'org.mortbay.jetty.servlet.Default.relativeResourceBase' => '/public',
    'jruby.max.runtimes' => '1'))
context.add_servlet(ServletHolder.new(DefaultServlet.new), "/")
server.set_handler(context)
server.start

Tweaking

At first blush our performance seemed to be pretty lacking. This required two tweaks: putting Merb in “production” mode and dealing with poor I/O due to logging. In the previous snippet you will notice that we set the merb.environment to production. Yes we lose the quick dev turnaround, but since there is a lot of Java in this project we usually have to recompile anyway which requires a restart anyway (phooey).

As for the I/O issue, a little digging revealed that shutting up Merb as much as possible would help reduce the amount of JRuby-level IO. In our config/init.rb we configure logging like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
Merb::Config.use { |c|
c[:environment]         = 'production',
c[:framework]           = {},
c[:log_level]           = :warn,
c[:log_file]            = Merb.root / "logs" / "merb.log",
c[:use_mutex]           = false,
c[:session_store]       = 'cookie',
c[:session_id_key]      = '_facet-store_session_id',
c[:session_secret_key]  = '49411912879b879e13f89a9280c0f6aaa2e3ab58',
c[:exception_details]   = true,
c[:reload_classes]      = false,
c[:reload_templates]    = false
}

Here we set the environment to “production” again (yes, you need to do both). Also we upped the log level to “warn” which significantly reduced the amount of logging merb does. With these tweaks in place we found that the Merb port of our service was operating within about 80% of the level of performance we were getting from our pure-Java solution.

Benchmarking was done by running httperf tests against the resources we expose and comparing both the number of requests per second and the average response time. Given that the options for generating XML, HTML and JSON were all so much easier than what we were doing in the servlet version, we were willing to live with the performance hit.

Proportional Code

October 26th, 2008

Few things are less sexy than command-line parsing. It is one of the most mundane tasks a programmer has to execute in their career. But, it surprises just how much code is required to do basic command-line parsing in a lot of languages, including Ruby. So I got to thinking, why does this bug me so much? I think the answer is that requiring so much code for such a relatively trivial task violates my sense of proportionality in the code. I hate having to say so much more about this teeny little task than I do about the “theme” of my code. I think it distorts the narrative of the code.

Let’s say that the processing of writing your program is like launching spacecraft. Ideally you would like to get from launch to cruising around in space as quickly as possible. The Star Trek universe solves this quite elegantly with the transporter. We don’t put you in a box and launch it, we break your atoms apart and transmit them to another location! That’s pretty cool, but maybe we’re just not quite that cool yet. Another solution is one proffered by the Star Wars universe. A ship like the Millenium Falcon can leave just about any planetary atmosphere any time it damn well pleases without the use of special equipment. It just flies away. Not bad.

Atlantis (STS-125)

However, here on earth, our primitive space craft need a tremendous amount of disposable apparatus to reach escape-velocity. The proportion of useful vehicle (the shuttle) to the orbit-busting mechanism (the rocket boosters and fuel tanks) is a staggering 5.4:1 (based on liftoff weight).

Command-line parsing in code exhibits a similar disproportion. The interesting part of your app isn’t the command-line parsing. Why should it take up such a disproportionate amount of space in your code? Those boosters quickly become “space-junk”, once the launch vehicle has left Earth; expensive trash that is never to be used again.

Space-junk is dangerous for the next guy that wants to launch into space. It’s also dangerous for the folks on the ground as it may decide to come crashing back down to earth. And those boosters have also been responsible for one of the worst disasters in NASA’s history. If we could only get rid of those damn things the whole space program just might be a little better off. Unfortunately physics, and our current space-flight capabilities currently require them.

But our code is a different story. We don’t have such physical barriers that handicap us. Any barriers we run into are usually of our own making. So why not try to reduce those as much as possible? Why say in more code, what you could say in less? Wouldn’t that cut down on bugs? Wouldn’t that ease the burden of maintenance? Wouldn’t that reduce the amount of information overhead you have to maintain each time you revisit that code?

Command-line parsing is a stupid, menial task that should require very little attention. By extension, it should only be given a stupid, menial amount of code to make it work. We have big ideas! They shouldn’t get bogged down by handling command-line options!

This is why I wrote Clip. Clip is an expression of the need to make the simple things simple, but no simpler. If you have modest command-line parsing needs, Clip rewards you with minimal investment. If you need something trickier, Clip allows you to say a little more to it and gain more benefits from it. You get to decide how much you want to engage—not the library.

This is one of the things I like about Ruby. The language is extremely flexible which gives me a lot of ways to “pack” ideas into code in a variety of ways. Having more than one way to do things isn’t all that useful by itself. But it’s essential when you want to write expressive code. Things like object literals, or one-line control-structure alternatives help me keep the lines of code proportional to the ideas they express.

This is also something I find challenging to do in Java. In languages like Java, even just creating a collection of objects requires quite a bit of code:

    1 import java.util.*;
    2
    3 public class Designer {
    4   public void makeItWork(List<Trash> trash) {
    5     // today's challenge: convert trash to wearable garments
    6     List<Garment> garments = new ArrayList<Garment>(trash.size());
    7     for (Trash t : trash) {
    8       Garment g = new Garment(t.getName());
    9       garments.add(g);
   10     }
   11
   12     submitToJudges(garments);
   13   }
   14 }

In Java we often solve this by pushing all of that code into a private method that is named something meaningful. This works pretty well, but does tend to result in an explosion of “helper methods”. Sometimes folks take the “cheap” route and simply prefix these riffs with explanatory comments like “convert each Trash into a Garment”. I’m not a real big fan of this. Generally I don’t care about the object conversion in the first place because the rest of the code is presumably doing something interesting with the Garments and I don’t give a damn about the Trash.

So let’s look at it in Ruby:

    1 class Designer
    2   def make_it_work(trash)
    3     submit_to_judges(trash.map { |t| Garment.new(t.name) })
    4   end
    5 end

By my count there are five lines in the Java example (including the comment) just to convert trash to garments. In contrast I boiled that down to one line in Ruby. OK I could have done this in two lines if you think that’s too much of a long-train. But I think there are couple of important points here:

  1. The importance of the concept being expressed diminishes from left to right
  2. The attention-span of the reader diminishes from top to bottom

The Ruby example beats Java on both counts. I don’t waste a lot of the reader’s attention span up-front on book-keeping details (in the vertical space) and I state the important thing I’m trying do (submit my top Foos) quickly (on the left). The details of which Garments I’m dealing with are merely a qualification of what I’m trying to do.

How you handle these two dimensions is greatly affected by both the language you use and the APIs you deal with. This is one of the reasons that I do not find the use of scripting languages for Java’s Swing API all that compelling. Scripting languages like JRuby or Jython help me with the horizontal space, but don’t do a damn thing for the vertical requirements. With an awful API like Swing I have to say a lot of words to make it go, regardless of the language I do it with.

Getting back to my dumb example, being on such a small scale this may not seem like a large impact. But multiplied several times over to match the size of most projects, this kind savings can really pile up. The difference in the amount of code required by these two approaches is manifested in a savings in cognitive investment required to grok these projects. This is the very essence of maintainability and sustainability. Anytime you can do more with less, you come out ahead.

At great peril to my own geek cred, I will say that this is why I find The Lord of the Rings to be such an awful piece of writing. It is so full of peripheral and non-essential information that finding the real story or characters requires extraordinary patience and concentration on the part of the reader. If Tolkien had been more concerned with the story and less with “world-building” I’ll bet he could have gotten that story boiled down to a single book.

Now I realize that a lot of folks love the Tolkien books for the very reasons I criticize it. That’s fine, that is an argument about aesthetics, not facts. However I would strongly argue that “world-building” in your code is a bad idea. I think you’re much more likely to build a decent piece of software if you pack your ideas tightly like a William Gibson novel than as a sprawling “trilogy” of epic code. Go ahead, prove me wrong. I double dog-dare ya.

OK, so by this point any credibility I may have had is gone. Look at the size of a post about saying more with less. In the hope that you might be lazy and like to skip to the end:

Do as much as you can…with as little as possible.

The Java Conundrum

December 30th, 2007

Steve Yegge’s latest blog post was one that really struck a chord with me personally. I think he hit most of the nail right on the head in describing a common frustration with the Java language. It seems like every attempt to refine the language ends up as some controversial, inelegant hack that often reduces the readability of the code. The same day I read that post I came across Josh Bloch’s presentation on Java closures. This was my first introduction to closures in Java-land and my first reaction was one of horror. This is supposed to enhance the expressiveness of the language? Sheesh, not as far as I can tell…

Steve talks about the size of your Java codebase and just touches on IDEs, but I’d like to explore that aspect a bit. I’ve been a dedicated Eclipse user for about five years. Before that I used NetBeans and before that Emacs. These days I think the three major IDEs (Eclipse, NetBeans and IntelliJ) are essentially equivalent. They all have great code completion, integrated refactoring tools and built-in unit-testing support. By the time I switched to Eclipse my Java projects were reaching a magnitude that required these sorts of tools. Switching back to plain old Emacs would have been possible, but a very counter-productive move. In essence, our projects mandate a certain set of tools in order to achieve some minimal baseline of productivity. There is no going back.

Maybe this isn’t a bad thing. I’ve certainly dismissed my fair share of kooks who live by the “desert-island” coding theory where any developer should be prepared to have to work on thirty-year old servers with no UI system and where only edlin is available. That’s nuts. We have evolved. BUT…is Java requiring additional evolution that we otherwise wouldn’t need? Like Steve’s point about dependency injection, are we creating new sacred cows whose existence is justified only by the requirements of working with Java?

I’m a big fan of dependency injection, but when I started working more seriously in Ruby I realized that it was a concept that had much less worth simply because of how the language works. So while the concepts behind projects like Spring are admirable, the amount of knowledge required to use these tools (all in the name of finding a shortcut around a bunch of manual work), seems to exceed any benefit as far as I can see. It seems that the evolution of Java has required additional complexity to manage the previous rounds of complexity we were trying to get around in the first place. A conundrum indeed.

Java seems to be suffering from a serious case of feature-envy and lacks a firm hand to guide its future. Java 5 brought a few helpful (and sometimes controversial) features, but since then I’ve started to tune Java out. The JCP process seems to have devolved into feature-addition-by-committee process where, if any sort of quorum can be achieved, any features can make it as a JSR. As other languages have gained popularity and offered developers alternatives in expression, many have tried to evolve Java to “keep up”. I would put forth that this is both a disservice to the language and its users.

Right, wrong or indifferent, Java has a point of view of how the world should work. Everything in Java is an `Object` and every object is of some defined `Class`. There are almost no literal expressions in Java so just about everything you want to do in Java must be carries out as methods invoked on objects. Many of the new language extensions seem counter to this original design and show all the signs of a conceptual impedance mismatch. Extensions like closures are trying to act like anonymous functions where we don’t really care about the type. Oh, except that we do. Well, but we don’t want to. Yeah, but we have to.

As a result, Java has evolved from a relatively simple and consistent language (at least compared to C++) to one that requires programmers to understand Java’s entire Tale of Gilgamesh before they can be trusted with the language. I can’t imagine how they teach how Java 6 works in introductory programming classes. Instructors must be faced with innumerable choices where they trade completeness for clarity. Given the tome-like size of the Generics FAQ, I can’t see how anyone could feel comfortable sicking this subject on the young tender minds of new programming students.

It just seems to me that whatever stewards there are for the Java language have been fairly hands-off in setting or restricting the direction of the language. Perhaps Java would be better off accepting the fact that it will, at best, play the role of an equal among a number of peers and that it would best sustain itself by adhering to its core design principles and allow other languages to evolve their features to meet needs that Java can’t adequately satisfy.

To paraphrase Chico Escuela, “Java has been bery bery good to me.” Java has sustained a nearly decade-long career in a profession I love. For me though, I’m pretty sure that my current gig will be my last Java gig. My attention to and love for the language has waned. I’ve found alternatives that work better for the majority of problems I have to deal with. In short, the thrill is gone.

There are few tools in my toolbox that are timeless must-haves. I am a self-described “tool whore”. If I can find a tool that gives me a significant amount of productivity gain (one that exceeds the investment effort), I’ll gladly switch to them. I was a long-time dedicated Linux user, but switched to Mac when I found that the effort to maintain a Linux laptop exceeded the energy I was willing to put into it. I haven’t rejected Linux, I’ve simply put it in a place in my technical life where I can best take advantage of it.

I feel the same way about languages. While I have called myself a “Java developer” for a number of years, I’ve come to learn that I’m really a software engineer whose tool of late has been Java. Given the constant change within this field, it is simply self-destructive to assume that I can sustain a long-term career with the same set of tools and skills. I firmly believe that a good developer has to be aware of what else is going on in the world and must constantly evaluate and adapt new technologies and approaches. In short, we must evolve or face irrelevancy and, ultimately, professional extinction.

Today I’m doing more Ruby and I hope to be doing more Ruby professionally for a number of years. But I expect that in a few years some new language will emerge that will address the future shortcomings of Ruby. Who would assume that any one tool/language/operating system has really got it right? It’s never happened in the history of technology. At best, we’ve had systems that did better than their competitors. I’ll even go so far as to say that I don’t dismiss the possibility that Microsoft may come up with an operating system or development environment that beats the alternatives. It would require quite a lot to overcome my personal biases, but I won’t say it couldn’t happen.

Posted in Java | 4 Comments »

Ten Things I Think I Think

October 16th, 2007

In the spirit of Peter King’s Monday Morning Quarterback, here are ten things that I think I think:

10. Maven 2 Moves The Ball Down The Field (well, sortof): All Java build systems suck. They all suck in different ways and the selection of one over the other is largely dictated by what types of pain you are willing to tolerate. I’ve used Maven since it’s inception. It solved some things Ant didn’t but also came with its own problems. Maven 2 attempts to solve some of the problems with Maven Mark I (namely scripting in XML, yecch), but lacks coherent documentation and a clear roadmap for learning the tool.

That being said, it makes tasks like creating a WAR file and deploying to a web server relatively trivial when compared with the amount of Ant XML you would have to write to do the same thing. There’s still too much XML for my liking and god help you if you want to do something outside of the box.

9: Maybe Static Imports Ain’t So Bad: When Java 5 first rolled around, I identified static imports as one of those features I would never use. Well, heh heh, never say never I guess. I have started to use static imports in a few places where I need something like the equivalent of a Ruby mixin. Interestingly enough the the only places I’ve felt comfortable with their use have been in unit-testing when I want to use EasyMock’s methods or JUnit 4 methods.

8: Java Annotations Are Curious Creatures: I can’t tell yet whether or not Java annotations are really all that great or not. If you’re a hard-core-no-good-thing-has-come-in-the-damn-JDK-since-the-collections-API kinda guy, you can make the argument that annotations are simply syntactic sugar for problems that could just as easily be solved with a proper object model or external configuration. In the old days (like the first version of EJBs) we wrote our configuration as actual code or, perhaps, as properties files. Then XML and Java went out on a hot date during the first dot-com bubble and spawned all sorts of illegitimate XML configuration children. I can’t tell you how many XML configuration systems I’ve seen that essentially reinvented properties files in XML (same configuration, twice the typing!)

Configuration via a pure object model can be, at times, extremely clunky (anyone remember writing EJB 1.0 deployment descriptors?) I think the evils of external file configuration have been experienced by just about any moderately experienced Java developer (Struts config anyone?) So it seems to me that annotations are simply a way to get some configuration closer to your code in something approaching a DSL (which most configuration files are attempting to be) without external files. I haven’t played enough with them to be totally sold, but the idea is intriguing…

7: I Couldn’t Code Java Without Eclipse: I say this not because Eclipse is just the greatest Java IDE of all time, but because I’ve invested so much time learning so many of its tricks. Really any modern Java IDE probably has equivalent functionality, so the issue is not so much that I can’t imagine coding Java without Eclipse, but rather that I can’t imagine coding Java with a plain ol’ text-editor. I don’t think this says as much about me as it does about the language itself. Does anyone doing Java professionally on a daily basis still use Vim or Emacs?

6: I Code Java, I Code Ruby. When Will I Use JRuby?: It’s funny that for as much Java and Ruby as I’ve done in the last eighteen months that I still have done no more than dabble in JRuby. The day can’t be far off, but I’m a little surprised that it hasn’t yet arrived.

5: I’m Tired of Algorithms: Well, that’s not exactly right. I’m tired of algorithms as the measure of one’s knowledge of software development. It’s important, but it’s not the most important. Apparently most of the software world doesn’t agree with me so it’s up to me to decide whether or not I want to continue swimming upstream or simply relax and go with the flow. Some little voice in my head tells that the latter is not a good idea…

4: I Think About Scaling All The Time: Aside from sustainable development, scalability is probably the most important thing I think about at my current position. I’ve worried about it before, but the scope of previous projects that I’ve worked on don’t approach the ambitions of this one. I’ve spent a lot of time in the last year reading up on all sorts of technologies around scalability. I’ve been pretty interested lately in things like the Spread Toolkit and Wackamole. I haven’t used them yet, but I’m keen to try them out. I’ve been using Jini lately…the jury’s still out on that one.

3: RDBMS Is Dead! Long Live RDBMS! Part of the result of all this scalability reading and thinking is coming to the realization that a relational database doesn’t work everywhere as the be-all, end-all of persistence. To that end I’ve been immersing myself in a number of different technologies. Inverted indices provided by the likes of Lucene or Ferret are fascinating alternatives to the traditional RDBMS approach. If you twist your brain the right way you can satisfy most requirements you would have of an RDBMS with inverted indices.

Similarly various key/value databases such as CouchDB and even Sleepycat make very sensible replacements for a general-purpose RDBMS. I find these interesting not so much because of their performance characteristics viz-a-viz RDBMS solutions—though that is certainly compelling—but rather because of their simplicity. For a lot of problems I really only care about storing and retrieving heterogeneous data via simple keys. Why make it any harder than that with a traditional relational column/row structure?

2: I’m Going To Ask Erlang Out On A Date: Erlang has gotten a lot of hype (and criticism) lately. Normally the simple churn of the blogosphere isn’t enough to get me interested in some johnny-come-lately, but Erlang strikes me as something with a little more staying power than the normal flavor-of-the-month technology. Perhaps it’s the track record as being “carrier-grade”. Perhaps it’s the move by some towards functional programming for solving particular problems. This, in particular, fascinates me. I’ve been an object-oriented guy for a long time, but there have been occasions when the OO approach seemed a little obtuse, but I didn’t really have a good alternative. I’m hoping that the process of learning Erlang will be a great foil to “get” functional programming.

1: I Think The OLPC Project Is Brilliant: I can’t think of a project that embodies more of the things I value than the One Laptop Per Child Project. It’s about putting the right amount of technology in the hands of kids. It’s about giving them a sturdy playground where they are encouraged to learn through experimentation. It’s about building sensible collaboration so that students can learn how to achieve more together as a group than they could as individuals. It’s about choosing and using a tool that gets things done. It’s not about learning a particular platform and it’s not about market-share.

I signed up for the Give 1 Get 1 program, but I can’t really justify having my own OLPC laptop. However I may get one just to play with it for a few days and then find a worthy home for it. I can’t imagine a better way to empower a kid than to put a tool like this in their hands.

The Ache of Swing Programming

September 7th, 2007

As I type this post, I have to fight every urge to grab my hands in agony and cry out like a hurt child. This hand-ache is not unfamiliar. I realize that my hands have always felt like this anytime I’ve had to do some Swing programming.

Why does it have to be like this? Because Swing requires just so much damn typing. My lord my fingers are buzzing with a solid week of keyboard contact. Swing is a tremendously verbose API—it simply requires a lot of letters to make it go. I consider myself a pretty advanced Eclipse user who takes advantage of most of its features to let it write my code for me, but my hands still hurt. I shudder at the thought of having to code Swing like I did “back in the day” with good old Emacs.

I find it interesting that demonstrations of Java code being called from a scripting language (JRuby, Jython, Groovy, etc.) always include an example of rapid GUI prototyping with the Swing API. I say this because I think that while these scripting languages really beat Java in terseness, they don’t really help much when dealing with Swing. In other words, a scripting language may reduce the length of a line I might otherwise write in Java, but the sheer number lines I have to write is about the same. I don’t think this is an indictment of scripting-wrapped-around-Java so much as what it says about the Swing API itself.

The other reason Swing wears your hands out is that it is not a well-designed, intuitive API. You spend a lot of time experimenting to figure out the magic recipe that will make your app work. Despite the verbosity of the API docs and various Swing Tutorials, I find that I still have to play (nee fight) with the API to figure out how to get it to work.

Take, for example the juggernaut that is the JTable. I wanted to have a JTable instance update with new rows when the underlying model changed. I wanted to set a custom renderer for one of the cells to display a URI as a hyperlink and allow the user to click it and view the URI in their browser (via Desktop.browse(URI)). OK, let’s see here, let’s go to our IDE and put the cursor next to our JTable instance variable and trigger the autocomplete drop-down. Hmmm, what can we use here? Oh here, we go, setDefaultCellRenderer, hey that looks good. OK, let’s see, takes a Class and TableCellRenderer, yeah that looks good. Alright, let’s fire it up…wait for the VM to get warmed up…load our data model…click the table and…aw hell, a NullPointerException during table painting. OK, let’s go through the stack trace and look for one of my classes in there. I must be passing some null reference around. Hmmm, no…actually these are all Swing and internal classes. Great, now what?

Eventually I worked out that the problem is that despite the plethora of options for cell rendering, only one combination worked in my particular case. Only by trying every square in the Swing-API-matrix was I able to stumble upon a combination that worked correctly. Now I will admit that my Swing skills are a bit rusty and that I have to blame myself to a certain extent. However my big beef with Swing API is that it gives you so many ways to hurt yourself in spectacular and unintended ways. Looking at the API and its base-classes with 200+ methods, it’s pretty clear that the API was developed from the implementation on up. Any design with regard to usability seems to be an afterthought.

I feel like whenever I’ve had to work on a Swing project, I have to change my whole approach. It’s much more difficult for me to cull decent unit-tests out of the code. In part this is because it’s so easy to embed testable code inside of un-testable code (think of event handlers), but also because UI testing is difficult. Even the various UI-oriented unit-testing tools don’t really enable easier unit-testing so much as make it barely possible.

Despite all of this and the persistent ache in my digits, I can’t say I didn’t have any fun with this. I’ve always said that programming Swing is a bit like riding a mo-ped, it’s fun for a bit but you would never want your friends to catch you doing it.

Posted in Java, Rant | 2 Comments »