Monday, December 22, 2008

Visualizing Maven

It'd be interesting to visualize the modules, parents and dependencies of a multi-module build using something like GraphViz or Structure101g.  M2Eclipse does a good job of this on a per-module basis, but nothing to handle multi-module builds.

Thursday, December 11, 2008

Maven Resource Filtering Bug - Property Prefixes Ignored

There's a problem with Maven resource filtering whereby the property matching seems to ignore prefixes during the filtering. As a result, you might have ${mySpecialProject.url} get replaced as if you'd said ${pom.url}.

This is weird, and irritating; it's occasionally bit us. I tracked down the related bug today in the Resources Plugin issue tracker and I'm filing it away for future reference. If you're hitting this, you'll want to upgrade your resources plugin to 2.3, sounds like.

Tuesday, December 9, 2008

Google's Native Client - Technology In Search of a Purpose

Google's Native Client seems like a step in the wrong direction for me.  It's an interesting technical challenge to securely run native code from unknown sources, and I could imagine that it's a challenge worth pursuing to some degree.


However, in the long run, it seems like we've made enough progress with virtual machines to stick with that approach.  Running x86 code in the browser just reduces the number of platforms on which you can run your code.  While X86 is certainly the dominant platform, I'm inclined to think we're better off staying at a level of abstraction from the operating system and the hardware when writing code to be distributed over the internet.

That said, i'm willing to let the market sort it out; this seems like interesting technology, and if it ends up being heavily used, then that implies that it had advantages worth pursuing.

Tuesday, November 11, 2008

Clover Test Optimization

The new Clover 'Test Optimization' feature seems pretty appealing.  Using coverage data, Clover can determine which tests need to be run to cover the changes you've made, and then run these (or run these first), such that you can get your testing done faster and/or fail faster. 

Thursday, November 6, 2008

Google AppEngine Syntax Errors with CRLFs under Cygwin

I've had a frustrating patch using Google App Engine lately.  Trying to use minidom under Windows was giving me an import error -- possibly I needed to find a way to install expat?  I installed python via cygwin to see if that was any better, in part because I could see that libexpat was a viable option under cygwin, and in part because I was sick of Python not understanding my Bash-style paths.


That solved the problems with Minidom, but then I suddenly started getting syntax errors on perfectly reasonable (and previously operational) import statements, which was pretty frustrating.  After a few false starts, I discovered that some Mac/Python users ran into similar errors when using GAE on Python scripts that had Windows-style CRLFs instead of simple line feeds.  I switched the line terminators in Eclipse, and voila, problem went away.

The issue report I found is closed, but i've commented in the hopes that the fix can make it into GAE for Windows for those of us using Cygwin.  i'm looking forward to replacing this half-dead laptop with something better that will run Linux or OS X in the near future.

Sunday, November 2, 2008

Google App Engine: REST, Frameworks, Lock-In and Agency Work

I've been doing a little experimentation with Google App Engine for a minor side project, and in the process of so doing, I've been discovering that App Engine seems reasonably well-suited for delivering a RESTful application.  I'm not ready to talk specifics or open-source the codebase for further examination, but I may get there.


In some ways, App Engine seems lower-level than I'd thus far; simple things like binding a URL to a template can't be done without a bit of code.  It seems like there's room for the framework to get a little thicker to cover the most common cases.  In essence, if enough people were going to use App Engine, I think there'd be some value in an App Engine framework.

Unfortunately, the primary problem is still this one: if you're building a long-term application that you expect to use and maintain, then doing it on someone else's infrastructure over which you have very limited control is a risky strategy -- you're making Google a silent partner in your business.   Google's a better partner than most vendors, I imagine, but it's still a pretty big leap of faith.

I'm curious App Engine would work in an agency environment where you're developing relatively short-term projects, where the infrastructure is rarely under your control, and where tying the ongoing costs to actual usage might make a lot of sense.  It's possible that this kind of approach might even be a differentiator for some agency work.  Anyone doin' it?

Friday, October 31, 2008

Configuring Cargo/Tomcat with Maven2

Commenting on my last post, Rob Sinner asked, "Can you post the pom.XML your using to launch cargo[?]"  I haven't had the problem he described, but I don't mind sharing the configuration I use.


Basic Cargo/Tomcat Configuration
A basic cargo/tomcat configuration adds the cargo plugin to your build plugins. If you place this within a WAR module, the module in which the cargo plugin is defined will be automatically deployed with no extra work on your part:

<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.0-beta-1</version>
<configuration>
<container>
<containerId>tomcat5x</containerId>
<zipUrlInstaller>
<url>http://www.apache.org/dist/tomcat/tomcat-5/v5.5.27/bin/apache-tomcat-5.5.27.zip</url>
</zipUrlInstaller>
</container>
<configuration>
<home>${project.build.directory}/tomcat5x/</home>
<properties>
<cargo.servlet.port>${servlet.port}</cargo.servlet.port>
</properties>
</configuration>
</configuration>
</plugin>
To fire up cargo, simply enter:
mvn cargo:start
To exit, press Ctrl-C.

Integration Tests
You can configure Cargo to start before the integration test phase and shut down after the integration test phase. This is useful if you have automated integration tests that you'd like to run against your in-container application. It's as simple as binding the cargo goals to the correct lifecycle phases:

<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<wait>false</wait>
</configuration>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>

Deploying Other Modules
In some cases, you'll want to deploy one or more modules that aren't the project you're in. In this case, you'll want to define deployables explicitly inside the cargo configuration:

<deployables>
<deployable>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-alpha</artifactId>
<type>war</type>
<properties>
<context>alpha</context>
</properties>
</deployable>
<deployable>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-beta</artifactId>
<type>war</type>
<properties>
<context>beta</context>
</properties>
</deployable>
</deployables>
Debugging
If you want the option of connecting a remote debugger to tomcat after firing it up via Maven/Cargo, I'd suggest a profile.  This is what we typically use:

<profile>
<id>cargo-debug</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.0-alpha-6</version>
<configuration>
<configuration>
<properties>
<cargo.jvmargs><![CDATA[-Xdebug -Xrunjdwp:transport=dt_socket,address=15102,server=y,suspend=n]]></cargo.jvmargs>
</properties>
</configuration>
</configuration>
</plugin>
</plugins>
</build>
</profile>

You can invoke this using:
mvn cargo:start -Pcargo-debug

Alternatives
There's also a Maven Jetty Plugin which has a pretty good reputation.  Unfortunately, there are currently two plugins with the jetty prefix, one in the mojo repository, and the other from mortbay.  The former takes precedence for me, whicih makes using the Mortbay version painful.

Thursday, October 30, 2008

Maven 2 Cargo Plugin: Version-Hell

I'm working on a small architectural spike, and I want the ability to run my WAR project in a container.  In past projects, I've configured Cargo's Maven 2 plugin to launch Tomcat, both for manual testing and for integration tests.  While I don't really need integration tests on this spike, I prefer to have the build-integrated option to launch a container rather than deploying the WAR to a container manually.


Maven 2 is Configuration-Over-Convention: configuring Cargo for a Maven 2 build takes a page of XML.  Rather than compose it from scratch, I just grab it from past projects.  After doing so, I refine it for any project specifics, and while I was in the fancy m2eclipse dependency editor, I did a quick check to see if 1.0-alpha-6 was still the current version.  Seem's not -- the dialog shows me that there's a 1.0-beta-1 version available.

I prefer to use the most recent version unless there are significant changes, so I thought I'd best check to see what's changed, only to discover that getting that information is nigh-impossible:
  • The home page lists the 'current version' of the Maven2 Plugin as "0.3", despite the fact that that version is a year old, and there's been a series of alphas and now betas since then.
  • The 'news' section is even older, showing that 'Version 0.2' of the cargo-maven2-plugin has been released, same as the announcements mailing list.
  • Although Cargo seems to use different version numbers for its various components, their Jira is configured with a Cargo project and the Maven2 plugin as a component.  In order to address the overlapping version space, they've created versions like 1.0-maven2.
If anyone knows what changed from alpha-6 to beta-1, please feel free to comment.  I give up.

XOM and Jaxen Transitive Dependencies with Maven

I briefly looked at using XOM to do some XML parsing in a Maven 2-built Java project this afternoon, only to discover that XOM has a transitive dependency on Jaxen and Jaxen has a transitive dependency on all of DOM4J, JDOM, Xercse and XOM again.


This is frustrating.  Seems to come from the fact that the Jaxen team didn't build Jaxen's POM (JAXEN-138, JAXEN-151, MEV-413), and nobody else wants to take responsibility for it.  

The longer-term fix is the thought (July, 2006) that Jaxen might move to Maven 2.  I'm quite tempted to volunteer for that port simply to solve this problem for me in the future.

Wednesday, October 29, 2008

Mortal Life as Sorting Algorithm

I was thinking last night about some amalgam of traditional religion, while waiting for my wife to emerge from an event being held in a church. Pierrette to come out of a La Leche League meeting in a Unitarian church.

