Flash Builder 4 Reference Card

I recently published a Reference Card with DZone: Getting Started with Flash Builder 4.  The Reference Card covers the new features of Flash Builder 4 and includes a basic overview of Flex application development.  Check it out!

I enjoyed working with DZone to publish this card, and the editorial process was great.  I hope you find it useful.  Let me know what you think!

Google Is Great, When It Works

I'm a big fan of Google.

While I've written my own email server, I've adopted Google Apps for nearly all of the domains I manage.  Gmail is a great tool, and has freed me from the tendency to over-organize my mail.  I can now find things easier and quicker than I ever did using Outlook or Thunderbird simply using minimal tagging and the built in search functionality.

I've used Google Search, Google Apps (Mail, Calender), Google Reader, Blogger, Google Docs,  Google Code, Google Web Toolkit (GWT), and the Google App Engine.  Great stuff.

If it works.

However, if something goes wrong, it can be difficult to find the answer.  Your best bet is to Google for the solution of course.  Hopefully someone has encountered the issue before and can point you in the right direction.  If not...

I recently migrated my Blogger setup (for this blog) from FTP publishing to a Custom Domain hosted by Google.  The transition went fairly smoothly (as I documented here), and while I was a bit annoyed I had to change my setup, it was fairly painless and hey, the price is right.

But I ran into an issue with my RSS (Atom) feed.  I've been using Feedburner for quite a while to track the number of subscribers.  When I used FTP publishing I simply edited the template to point to my Feedburner feed.  However, now that I switched to hosted mode, I can't edit the template the same way.  So most new subscribers are using the base Google feed, not the Feedburner feed. 

Google does offer an option to handle this, 'Post Feed Redirect URL', with the description: "If you have burned your post feed with FeedBurner, or used another service to process your feed, enter the full feed URL here. Blogger will redirect all post feed traffic to this address. Leave this blank for no redirection." Of course, when I enter my Feedburner feed in this URL, I get the error: 'This URL would break your feed, resulting in a redirect loop. Leave the field blank to serve your feed normally.'  Based on all the reading I've done, my setup appears to be correct and this should work.  Faced with limited support options, I posted a question to Google's help forums.  I got a response that appears to suggest that something internally needs to be reset, but no help from any Google resources.  So, I guess I'm stuck.

Or course, you can point out that I'm getting what I pay for, which is true.  Blogger is a free service, and I'm not entitled to any specific level of support.  But that doesn't make the situation any less frustrating.

At least this issue is minor.  In the end, it doesn't really matter.  But suppose I had in issue with Gmail.  What would I do then?  Well, I guess the answer would be upgrade to a Pro account, and then demand support, but that is only because I'm using Google Apps instead a plain Gmail account.

The risk of free...

Programming in the Small

I believe that successful application development today is about 'tweaks and sub-features', not major functionality.  But my thought process for this post was kicked off by an interesting post by Mike Taylor: 'Whatever happened to programming?' Mike laments the evolution of programming.  He is nostalgic for the day when writing a program was about creating something from scratch, instead of assembling the various pieces.

I think his assessment of the transition is fairly accurate.  The number of frameworks and libraries in projects today far exceeds the number used in projects 5, 10, or 20 years ago.  This is especially true in the Java world, where build tools like Maven gained traction because they handled the dependency management.  And now, a non-trivial Java project can easily incorporate 100 or more jar files, while a trivial 'boiler plate' web application can easily have 20 jars.

In many ways this is frustrating.  It has also given rise to what I call the cut and paste programmer.  You can actually achieve reasonably impressive results simply by searching for the right libraries, and them assembling them together but cutting and pasting example code found via Google.

From a business perspective, these are all good things.  The level of skill required to produce results is lower, and the speed of development has greatly increased.  We are standing on a very tall foundation.

