Skip to main content

Java, applications and user feedback: which program version are you using anyway?

Posted in

Do you know this kind of situation? You get an email - A bug report for one of your applications and it kinda reads like: "Help, your app is broken - please fix it". Now it's your job to help the user figure out which application is meant (assuming your portfolio contains several) and more importantly, which version of that application s/he is actually using. A task, that usually includes sending back and forth a number of extra emails, just to explain how to gather the required information.

For the sake of the argument let's consider that you already made that experience once and in reaction to it decided that the version identifier will, from now on, always be shown in the window title. Big question: what's the best way to do this? Let's start with the naive approach:

    import javax.swing.*;
    public class MyApp {
 
      public static String VERSION = "v1.1";
      public static void main(String args[]) {
        JFrame frame = new JFrame("MyApp "+VERSION);
        frame.setBounds(50,50,200,100);
        frame.setVisible(true);
      }
    }

Now, this is not a very smart solution for a number of reasons:

  1. You should never hardcode display strings in your application. That's just a catastrophe in the making when internationalization comes into play.
  2. Your sourcecode is probably living in some kind of version control system (e.g. git or subversion). It's way to easy to commit the final patch for a release candidate, build it, deploy it and afterwards realize that you forgot to update the version identifier.
  3. Depending on what bug your user reported, you might want to build a test version of your application (and send it to him/her) that clearly states "TEST XYZ" in the version identifier, so it cannot possibly be confused with the production code. Changing files for this is just not an option. You might forget to change them back and end up with the problem, mentioned in the previous point.

Considering these three points, it's quite obvious that the version identifier should not live in any file at all. It should rather be submitted as an argument to the build process. So, how do you do that? First of all, let's have a look at the Manifest specification: it lists an attribute, called "Implementation-Version" and that is just perfect for our needs. The Ant task to get it into your JAR Manifest should look something like this:

      <property name="version" value="DEVELOPER_VERSION"></property>
      
      <target name="bundle">
        <jar destfile="MyApp-${version}.jar">
          <fileset dir="." ></fileset>
          <manifest>
            <attribute name="Main-class" value="MyApp"></attribute>
            <attribute name="Implementation-Version" value="${version}" ></attribute>
          </manifest>
        </jar>
      </target>

Invoke ant with the -Dversion=TEST_A commandline argument and it should build a file called MyApp-TEST_A.jar. Pretty neat so far, but we still have to actually get the identifier into our window title. Fortunately, this is rather trivial:

    import javax.swing.*;
    public class MyApp {
 
      public static String VERSION = Package.getPackage("MyApp").getImplementationVersion();
 
      public static void main(String args[]) {
        JFrame frame = new JFrame("MyApp "+VERSION);
        frame.setBounds(50,50,200,100);
        frame.setVisible(true);
      }
    }

Et voilĂ ! The version identifier can now be submitted externally. If none is submitted on the commandline, the default one ("DEVELOPER_VERSION" in the example above) is used instead.