Imagine that in a vaguely Catholic-like way, mortal life is simply a classification system for people (or souls). A giant sorting machine at the beginning, very brief in the grand scheme of your existence. And that, basically, when you're done being sorted along with your fellow mortals, you spend the rest of your existence in the company of your equals, in tiers.

So the reward for being good on earth is spending your time with other people who were good, and the punishment for being a d*ck is spending eternity with other d*cks. The golden rule isn't so much an exhortation as a tip for finding the right tier in your afterlife: "Do unto others as you want others to do unto you for the rest of your very, very long post-life existence."

After beta trials, God notices that some people attempt to game the system. Like any good game designer, Allah realizes that he needs some special tiers for those people who are gaming the system. In the same way that a video game might have an invincible mode that is completely out-of-proportion difficult for those who've already finished the 'hard' level with all their ammo and never having been hit, The Earth Mother realizes that those maximizing for altruism beyond all expectation deserve a special tier to be called Heaven, and that those who maximize for self-interest at any cost should have a special tier called Hell, where the reward and the punishment is also more than simply being sorted with your peers.

Unfortunately, the publicist screws up and the media take the sensationalist points and only covers Heaven and Hell, leaving out the important salient points about how most people will get sorted.

Tuesday, October 28, 2008

Demand for iPhone Developers up Infinite Percent

Since the iPhone was introduced, demand for iPhone developers has skyrocketed to infinity when compared to the previous non-existent demand.  Now that the iPhone has been released, it seems that some people occasionally want to hire people to develop for it.  Truly stunning news from the Apple Blog.


Is this really news?  Of course demand for development in a totally new technology is showing significant growth.  That's true of any technology that's seeing any real new adoption, and it's certainly true that the iPhone falls into that category.

Wednesday, October 22, 2008

Living in the Shadow of a Non-Factor

From Managing Humans, by Rands:

The organization's view of your manager is their view of you.  I'm glad you're a C++ rock star, but the problem is, your manager is passive non-communicator who doesn't take the time to grok the political intruigue that's created by any large group of people.  I see him as a non-factor and you're living in the shadow of a non-factor.
I've seen that very thing happen. 

Tuesday, October 21, 2008

Katamari Damacy Garbage Art

Look, Katamari Damacy visits the dump to create as Art.

Monday, October 20, 2008

Experimenting with jQuery

I've done a little experimentation with jQuery while building out geoffreywiseman.ca.  I've been meaning to get a little deeper into AJAX and jQuery was one of the libraries that appealed to me.  It went pretty well for the most part, although I'm not yet sure if it took me less time to learn jQuery than it would have taken me to do the work by hand with JavaScript.  Seems pretty powerful as a library, though.


I did some experimentation with jQuery animations, but quickly discovered that it wasn't going to do the job for me -- you can roll over the icons faster than the animations typically run, and it's very difficult to get a set of animations happening in sequence, cancelling each other without tripping over your own feet, so I dropped the animations.

Even then, I was pleased to realize that I could accomplish this all in presumably cross-browser code without having to test in all these browsers.  Out of curiosity, I fired up IE7 this morning, only to discover that although the site works well in Chrome and Firefox, it's got problems in IE7. 

Ah, browsers.   Can't code web-apps without 'em, can't kill the vendors who wrote such incompatible clients without getting arrested.  This is one of the things that had me focus on server-side code for most of my career.  I'm hoping there's an easy fix.

Saturday, October 18, 2008

Movin' On ...

Well, the writing's on the wall for my current employment.  While I'm not moving on right away, it's time to start keeping an eye out for anything interesting.  In many ways, that's just more of the same, since I do that for Toronto Technology Jobs.


In the meantime, I decided this was a good opportunity to resurrect a personal site, so I've been getting the basics together up at geoffreywiseman.ca.

If you're looking, or know someone who is in the Toronto area, drop me a line, either because you're interested in having me take a look for TTJ or because you think I might be a fit.

Tuesday, October 14, 2008

Eclipse Update Problems: No Repository

So recently when trying to update just about anything in Eclipse, I've been getting errors complaining about "no repository found for..."  I ignored this a few times assuming it was some kind of weird transient error, but it hasn't gone away, so I did a little more digging.


Turns out this is a relatively common occurrence in recent versions of Eclipse, there's a bug they're having trouble reproducing, and the simple workaround at this point is to remove and re-add update sites that are giving you problems.

Worked for me; hopefully raising awareness will help some of you.

Thursday, September 25, 2008

AJAX via XMLAsynchronousMessage

It seems to me that much of the interactions that take place over a relatively synchronousAJAX XMLHttpRequest could just as easily have been modelled as asynchronous messages.


Now, I'll grant that async messages have been hampered by not using a common wire protocol (e.g. AMQP), and that browsers are fundamentally HTTP clients, but I wonder if an event-driven asynchronous model would have made more sense in the long run?

CentSpring: Community Enterprise Spring Framework?

If Spring is going to stop putting out maintenance releases to the community at large after either three months or when the next release is out, do we simply need another organization to look at the maintenance branch and bundle up the work for us?


In essence, CentOS is to RedHat what X is to SpringSource.  Solve for X.

Tuesday, September 23, 2008

Agile Office Furniture

When looking at systems furniture or other corporate furniture, are some better-suited to agile techniques than others, including pairing and pair-swapping? I was just looking at the Kimball Hum desk, which is appealing in some ways, although it still doesn't match the truly mobile solutions where you could have a workspace but move it around easily (Herman Miller used to have a desk I really liked in that respect, although I haven't seen it recently).

I also have fond memories of using a Huddleboard.

I'm curious if some of you have recommendations with respect to furniture that's worked well for you.

Thursday, September 4, 2008

Scala in Eclipse

Last time I looked at Scala, I quickly stumbled over the nascent support for Scala in Eclipse and found that I didn't have the energy to work with a JVM language that didn't have good IDE support.  It's been a while since then, so it seemed like a good time to look at Scala again and see how support for Scala in Eclipse has improved.


Installing Scala in Eclipse
Installing Scala in Eclipse was pretty easy.  There's a documentation page covering it, Eclipse 3.4 (Ganymede) is supported, so I added the update site, installed, restarted Eclipse, and voila, a Scala perspective, as shown on the Scala site:

Hello, World
Following along with either the Eclipse/Scala plugin page or with the default tutorial, I tried creating my first Scala "Hello World", and immediately started hitting minor hiccups again.  

First of all, starting strings often highlights the open quote with an error indicator that doesn't go away when you close the string.

Secondly, there's no shortcut for running a Scala application.  Alt-Shift-X brings up the usual menu with no addition for Scala.  Likewise, you can't "Run As > Scala Application", another normal way to run an application in the Java development tools.  Your only option is to go into the run configurations dialog, create a new run configuration under Scala Applications and enter the class to be used.

Further confusion sets in within the Run Configuration dialog, where there's a Browse button to search for a main class, but the HelloWorld object I've created doesn't show up in the dialog that results from pressing this button.  As a result, if I type in the fully-qualified name of the object, the run configuration works, but it's fairly painful to reach that stage.

Interaction with Java
Continuing with the tutorial, I start the stage of interacting with Java classes.  Although the typed-out examples show import statements, I'm used to these import statements being generated by the IDE in Java, so I decide to omit them.   The Date type and getDateInstance methods are highlighted as being not found, although the warning information that appears when you hover over the error is both simpler and uglier than the Java equivalents, and incorrectly sized for the text, so scrollbars appear.  There are no quick fixes available, so it seems likely that I'm going to have to enter the imports by hand.  I do seem to get autocompletion on the imports, which makes entering these less painful than they might have been.

Having completed the import statements, the Scala editor is now aware of the Date instance, but seems to have failed to notice that getDateInstance() is overloaded; it's complaining that I'm offering up (int.Locale) to getDateInstance().  The code still runs when the run configuration is executed, but the editor is blissfully unaware of the successful compilation of the code, and continues to present the getDateInstance() method as being in error, even when I take it out and put it back in.

Second First Impressions
Well, this is my second time checking out Scala on Eclipse, and my first impressions this time around is that there's still a ways to go before Scala in Eclipse approaches the polish I'd like to see.  It's certainly better than when I last looked, but I'd still be tempted to take a look at the support in IDEA and Netbeans before sticking with Scala in Eclipse.

Tuesday, September 2, 2008

Google Chrome Well-Funded

If you think about it, Google should have no problem funding Chrome. With Firefox's small but growing share of the search engine referrals, they're already paying them $55M a year. If Google were able to take over some segment of that market share, they wouldn't need to pay themselves referral fees.

Now, I'm not saying that this is a move on Google's part to take away Mozilla's market share and funding -- I doubt that's a huge factor in their mind. It's not like they can't afford to pay for these kinds of projects in other ways, and there are lots of good reasons for them to pursue the browser as an application delivery platform.