This also means that the major functionality of many applications is provided mostly by libraries and frameworks.  The heavy lifting parts are not really heavy anymore.  I think Jeff Atwood hits this nail on the head when he stated on a Stack Overflow podcast episode that the major features of Stack Overflow themselves are fairly trivial.  The real value is that it is a collection of many small features and tweaks that make the overall system successful (I can't find the reference, so I apologize if I paraphrased incorrectly).  I think this point is right on.  Most major 'features' are trivial to implement today using the rich set of libraries that exist.  Building a website that has questions an answers like stack overflow is trivial.  Making it successful is hard.  And the difference is all in the fine print.

Jeff discussed at some length the time they spent with the syntax parser (markdown) and instructions on the 'ask a question' page.  Small changes to how the information is displayed and highlighted are much more important then the major feature of saving the question to a database and displaying it.

Successful applications today are about the user experience.  There are very few applications that are truly innovative themselves and could not be replicated by gluing together a set of frameworks.

Real innovation today is in the small.  This is also why I believe that the rise of Appliance Computing is here, and that Write Once Run Anywhere languages are inferior to native client applications.  It is the difference between a iPhone web application and a native app.  They both have the same features, but the experience can be very different.  In the end, the real value is the small efficiencies in the application, not the large features. 

Web File Extensions are Bad

I hate file extensions on websites.  It is an unnecessary leaky abstraction, and is discouraged by the W3C.  All file extensions are not necessarily bad, but any file extension that exposes the underlying technology implementation is.  Any .pl, .php, .asp, .aspx, .jsp, .do, *.struts, etc extensions are B A D.

I've talked about this before, and come up with some workarounds to build extension-less java web applications before.

However, I've come across what I think is a better way, thanks to a post a couple years ago by Matt Raible.

I came across the issue using the Spring WebMVC DispatcherServlet.  I want all dynamic URLs handled by the Spring Controllers, using Annotations.  However, mapping the DispatcherServlet to /* means that every URL will be processed by the DispatcherServlet, including the .jsp views returned by the Controller.  As I mentioned in the previous post, you can 'unmap' content and have it handled by a default or jsp servlet in some app servers, but not all.

You can also try to map specific subsets of URLs to spring.  However, this is harder than it sounds.  By default, Spring will map the wildcard portion of the URL matched, not the entire URL.  So if you have /foo/* as your url-pattern, the controller with a mapping of /foo/one will not match /foo/one, but instead matches /foo/foo/one.

It appears that you can use the property alwaysUseFullPath to change this behavior, but it did not seem to work as expected for me.

Instead, there is a more generalized solution, as Matt suggested.  URL Rewriting.

The URL Rewrite Filter project provides a Filter that you easily define rewrite rules for, just like in Apache.  So I setup my DispatcherServlet to match *.spring, I setup a rule to rewrite all extension-less requests to .spring, and I setup my annotations to have the .spring extension.

Now my web application can handle the odd html, png, or other static files if necessary, but does not expose any implementation details in the URLs.  Perfect.

For reference, here are the relevant portions of my config:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"

    <to type="forward">home</to>

    <to last="true">$1/$2.spring$3</to>
Sample Controller
public class SimpleDataController {

  public ModelAndView bar() {

Developing a Google App Engine (GAE) app using Maven

If you want to develop a Google App Engine (GAE) application using Maven, you can either use the Maven plugin maven-gae-plugin, which requires non-trivial hacking on your pom.xml, or you can keep your pom clean and create a simple Ant script.

My pom is a simple web application pom, with no specific GAE configuration.  I then created a build.xml in my project root that looks like this:
  <property name="sdk.dir" location="/opt/appengine-java-sdk-1.3.1" />

  <import file="${sdk.dir}/config/user/ant-macros.xml" />

  <target name="runserver" depends=""
      description="Starts the development server.">
    <dev_appserver war="target/yourappname-1.0-SNAPSHOT" />


Using this, you can run your application in the GAE sandbox without having it take over your pom.

You can also have the ant task perform a maven package to insure everything is updated by adding an exec target to the runserver task.

You can read more about the full range of Ant tasks available for GAE, but I found this simple script helpful to get up and running quickly in the GAE sandbox without much effort.