That said, it's interesting to realize that this can, to a certain extent, pay for itself, if it's successful enough.

Tuesday, August 19, 2008

Staying Flexible: Develop in Another Environment

I've been doing a little work on a Firefox Extension lately, and I've gotta say, it's stretching me in very different ways compared to the development work that I usually do. That's true of any environment that's new to you.

In any environment where you do a lot of development, you reach a point where everything is either pretty clear, or at least pretty familiar. It's true that I've never written a line of Struts code, but having done work in several other Java web development environment, I'm pretty sure that I could pick up Struts with a minimum of confusion.

The same isn't true of building a firefox extension -- I don't have a broad knowledge base to fall back on. It just took me about an hour to get a shortcut key added to a sidebar, even with a working example, and I'm still not entirely sure how working bit of XUL differs from the original bit of XUL that wasn't, for reasons unknown, working.

While it's a little frustrating not knowing what I'm doing, and wishing the documentation were better, at the same time, I'm inclined to believe that doing some work in another environment is good for me, increases my flexibility, and my sense for the available options.

Monday, August 18, 2008

PURE + AJAX + REST + JSON Web Framework

I am imagining a web framework that delivered static HTML which made data requests to the server using AJAX to REST services that returned JSON, which were mapped into the HTML using PURE.

I'm curious to see what working in that kind of structure would be like. Seems very tightly compartmentalized, quite possibly in a good way.

In particular, I'm not totally sold on the idea that interleaving application data with HTML on the server-side is the right approach - sending down a clean, cacheable template of HTML (possibly still generated on the server-side to put components together and so forth), and then sending down a really thin data representation and having the client interleave the two seems appealing, and I haven't yet worked with a web framework that goes in that direction.

Apache Geronimo, Still Interesting, Still Troubling

I tried Apache Geronimo a little bit in the 1.0 era, mostly just to see what all the talk was about. It looked like it had some interesting concepts, but had a lot of rough edges, and for the most part, I get along with simple web containers like Tomcat, so I stopped playing with it.

I recently had the need to fire up an integration test with a web container and messaging queue, so I thought I'd try Apache Geronimo again, see if it was the right tool for the job. So, Wednesday morning, I took a quick peek at Cargo's integration for Geronimo, and decided it was unsuitable, then spent the remainder of the day with the Geronimo plugin. There were a few minor documentation warts, nothing serious, but enough to delay me 'til mid-morning on Thursday while I sorted it all out.

By Thursday end-of-day, I had a Maven configuration that would start up Geronimo before the integration tests and tear it down afterwards. That seemed to work fine, but deploying our applications to Geronimo didn't.

I took the first part of Friday to re-verify that Tomcat 6.X and ActiveMQ could, independently of Geronimo, deploy and functionally test our modules, and, yes, they could. The rest of Friday was spent trying to make Geronimo do the same, either geronimo-jetty6-javaee5, geronimo-tomcat6-javaee5 or a custom assembly. Every configuration we tried had some subtle inability to either deploy or startup several of our modules.

Now, I can't blame Geronimo outright -- I don't know what the problem is, there could be some issues with our WARs that don't show up in our usual deployments, or some problem with one of the many modules that Geronimo includes, but ultimately, if it takes more than a day to deploy a few WARs in an application server, I'm starting to be a little concerned.

Geronimo has some interesting ideas, but I end up feeling like it still has too many rough edges for me. Maybe I'll try again with 3.X?

Tuesday, July 22, 2008

Matias Tactile Pro

The Matias TactilePro page says boldy:

Built like a tank.
The Tactile Pro Keyboard is built to last, and comes with a 5 year warranty.
I'm not sure any keyboard I've ever owned has died within five years. Generally, keyboard are trouble-free, as long as you ignore all the crud that gets trapped in them, especially if you have animals that shed. If you really want to be seen as standing behind your product, you'd have to do a lot better than that to impress me.

Maven Makes Developers Feel Stupid

Although Maven has its benefits, its documentation is often spartan and scattered, and sometimes it can be quite painful to figure out how to accomplish a task, although once you've figured out how to do it, it's usually not terrifically hard to repeat it in the future.

A recent post to the Maven list just classically typifies this, for me: "How to use EAR plugin? Am I stupid?" Yes, sometimes Maven makes you feel stupid. I'm inclined to believe that's often Maven's fault, not the developer's.

Thursday, July 17, 2008

Matching JAXB Dates in Tests

If you find yourself wanting to correctly generate the date format used by JAXB, most likely in test code, you might find yourself messing with an XMLGregorianCalendar doing something like this:

        GregorianCalendar gregorian = new GregorianCalendar();
        gregorian.setTime( date );
        XMLGregorianCalendar xml = DatatypeFactory.newInstance().newXMLGregorianCalendar( gregorian );
        return xml.toXMLFormat();

If you do, you're likely to get bitten by the fact that on dates with 0 milliseconds, your method will include the milliseconds and the JAXB output will not:

expected:<2008-07-16T15:15:51[]-04:00> but was:<2008-07-16T15:15:51[.000]-04:00>

As a result, you'll want to employ code more like this:
        GregorianCalendar gregorian = new GregorianCalendar();
        gregorian.setTime( date );
        return DatatypeConverter.printDateTime( gregorian );

Et voila.

Wednesday, July 16, 2008

JBoss Effect and Hibernate Session.connection()

Sometimes it seems as if there's a JBoss effect wherein developers, once they've become a part of JBoss, become somewhat arrogant and rude in dealing with some members of their community. At first, I thought this might be the Marc Fleury effect, but he's gone, and JBoss seems to still have the same effect at times.

Case in point is the recent deprecation of Session.connection() in Hibernate and the tone of the responses here (Google cache version if Atlassian's still doing maintenance) and here.

Now, granted, the method is deprecated, and the deprecation comment implies that it will be replaced in the future with new methods. That said, the comment neither talks about the dangers of using connection() nor talks about alternative approaches that could be taken, both of which are common in deprecation Javadoc, and both of which would likely have reduced the volume of questions they were going to field.

And, frankly, if the best you can do to "help" the community is to respond with brusque, unfriendly comments about said member's ability to read and/or interpret the rather spartan documentation on this point, perhaps you should just stick to coding, instead of "helping"?

I will point out that another thread, About 3.2.4 and Deprecated function, generally stayed in the informative and polite zone, mostly due to max. Thanks, max, it's nice to see. So if you want to know why Hibernate 3.2.4 is deprecating Session.connection(), read that thread instead.

Wednesday, July 9, 2008

TweetDeck vs. Spaz

I've spent part of the day witih TweetDeck after weeks with Spaz, and have come away with some comparative notes.

Spaz

  • Simple tabbed single-column layout.
  • Works well with the keyboard, allows you to scroll up and down, lightly greys items you've previously looked at.
  • Scrolls pretty smoothly.
TweetDeck
  • Single or multi-column layout.
  • Multi-column layout looks a little lame when most of the columns are empty.
  • It's nice to be able to separate replies from the rest of your incoming messages.
  • The ability to group people or have a few searches up at once seems handy, although I didn't use either, and I'm not sure how often I would.
  • Feels jumpy when scrolling, easy to lose your place.
  • Not well-suited to keyboard scrolling and difficult to know which items you've already read.
Basically, these are both reasonable clients with different strengths; if you need to organize your tweets, I imagine TweetDeck is your choice.  If Spaz' simple layout will work for you, I find it a little more usable right now.

I've also played briefly with twhirl, but so briefly that I don't really feel qualified to comment.  I found the skin to be more noisy and cluttered, so I quickly went back to Spaz.

Tuesday, July 8, 2008

Command-Line Parsing Libraries for Java

I've recently had the need to do some command-line argument parsing in Java, and so I took the opportunity to quickly evaluate some of the command-line parsing libraries that are available for Java.  After looking briefly, the following options seemed to be relatively well-known:

  • args4j
  • JewelCLI
  • jArgs
  • Commons CLI
args4j
Of the options, I spent the most time with args4j; it seemed to be relatively modern, it was available in a Maven repository, it was written at least in part by Kohsuke Kawaguchi, whose Hudson project seems to have turned a lot of heads.

Most java.net projects have pretty weak websites and documentation, I've noticed.  The args4j project is no exception.  It has a sample page, a blog post and some javadoc, and if you piece all three of those together, you'll basically have enough information to get started, after which you'll occasionally have to dive into the code.

I was able to make this work for me, but it lacks most of the bells and whistles that I had hoped adopting a third-party library designed for this purpose would provide.  Args4j will not easily:
  • Limit the number of arguments
  • Restrict arguments to matching arbitrary rules like regexp pattern-matching
  • Display great help for the available options (it has usage, but it seems to leave out information like whether or not an option is required)
Although I haven't dug through the source code in detail, it doesn't look to me like there's a very complete suite of tests.  That doesn't matter if the code is solid and the documentation's good, but with the gaps in the documentation, some tests would have helped to make things a little easier to understand.

JewelCLI
JewelCLI has a pretty spartan (Maven-built) site, but seems to have good functionality and clear, if simple, documentation by example.  As far as I can tell, it isn't available in any Maven repositories, which is too bad because it seems to be built with Maven and, at first glance, I'd say it looks slightly more capable than args4j, and it seems to have a full test suite, although it doesn't look like anything's changed much recently.

It's another anotation-based implementation.  It uses an interface instead of a class, which has pros and cons.  It's vaguely fun because it allows them to implement some simple things under the hood like interrogatory methods for optional parameters.  That said, args4j's class approach gives you the flexibility of putting the behavior inside the same class as the data, if you choose to accept that option.

jArgs
jArgs seemed like it might be reasonable, but the last release was in 2005, the site is sometimes unresponsive, preventing you from looking into it in more detail, the implementation seems like more work to set up - programmatic configuration instead of class-based or interface-based reflection/generation.  Ultimately, if I can't get to the project consistently, I tend to take that as an omen.

Commons CLI
Apparently the oldest of the options here, and doesn't get a lot of respect from commenters, so I didn't really look at this very closely..

In Summary
I ended up using Args4j for now, but I think I'd use Jewel CLI next time, and if it works out as well as it seems at a distance, probably stick with that. 

This is also a good time to point out that Java's console programming model is pretty limited.  Key bindings?  Clear screen?  Move around?  Nope, sorry.  There seem to be third-party tools to get you there, but the core console functionality is basically suited to log output and the occasional thin piece of input.

Taylor Gautier looked into some of the before, if you're looking for further comparisons.

Tuesday, July 1, 2008

Disabling Menu Items: Gruber/Spolsky

Joel Spolsky takes a stand against disabling menu items, arguing:

Users see the disabled menu item that they want to click on, and are left entirely without a clue of what they are supposed to do to get the menu item to work. Instead, leave the menu item enabled. If there's some reason you can't complete the action, the menu item can display a message telling the user why.
John Gruber returns fire with the pro-disabling-menu-items argument:
This is why Spolsky is a Windows developer, not a Mac developer. Disabling menu items when they can’t be used is a fine practice — it means that the visual state of a menu item reflects the actual state of the command it represents. ... Spolsky’s suggestion — that you leave all menu items enabled all the time and show an alert when they’re chosen but can’t be used — would be irritating as hell every time you ran into it.
Spolsky’s suggestion is also predicated on the assumption that the user is stupid. Better is to assume that the user is clever and curious and will be able to figure out for themself why a certain command is currently disabled.
As with most polar arguments, this is a false dichotomy: there aren't simply two choices here. Yes, it can be confusing to see menu items disabled and not know why. Yes, it can be irritating to see menu-items enabled even when they can't work, such that triggering one will result in a warning dialog. But there may be ways to solve both problems. For instance, what about disabling menu items but allowing those disabled menu items a way of communicating the reason for which they're disabled where a confused user an learn more. We can assume the user is clever and curious without forcing them to dig through help and experiment to answer the question. For instance, some kind of a tool-tip on a disabled menu item could probably be done. It sounds vaguely ugly, but there's probably some way to make that work. On a windows window, where you're pretty much guaranteed to have a status bar, the message could easily be displayed there. On a Mac, where you might have a menu and no window at all, something like a tooltip seems like your only available choice.

Monday, June 30, 2008

I'm One-Dimensional?

Wow, I guess my use of del.icio.us is pretty near one-dimensional.  Either that, or I'm pretty near one-dimensional.  I prefer the former.  ;)



(via silk and spinach)

Sunday, June 29, 2008

Why Hiring Technologists is Difficult

I've just written up a brief post applying Malcom Gladwell's mismatch problem to hiring people in the technology sector for Toronto Technology Jobs. Since it's not Toronto-specific, I thought I should share it here with some of you here.

Wednesday, June 18, 2008

The Pitfalls of Technology-Driven Architecture

Software architecture is about technology, and it's nearly impossible to talk about software architecture without talking about technology. But software is meant to serve the needs of a particular set of users, to solve the problems in a particular domain. Likewise, the architecture of a particular piece of software should be intended to solve the problems that face the software within a particular domain. Architecture is driven by business need.

Architecture is Driven by Business Need
For instance, the domain of mass-market internet search requires searching for words within a vast quantity of data, returning the results very quickly, and doing so for a large number of people. Accordingly, the architecture is one of work-division and work-sharing, scale and data-handling, as is evident in the details of the architecture that Google has occasionally shared.

Technology-Driven Architecture
Unfortunately, it's common to see architectural discussions revolve solely around technology, where the technology and the architecture are not clearly linked to the problems facing the business, at least in the near term.

You can often see this when technologists of one shade or another (architects, chief technology officers, developers, whatever) get excited about a particular technology. That technology starts to show up in discussions without being grounded in business need. For example, if a technologist believes that .NET has better tooling than Java, he or she might start suggesting that any new project be built in .NET without having considered the cost and benefit to the company or organization in which he or she works.

Warning Signs
The most concrete and obvious warning sign for technology-driven architecture are when new software designs and architectures are proposed and discussed, and the technologies and the generalized benefits of those technologies are described at length but are not tied directly into the problems that are facing the business.

A secondary warning is when the architecture is tied to problems facing the business, but not the most immediate problems. If the architecture addresses future-facing or secondary problems, you have to ask yourself: Are these the right problems to be traclking right now? For instance, cloud computing architectures address scale, but many businesses have much more immediate problems than how to scale.

These choices are less black-and-white. It's true that many successful software businesses will eventually face the problem of how to scale, and if you ignore that potential problem right through the architecture and design of your application, you may end up paying a heavy cost at some later date. On the other hand, if you decide that scale is a problem you will eventually face, you might spend a lot of time building solutions to scale-out into early product designs, slowing down the development, restricting choices, and generally making it that much harder to succeed. These kinds of long-term architectural choices can be insidious in both directions.

You'll also find warning signs whenever anyone argues that a particular technology is just better than the alternatives, as if there's no trade-off to be made. There's always a trade-off to be made, and ignoring the costs in a new technology has sunk many a project into unexpected quagmires.

Common Examples
Some technologies make regular appearances in technology-driven architectures. They're technologies that sound good, that cause some people to believe they're just better, without seeing the inherent tradeoff. These examples are probably no surprise to anyone. :

  • Enterprise JavaBeans
  • Service-Oriented Architecture
  • Rule Engines
  • Workflow Engines
  • Business Process Management (BPM / BPEL)
  • Enterprise Service Bus
Each one of these can have benefits when compared to some of their alternatives, but each comes at a cost. They have a tendency to complicate the architecture, add more moving parts, reduce the predictability and testability of the final solution while slowing development. They can require a different mindset in order to use effectively. And then there's the more visible costs: learning curves, licensing fees, support contracts.

Exceptions to the Rule
There are exceptions to every rule, including the rule about there being exceptions to every rule. This rule is no exception. ;)

There are some instances where technology-driven architectural choices make sense:
  • Good prognostication is very hard, but if your team has a great track record of taking on future-facing problems in advance and you trust that, if the team wants to explore a technology, they probably have a good reason for it, and it'll work out in the end ... well that's a judgement call you can make.
  • Choosing an architecture based on a technology for a project that isn't on the critical path for a business can expose the development team to a new technology, allow them to explore it, find its strengths and weaknesses. This will allow them to make business-tied decisions about that technology in the future, and increase the odds of success if that technology does prove valuable on a more critical project at a later date. Even here, though, if the technology doesn't have an obvious link to the problems facing the business, it may be a waste of time to explore it at length.
There are all sorts of reasons to make technology and architecture choices, and I can't possibly tell you that your architectural choices are right or wrong. Mostly, I'd just like anyone proposing an architecture to stop and ask themselves what business problems this architecture addresses, and if those are the right problems to be tackling.

Monday, June 16, 2008

SproutCore Down

It's always amusing to me when the websites for web frameworks have visible downtime that appears to be related to the "application" or at least it's handling of errors rather than to, say, hardware.

SproutCore is currently showing an HTTP 500 - Internal Server Error.

Saturday, June 7, 2008

JAXB and Collections

Am I missing something? Does JAXB really require you to expose a naked collection in mapped objects?

If I expose a Collections.unmodifiableSet(property), JAXB invokes .clear(), which throws an UnsupportedOperationException.

If I return a shallow copy of the collection, when JAXB is converting XML to Java, JAXB requests the collection, clears it and modifies it, without so much as calling the setter again. As a result, the collection values don't appear in the final Java object.

That seems pretty awkward, so my first assumption is that I've made a mistake somewhere along the line, but ... perhaps JAXB really does want me to expose a mutable object, with the risk that entails. :/

Thursday, June 5, 2008

Equality and Object-Relational Mapping

Hibernate (and apparently JPA) uses the same object instance to represent the same record within the context of a transaction/session. This ensures that the default Object implementation of equality (Object.equals(object) compares instance identity) is sufficient for comparisons of persistent classes within a given transaction.

Outside of the transaction, this is no longer true -- one record in the database might have multiple instances, and if the values are changing, the values might not be the same. This leads one to all sorts of questions about how best to implement equality for persistent objects. There are discussion threads and wiki pages on the Hibernate site that go on about this in length, and I've read them a number of times over the years.

This morning, I think I've finally decided that all the mental effort I've put into that over the years is mostly wasted time. I'm coming around to the believe that instance-comparison is, in fact, a good behavior for the equals() method of persistent (or persistable) object instances.

There are basically a limited number areas where the equals() method of a persistent object comes into play for me in rough order of frequency of use:

  1. Regular database-interacting code within the application. In this case, I'm typically working within the context of a particular transaction, and instance comparison is sufficient.
  2. Test code, often persistence tests or integration tests where I'm expecting an object's fields to be the same before and after a particular operation (e.g. create object, save to database, load fresh instance, verify same fields). In these cases, I can use a Commons ReflectionEqualsBuilder without altering the implementation of equals().
  3. Long-running database-interacting code. In this case, I might have detached instances between transactions, but mostly comparisons will occur within the context of a transaction, and I don't mind reattaching / refreshing to make this work.
  4. Database-interacting application code that needs to compare objects from one transaction with objects from another. This does come up, but it's infrequent. In these cases, I think it's probably reasonable that the default comparison (equals()) fail fast, encouraging me to think carefully about why I'm doing this kind of comparison, what I'd like to compare, and how I'd like to go about it. This is rare enough that putting a little extra effort into these cases and having to put thought into why I'm doing it is probably a good thing.
So, I'm thinking for my next project, I'm going to stick with instance equality for my persistent objects and see how it goes.
Most of the time, I'm working with objects in the context of a transaction. When I want to compare objects across multiple transactions, I'm typically doing this in a test (e.g. a test of the persistent object mapping), and I can easily handle this with a reflection equals builder without actually altering the implementation of equals().

Monday, June 2, 2008

Detecting Intermittent Build Failure with Timed Builds

Almost every project I've been on eventually reaches a point where one or more tests are failing sporadically. Usually, this indicates there's a problem with the test, such as relying on timing, but occasionally it's a problem with the unit under test, or with the testability. For instance, integration testing of concurrency in a web-application is difficult, as you cannot control the timing of the threads inside the application server.

These problems often make themselves known in subtle ways by failing on occasion. If the developers working on the project aren't proactive, it's not uncommon to reach a point where any failed build on "known broken" tests are simply run again, which can consume a lot of potential productivity.

In order to find these kinds of intermittent failures, we often run timed builds in the off-hours. In the periods we're unlikely to be developing (at night and on weekends), we have a build trigger set to run project builds repeatedly (in Bamboo, this is a scheduled build with a cron expression like: 0 0/20 0-7,19-23 ? * *). When we come back the next day or after a weekend, we have a large number of build results waiting, and if we have an intermittent failure, it's likely to have come up at least once, often more than once.

This does take a little effort, but it's a step towards promoting the overall health of the build.

Monday, May 26, 2008

SubEtha SMTP, Maven and a Community Repository

We'd been using Dumbster to run some email integration tests. I've used it before, and it gets the job done. However, when running the overnight timed build (to drive out problems, we run the build repeatedly overnight), the email integration tests would occasionally lock up, never exit, and cause the build to run forever. A few logging statements drove out the source of the problem -- the Dumbster.start() method was going away and not coming back.

I'd previously seen the suggestion that SubEtha's Wiser was as capable and better code (less flaky, fewer problems) so I quickly swapped out Dumbster for SubEtha. Or, so I hoped. The swap was pretty easy, the hard part was getting a Maven-ready version of Dumbster with:

  • A versioned JAR: Grab the JAR from the download, upload it to our local repository, give it a group id and a version number (org/subethamail/subethasmtp/2.0.1/subethasmtp-2.0.1.jar).
  • A versioned JAR of sources: ZIP the source directory starting with the top-level package, rename it to a JAR, upload it to the local repository with the same group and artifact id as well as a version number (org/subethamail/subethasmtp/2.0.1/subethasmtp-2.0.1-sources.jar).
  • A POM listing the transitive dependencies: Create a POM, check all the dependencies in the lib directory, look up each to find out the appropriate artifact and group identifier, spend a little time evaluating the smallest set of dependencies that are necessary (if one includes another, such as was true for parts of Mina), then upload that as the POM (org/subethamail/subethasmtp/2.0.1/subethasmtp-2.0.1.pom).
This isn't a vast amount of work, and it could be simplified a little by tooling (that last step in particular), but it's a pain, and it's entirely preventable, if someone, ideally the project itself, provides the JARs and POM for you.

Since I'd already done the work, I posted my work to the subetha issue tracker in the hopes that they'd adopt it. No such luck. Their response:

That's great and all, but I don't really care about Maven, nor do I really want to add or maintain a pom.xml in the project. Sorry.

I admit, if I weren't using Maven on my project, the idea of keeping a POM up to date and uploading it to a remote repository would seem like a pain, and I've seen that attitude before. That said, if you want your project to be adopted by people, this is one way to ease the transition for some group of users, so it's unfortunate that projects take this stance.

A Community Repository
With that in mind, it'd be great if there were a public community repository for Maven which was like the public repository, but held artifacts for projects that were unwilling to supply them, but willing for someone else to maven-ize their project. Members of the community who'd created a Maven-enabled version for their own use could post their version for others to pick up.

This could be as simple as a second public repository which could be added, or perhaps even simpler, a top-level folder in the Maven public repo called unofficial where unofficial artifacts could be posted. The latter would ensure that Maven users would be fairly clear up front that they were pulling in an unofficial artifact, by virtue of the group id.

The primary danger in this approach is that people would fail to respect the license terms of software -- by packaging a piece of software for Maven, you may be considering redistributing it, and you'd have to be careful, as some software projects might not wish to have this happen.

As long as it were possible to have one's project removed from the repository and if the community tried to respect the desires of those projects, this still seems like it could be a very helpful addition.

Thursday, May 22, 2008

Spring Can Hide Transaction Demarcation Failures

When you define a TransactionProxyFactoryBean containing TransactionAttributes, the method names you use for transactional boundaries need not exist. The transaction attributes are examined to determine which methods on the inner class need to have advice applied, but nothing prevents you from attempting to apply transactions on methods that do not exist.

That sounds pretty innocuous, but it can mean that you thought you applied a transaction to a service method, but failed to do so, or that a service method that was renamed is no longer transactional but that you receive no warning. This has bitten me a few times, and I've seen very little discussion of it, so I thought I'd record it here.

This is of particular import if the underlying persistence implementation (ORM and Database) are willing and able to create transactions for you, or operate non-transactionally, if you fail to do so yourself. Without this, service methods that don't have a transaction boundary will simply error out when they attempt to do any serious work with the underlying database. With these "simplifying" assumptions, your service methods may be written as if they are transactional, but without the safety applied by having a transactional boundary.

With this in mind, I lean towards using the @Transactional annotation that Spring provides, which is more visible when you're doing work in the service class and less likely to get lost during simple refactorings.

Alternately, if you're using Spring and Hibernate, you might want to turn off HibernateTemplate's allowCreate, which enables it to create a session if not present, which helps to mask the problem.

I hope this saves some of you future pain.

Wednesday, May 21, 2008

Maven Build Profiling

I've often wished I had a tool that could provide a high-level profile of the build execution. I'm not talking about running the entire build on a profiler -- while that might be the ultimate goal, it's probably overkill, and harder to read than something simpler.

For instance, Maven 2 has a build lifecycle and plugins that tie into that. If Maven 2 could generate a report that indicated how long each phase of the build lifecycle took, possibly breaking out each pre- and post- phase, as well as each of the plugin executions, that'd be a terrific way to make a quick start on reducing the time of a particular build.

For instance, if your project has a fifteen minute build, but you're spending 13 of the 15 on the integration-test phase, then you have a pretty good idea right away on what your options are with respect to cutting down the build time (profiling the integration tests, reducing the number of integration tests, run integration tests only in CI, etc.).

I don't have enough Maven plugin development experience to argue if this is something that could be plugged into Maven easily, or not -- it seems as if the Maven plugin approach is better suited to things that execute at particular places in the lifecycle rather than interleaving with the lifecycle.

Friday, May 16, 2008

AMM: CMM for Architecture?

You know, I'm surprised that I haven't encountered an effort to create a CMM-like maturity model for architecture: an Architecture Maturity Model.

Although I'm not personally a big believer in CMM, nor do I put the same weight on big-A Architecture that some do, I guess it just seems like the sort of thing that the management boards of enterprises would like to hear. "Our new billing system is AMM Level 5!"

Is there something like that lurking in TOGAF, Zachman, ITIL etc. that I haven't encountered because I've studiously avoided learning these? :)

It doesn't seem unheard of in a Google Search, but just because someone, somewhere has used the phrase doesn't mean that it's an actual movement that has any weight behind it.

Thursday, May 15, 2008

Rated Syndication for RSS/Atom

I've often wished that content syndication via Atom and RSS came with ratings. Basically, there are feeds that contain good content, but have entirely too much of it. Consider the prolific output of some person or site like Robert Scoble or Engadget, and imagine that instead of having to choose between ignoring them entirely or drinking from the firehose, you could subscribe to the top X% of their syndicated content.

So when Engadget delivers the news about iPhone 2.0 and rates it 95%, you'll read it, but when they unbox a Samsung Blackjack 2.2 Silver and rate it 30%, you might not even have to skip past it with 'j' in Google Reader.

Heck, Google Reader could even offer to tweak your settings based on usage. "I've noticed you only read about 15% of Robert Scoble's postings. Would you like to subscribe to his top 20% syndicated content instead?" "I see you've read everything that Clay Shirky wrote this week. Would you like to expand your subscription?" "I see you're writing a memo ... "

The ratings could be delivered entirely by the content author/syndicator or through tools they supply for readers to modify the ratings, a la Digg / Reddit.

So, if you're out there working on the next syndication format, please take some kind of content rating into account, save me from the never-ending river of content.

Tuesday, May 13, 2008

Viewing Logs as Trees using NDC/Viewer

One of the problems that one tends to find when attempting to diagnose a problem using logs is the sheer volume of information that one has to digest. I've been thinking about that a little over the last couple of days, and it seems to me that with a little work you could display logs in tree form, like a call stack, which would give you the ability to do many of the kinds of things you can only do with a profiler right now, such as:

  • Track down the hibernate logging that relates to a particular HTTP request so that you can diagnose a tricky persistence problem.
  • Analyze the number of SQL calls made by a single HTTP request.
  • Get a rough outline of the time involved at each layer of a request.
In order to make that happen, it seems like you'd want:
  • Judicious application of the nested diagnostic context in Log4J or Logback to store a sense of the layer. This is probably done easiest with an aspect that could be applied at various tiers (services, daos, etc.)
  • Some kind of request-tracking key, whether this is the thread, or some kind of context-free identifier stored in the mapped diagnostic context. Again, this could be applied via an aspect.
  • Better log-parsing/viewing tooling. Using the above pieces of information, you could display logs as a tree, allow for querying, etc.
It's an interesting idea. Like most interesting ideas, it would take someone to actually follow through on it, and i'm not convinced that's going to be me. ;)

Monday, May 12, 2008

Project Wiki or Project Blog?

I've seen a lot of technology development projects adopt wikis as a way of sharing information. Often, unless you appoint someone the job of keeping the information both up-to-date and organized, these often get out of hand pretty quickly. Without a common kind of organization to keep things in check, it gets difficult to find information, and without someone constantly reviewing the documentation for relevance, some information gets out of date quickly while others remain relevant.

I'm starting to wonder if projects should probably seek a platform that emphasizes a blog style rather than a wiki style. The blog entry metaphor is more suited to "writing information about a point in time." When you do a search for something in your project blog and find information from May 2006, you're much more likely to think to yourself, "Hey, I wonder if this is still relevant."

That's not to say that a Wiki isn't a good idea, just that wiki content should be saved for information that is both long-term relevant and worth keeping up-to-date, and then someone should, in fact, regularly review it for relevance and make any necessary updates.

In keeping with my agile mindset, this kind of regularly updated documentation should be kept to that information that is very valuable, so that you don't distract a team whose job is creating value through software and end up spending a lot of their time reviewing and updating documentation that isn't necessary.

Wednesday, May 7, 2008

Scala Lift-Off

Interesting to see Scala and Lift gain a little momentum, with Scala Lift-Off, an unconference.

Wednesday, April 23, 2008

Clustered JMX

I'm a little surprised that it's taken until Java 7 to seriously consider how to address JMX in a Cluster. This seems like something that a lot of people would have to be dealing with regularly. I'm trying to discern what this means:

  1. People don't use JMX much.
  2. People who do a lot of clustering don't use JMX to manage their running applications.
  3. Everyone who clusters and uses JMX invests a fair amount of time into deploying a solution like OpenDMK.
Thoughts?

Tuesday, April 22, 2008

Doug Lea on the Art of Multiprocessor Programming

Doug Lea on Concurrency-Interest:

This is by far the best source for explaining the ideas and algorithms underlying java.util.concurrent -- the vast majority of them, plus some others, including a few that may someday appear. It also uses Java / java.util.concurrent to illustrate most concepts. I strongly recommended it.
Strong praise coming from a distinguished source like Doug Lea, I'd say.

Friday, April 18, 2008

Mesh U

MeshU looks pretty interesting. Toronto's just overflowing with interesting conferences these days.

Thursday, April 17, 2008

Twitter Quote of the Day

"I used to think that people who didn't look constantly bewildered were smarter. Now, I think it's the other way around." - Michael Feathers.

Log4JWebConfigurer Not Suited for J2EE

It's not uncommon to want to be able to change the logging configuration of a running application without restarting the application. There are a few mechanisms for doing this. One, which I've used in the past, is to expose Log4J via JMX. It's a bit of work, but not terrifically hard.

Another mechanism is to have the logging framework watch its own configuration file and, if it changes, reconfigure itself. Log4J has a mechanism for this, which Spring exposes through the Log4JConfigurator (Log4jWebConfigurator, etc.)

Unfortunately, it seems as if, at least according to the Spring folks, and their documentation, Log4J's mechanism doesn't do a good job of shutting down its thread, and therefore should not be used in a production setting.

That means that either I'm going to have to back to using the JMX approach or, alternately, switch the project to LogBack, which has a JMX Configurator built-in, and can reload from configuration using JMX.

Tuesday, April 15, 2008

AppDrop with SimpleDB

It'd be interesting if AppDrop moved its persistence layer to SimpleDB. You could then get a good comparative benchmark of a single instance of AppDrop EC2/SimpleDB vs. running on the Google App Engine infrastructure. From there, you could work on the scaling story, either with transparent scaling, like Google seems to offer, or with user-controlled scaling (since AWS services aren't free, the latter might be less dangerous).

Not that AppDrop is necessarily the future of AWS apps any more than GAE is the future of cloud computing, but a common model for platform-on-cloud development that could be deployed in more than one infrastructure is appealing.

Maven 2.0.9 Build Stability

Maven 2.0.9 locks down the versions of core plugins in the super POM. This should increase the stability and repeatability of your builds somewhat. You'll still want to lock down versions of third-party plugins in your build for the same reason.

Monday, April 14, 2008

EnumSet from VarArgs

Irritating that EnumSet doesn't support Varargs and/or iterable. That means you need some ugly transition code like:


public InclusionCompletionModel(JobStatus... completeStatuses) {
this.completeStatuses = EnumSet.copyOf( Arrays.asList( completeStatuses ) );
}

Successful Unversal Data Models?

A friend passed on a link to this Universal Data Models article, and I have to admit this is an issue about which I feel some conflict.

On the one hand, I respect the notion that, in the world of standardized relational databases and object-oriented programming, it'd be nice to be able to pick up standard models that represent clear and common items like people, companies, and the relationships between them.

On the other, I've wandered partially down this path before a few times and emerged with scars. While it's certainly true that many organizations have software that needs to track information about people, organizations, and the ways they're related, it's also true that there innumerable pieces of information one might want to record about people and organizations, and countless ways in which they can be related. In order to be truly universal, you'd have to capture all of those ways and distill it into a common data model.

Practically speaking, I find that universal data models fail in three important ways, and most models attempting to be universal suffer from at least one if not all three of these:

  • Too Generic: Because the model attempts to be flexible, to be useful in all kinds of scenarios, what you're left with is often too generic to be as useful as a data model tailored to your needs. For instance, if your company has one and only one account manager assigned to a particular client, the simplest way to represent that is something like a foreign key from a client to an account manager. In a universal model, this is might take the form of, say, a PERSON_ORGANIZATION relationship between an 'employee' person and a 'client' organization and where the PERSON_ORGANIZATION.ROLE is 'account manager', and you'll need application-level uniqueness checking to ensure there are no duplicates. You'll find yourself having to do extra work for the simplest things -- if a billing address is a requirement for any client, you can enforce that in your custom data model, but there's no way that your generic model can do that for you.
  • Too Much: The model has more information than you need. You don't have email addresses for your field employees, or you don't care about fax numbers, or perhaps your clients don't have departments and regions, or you don't care to track them.
  • Not Enough:
Often, each instance of those problems is pretty minor:
  • The universal model has a field you don't need? Ignore it, filter it with a view or don't map it to your domain objects.
  • The universal model doesn't have a field you need? They've kindly supplied a key-value table or custom_field_12 where you can put that sort of thing.
  • The model's too generic? You can simplify that by using a domain object that hides the complexity.
All those things are true, but they increase the pain and effort of using the model. Quickly, the cost of using a generic model exceeds its benefits, particularly if you're doing so for purely philosophical reasons like, "Wouldn't it be nice if we could all re-use a common idea of what a Company is?"

Worse still, these can introduce cognitive dissonance when you force-fit your own business needs into someone else's generic model - you can make it that much harder for your business members and development team to share a universal language about your domain and communicate effectively. When the business owner asks "Validate that when an account manager leaves the company, another account manager takes his place with that client", you have to do mental gymnastics to imagine what they mean, and those gymnastics can introduce errors, almost like transcription errors: "When a PERSON with PERSON.type='employee' and PERSON_ORGANIZATION.role='account manager' becomes PERSON.active=false, then add a new PERSON_ORGANIZATION record that associates another PERSON.type='employee' with PERSON_ORGANZATION.role='account manager' ... "

I'm curious how many people find themselves using universal models and are happy doing so.

Friday, April 11, 2008

Gartner: Windows is Collapsing

Gartner says Windows is Collapsing. While I don't believe in industry analysis for the most part, and any headline like this is oversimplified, I'll agree insofar as this:

Microsoft has survived a poorly reviewed operating system before, but they're beseiged right now. If the next version of Windows doesn't get business accolades, we may well have witnessed the beginning of the end. Microsoft isn't going anywhere now, tomorrow, or even next year or the year after, but if they don't make some ground, they're going to be increasingly marginalized as a technology has-been.

Some people would argue they're there already, and have been there for a while, but as long as Windows and Office continued to bring in the Cash, it's hard to argue. If that destabilizes, Microsoft will begin to devolve for real.

Tuesday, April 8, 2008

Would You Trust Google App Engines?

I have to say, after preparing a long and exhaustive post on Google App Engine for InfoQ, one of my remaining takeaways is that in order to make good use of App Engine, you've got to be willing to trust Google.

To a certain extent, that's true of most software-as-a-service. If Google decides to terminate GMail, or goes out of business, that's going to do serious damage to my ability to communicate with the world, which is a little scary. At the same time, that's mostly relatively personal, relatively low-consequence items. I'm not saying I'd be happy if GMail went down, far from it, but I'd survive it.

On the other hand, if I built my startup in Google App Engine there are so many things out of my control that can happen, not the least of which is that Google could increase the cost of the service significantly, and notify me, and it wouldn't be incredibly easy to take my app and host it elsewhere.

That's not true of most web applications, which can be hosted at any compatible hosting provider, of which there are usually many. So you are, to a certain extent, locked in to the Google infrastructure, which provides you benefits, but comes at a cost.

That's not necessarily a deal-breaker, especially when compared to the cost of hosting an application yourself and managing it to scale, but it's something that any adopter has to seriously think about.

Google App-Engine and Top-Down Cloud Computing

Many people are comparing Google's App Engine to Amazon S3. There's certainly some relation - both offer the ability to build an application and run it 'in the cloud' - in someone else's infrastructure, with seemingly limitless expansion room (well, Google's offer has a strict quota, but one assumes there'll be pay plans beyond that point in the future).

But Amazon's approach has been bottom-up - web services that allow you to control the bits and bobs of infrastructure you might use to create your own cloud-computing application (e.g. EC2 instances and S3 storage). This gives you a fair amount of flexibility while still being simpler and more cost-effective (in some cases, anyway) than building your own grid infrastructure. For instance, EC3 can allow you to scale to handle peak loads while still keeping your costs low when there's less traffic.

On the other hand, Google's top-down approach isn't really about giving you options, it's about creating a model for applications that run in the cloud and restricting you to that model, so that you can focus on building an application and trust that the limitations Google has placed on you will allow Google to scale it up and down as necessary to meet demand.

The former has a lot more control and sometimes that'll be very necessary for applications that are difficult to build in Google App Engine (for instance, there's only language support for Python at the moment). On the other hand, the latter offers a very simple model for creating applications at scale without needing to really know that much about how to scale an application.

It'll be interesting to see, with time, if development for the cloud is closer to Amazon's (full control, skill required) or Google's (restricted choice, with simplicity). I'd probably bet on the latter for most applications.

I'll have more to say on this later -- I'll be doing something more comprehensive for InfoQ.

Sunday, April 6, 2008

Disposable

I guess I've never been a big fan of the idea of disposable razors. It seems like regular razors are pretty convenient, and I'm not sure there's much convenience to be added by throwing away the handle. I guess it never really seemed to make a lot of sense to me. Even if you want a razor just for travelling -- go buy a second razor, I guess.

It also seemed pretty wasteful. So I guess when the Yonge and Bloor stations in Toronto were papered over with "Mach 3 Disposable: Enough Said" ads, it really struck a nerve. Enough of a nerve to spend some time in Photoshop to translate their ads into the subtext, as read by me:
I wasn't sure how much one could get away with without dealing with cease-and-desist letters, so I decided not to pull in the Gilette name or the Mach3 specialized writing, just to try and calm down the possiblity of legal storm. That said, either nobody ever really notices and neither will Gillette, or perhaps this'll attract enough attention to bring Gillette, at which point I hope this has reached a large enough audience, by then, that the value of issuing letters to have me remove this will be significantly reduced.

Wednesday, April 2, 2008

Maven Web Project Gotcha: Overlays

In order to prepare for some integration testing of a multi-WAR service layer, I included one WAR into the project dependencies of a Maven web project. If I had time to do this in 'the maven way', I'd probably pull this into an integration test subproject, but, sadly, I don't have time for that in this instance.

Unfortunately, this leads directly to Maven's principle of 'most surprise'. Turns out, if your web project depends on a WAR, the contents of that WAR will be overlaid over your web project, unless you explicitly tell it otherwise. Since I hadn't read about overlays this was actively damaging to my project, and very confusing. This cryptic build output helped me understand what was going on:

OverlayPackagingTask performPackaging overlay.getTargetPath() null

I hope that my mentioning this will save some of you future grief.

Tuesday, April 1, 2008

JAX-RS Momentum

It's great to see JAX-RS picking up momentum. I've done work in Restlet, and I'd like to spend some time in Jersey, so it's great to see that I'll have more choices next time.

Next comes tool support, integration, and then ... the world. Although, to be honest, I'd be happier with web services and remoting if I felt that they were consistently being used appropriately. I still find that people consider remoting when they don't need it -- too busy looking for the long-term flexibility and not enough time actually building the immediately necessary functionality.

Monday, March 31, 2008

Offline Google Docs

Curious to see how the availability of Offline Google Docs [via Scoble's twitter] affects the office software space.

Eclipse 3.4 Annotation Formatting

Eclipse 3.4 M5 resolves one of my biggest remaining complaints with the Eclipse formatter -- the inability to specify newline-after-annotation settings differently for annotations on different scopes:

Starting with 3.4M5, the Java source code formatter provides fine-grained options for line breaks after annotations. Instead of specifying whether line breaks should be inserted after all types of annotations, it's now possible to specify this separately for each of the different types of annotations


For instance, I would personally like to have newlines after method annotations, but not on method parameter annotations.

Thursday, February 14, 2008

Google Docs Will Be Your Valentine


Somewhere out there, there's a poor soul giving a business presentation who's going to call up Google Docs on the projector and get a bit of a shock.

For the rest of you, well, I guess I can live with a Valentines-themed Google Docs as long as next October 31st, I get black cats, ghosts, skeletons and the like to compensate.

I wonder what St. Patty's day will bring?

Wednesday, February 13, 2008

Testing Cluster Configurations with VMWare Teams

I hadn't noticed that VMWare had added a teams feature whereby you could set up a series of virtual machines with a particular network configuration and have these be loaded together. As a result, you could create an entire cluster configuration, such as a master/slave MySQL configuration, a firewall, a cluster of application servers, another firewall, and some client machines.

Once this is configured, you could deliver this VMWare team to someone who could do load and failover testing, deployment/upgrade testing on the cluster, and so forth. Seems like a nice option to have available.

Any of you making use of this?

Tuesday, February 12, 2008

Toronto Summer: Agile 2008, RubyFringe

Wow - Summer 2008 is going to be a killer Toronto summer for Conferences. We've got:

  • Agile 2008: August 4th-8th, the best-known conference on Agile.
  • RubyFringe: July 18th-20th. A new conference dedicated to the fringe of Ruby, everything but Ruby on Rails, really. This presumably covers 'waves' and 'merb' and many other things. Just announced.

Thursday, February 7, 2008

Eclipse Data Tools Platform

A friend of mine, having some troubles with the Data Tools Platform, asked me if I knew much about it. I didn't -- even though I've often had Quantum installed, I usually fall back on standalone tools, either gui tools like like Oracle SQL Developer, command-line clients (mysql, sqlplus), or even generic tools like DbVisualizer.

On a whim, I decided to take a quick look at the Data Tools platform and see what I thought. After all, it might be great.

Turns out, it's ... very Eclipse. It's as if they took someone who'd barely used a database in their life, and certainly not other database tools, and yet was quite familiar with Eclipse. Setting up database connections for the first time is a little bizarre, as there are all sorts of database definitions without the required driver JARs, for which the JAR name is defined, but not supplied.

Once you've got that done, there's a data source explorer which isn't bad - lets you explore the structure of the database and metadata about the database. There's also a SQL Results view, again somewhat in keeping with other tools.

Where it gets really bizarre is when you want to do a Query. For many database tools, this is the central metaphor. There's a query box, you type in it, execute it and get results. For some tools, the idea of running scripts is secondary. That's because doing database development is often very exploratory and iterative, and it's not uncommon to build a query in pieces, executing it as you go, until you arrive at the final query that you intended from the beginning.

However, Eclipse has buried this idea deeply. You can either create an SQL file which you may edit, then right-click to execute, or you can create a launch configuration of 'adhoc query', which you can run in the Run menu. This isn't really ad-hoc, of course, because the query is defined in the launch configuration and not easily changed without going through a multi-step process. Both of these could be useful if the supplemented a simple query view which seems to be bizarrely missing.

Does this strike anyone else as a little queer?

I've gotta say, I'm tempted just to uninstall this, as it's clearly using up space my disk and possibly in memory for no reason at all. In its current form, I wouldn't bother with it.

Spring-Enabled vs. Spring-Dependent

It's getting surprisingly common for projects (e.g. Enunciate, CXF) to bundle Spring amongst their dependencies, which is creating a bit of "DLL-hell" - having to make exclusions for various versions of Spring and make sure that all the projects can agree on a particular version of Spring.

Requiring Spring to work at all makes these projects spring-dependent in a way that I'm not entirely happy with. Personally, I'd prefer them to be spring-enabled, whereby they are well-suited to being injected in your project, but can operate without Spring, and therefore, don't come with their own version of Spring with which you have to negotiate.

I'm not opposed to there being multiple modules available -- a module that is spring-enabled for projects already using spring, and a module that's spring-dependent for projects not otherwise using spring or not worried about the particular version of Spring. That seems like a handy way around the problem.

Enunciate's case is somewhat forgiveable, in that it's generating a WAR that includes Spring MVC code. I haven't investigated CXF's dependency on Spring, but it's causing some grief for a colleague.

REST and SOAP and the Right Tool for the Job

I don't disagree with netzooid's conclusions:

Please keep in mind that REST and SOAP programming models don’t mix well. There is this complete fallacy going around (I succumbed to it too at one point) that you can use the same service class or description to build a RESTful and a SOAP based service. However, the interactions and mappings should end up being completely different from one to the other! One is message based and one is resource based. You’re going to have to design your service differently as they’re two completely different beasts.
I largely agree with this. What I will say is that if you've already got a REST or a SOAP API and you have the capability to expose that API through the other technology, it's often possible to do so. While this might not truly be a REST or SOAP api, it's close enough for many people.

That said, the natural approach for REST and the natural approach for SOAP are quite different, and to do a good job of both, you'll find that your services end up being quite different, even if they're layered on top of the same basic infrastructure.

I've used Restlet, and I'm relatively happy with it. It's still maturing, but it's basically ready-to-go. I've been watching Jersey interestedly, and it seems to be shaping up well, but there's always time for the JCP to mess it all up before a final release. I've also used Enunciate, which is capable of generating both SOAP and REST. It's an interesting concept, although I do believe it needs more time to be mature enough to recommend.

Monday, February 4, 2008

Multiple Representations in Object/XML Mapping

Having tried a few different approaches for Object/XML mapping over the years, from SAX/DOM manually coded work, through Rails' (ActiveRecord) toXml, JAXB, XStream, Hibernate, etc, I'm constantly surprised by the idea that most of these frameworks seem to assume that most people are going to want a single representation of an Object in XML form.

In almost every application I've ever built that did any kind of Object/XML mapping, I've wanted to have multiple representations of the objects. In particular, I'm most likely to want these three:

  • A simple reference - in this form, I'd like to link to the object, and provide almost no additional information. This is usually used to link from one object to another.
  • A summary - in this form, I'd like to provide just enough information to populate a list, or a combo-box, but no more. I'd usually use this to populate a list or a combo box.
  • The full details - in this form, I'd like to provide most or all of the information about the object. This is for detailed views of the object.
By way of example, assume that I've got a REST service for contacts in an email program (e.g. GMail). If might expose the following representations of that contact:
  • Reference
    <contact id="123" href="http://my.rest.context/api/version/contacts/123.xml" />
  • Summary
    <contact>
    <id>123</id>
    <name>Joe Blow</name>
    <email>joe.blow@example.com</email>
    </contact>
  • Full
    <contact>
    <id>123</id>
    <name>Joe Blow</name>
    <email>joe.blow@example.com</email>
    <firstName>Joe</firstName>
    <lastName>Blow</lastName>
    <address>1 Yonge Street, Toronto, ON</address>
    </contact>
In many cases, I can combine the first two; that may not be ideal in all cases, but it does help to simplify. When one object refers to another, I'd like to retain control over its representation separately. In complicated cases, I may need field-level control over the representation at various levels of an object graph. In these cases, it almost seems like I want SQL-like syntax.

I've not yet run into an Object/XML mapping framework that made this kind of control easy (do feel free to recommend some, if you like), so I've often felt like a templating approach, the same kind of approaches one uses to generate HTML, makes as much sense as any. In Rails, this takes the form of RXML templates. In Java, this could be Velocity/Freemarker, or something of that ilk.

Suggestions for another approach are welcome.

Why does JDK install two JREs?

I've never really understood it, and since I've installed Java SE 6.0 Update 4 about five times in the last few days, it's really started to become irksome. When you install a JDK on Windows, it installs one JRE under the JDK directory (e.g. %JAVA_HOME%/jre) and then, having finished installing the JDK runs out and installs another JRE in a different directory.

Why? What's the point behind this? I realize it allows you to uninstall the JDK and leave the JRE intact, but isn't that like having Microsoft install Office as a suite, and then Word, Excel, etc into different directories so that you can uninstall Office without uninstalling Word, Excel and Powerpoint?

It's weird, and silly. Is there a rationale that I'm missing?

Friday, February 1, 2008

Whatever Happened to Version Numbers?

Used to be, when you released software, you did so in major and minor versions, and sometimes patch releases: 8.0, 8.1, 8.1.1. These are the version numbers I grew up with.

These days, it's all over the map. Windows "XP" "Service Pack 2". Java SE "6 Update 4". And let's not even talk about Java 2, Standard Edition, 1.4, Update 1. OS X 10.5

Was the old system so bad? Is there some reason that Java can't be Java SE 6.4, or, if there's an undesired implication of changed functionality, Java SE 6.0.4?

I wonder, have we done this to ourselves in some way, or is there some kind of regulation of which this is the unintended consequence? Has SAS70 compliance scared corporations into ignoring the old versioning approaches because they have become burdened with regulatory issues?

Or is this simply a case of marketing gone wrong?

When Microsoft gets bored of trying to acquire Yahoo and goes back to contemplating how to get away from Windows Vista, I'd like to make this suggestion: Windows 10.0.

After all, Windows 3.1 was followed by Windows 95 (Windows 4), Windows 98 (Windows 5), Windows 2000 (Windows 6), Windows ME (Windows 7), Windows XP (Windows 8) and Windows Vista (Windows 9). I know things get complicated if you look at Windows NT 3.5/4.0 and Windows 2003, so I'll leave those out for the sake of simplicity.

Besides, Apple seems to think that 10 is a good number. I'm looking forward to OS X 10.12, Sabertooth.

Wednesday, January 30, 2008

Can Hibernate Learn from Edge Rails?

Just finished reading about some eager-loading options for edge rails, and how they've moved away from the outer-join approach and into a multi-query approach because they believe it to be faster.

Last I saw, Hibernate used the outer-join approach in its internals for eager-fetches, so I wonder, is this an instance where Hibernate can learn from edge rails? I'd be curious to evaluate the two approaches across all the databases Hibernate supports with different data sets and see which wins out.

Monday, January 28, 2008

Multi-tasking Development Less Efficient?

The Autumn of the Multi-Taskers argues that multi-tasking doesn't really work, that by trying to do so, we're doing less, and burning ourselves out at the same time.

Multitasking messes with the brain in several ways. At the most basic level, the mental balancing acts that it requires—the constant switching and pivoting—energize regions of the brain that specialize in visual processing and physical coordination and simultaneously appear to shortchange some of the higher areas related to memory and learning. We concentrate on the act of concentration at the expense of whatever it is that we’re supposed to be concentrating on.
Perhaps worrisome that I managed to get this read while developing and building (more the latter than the former, but ...). I find developers practice multi-tasking quite a bit, and I wonder sometimes, if it's as effective as we might like it to be.

Via Gruber / Rands.