Posts Tagged ‘java’

Java Web Start 1.5

The Java Network Launching Protocol (JNLP), commonly known as Java Web Start, is some very cool technology. In my opinion, it hits a sweet spot between web applications and local applications:

  • Software is run locally on the client machine. JNLP is supported on every platform that Sun’s Java Runtime environment is available, including Linux, Windows, and Mac OS X.
  • The software can be updated on the remote server, and it is updated locally as soon as it is next run.
  • Desktop integration is possible, meaning that the user of the software has a nice double-clickable application shortcut on their desktop, start menu, applications folder, or wherever you would store such a thing in Linux.
  • New in Java 1.5^H^H^H5.0 – file associations can be specified in JNLP files, meaning that I can open a “.whatever” file with the Whatever Java Web Start application by clicking it. Cool!

So, basically JNLP has some of the advantages of Web applications (immediate upgrades available, doesn’t need to be rolled out by network administrators [whether this is really an advantage is questionable]), and some of the advantages of desktop applications (run locally, quick to run, shortcuts and file associations). Cool.

However, the changes to JNLP in Java 1.5 are somewhat poorly documented. I’ve discovered three tidbits of information that I believe are pretty useful, so I’m going to share them with you.

First of all, I wanted my users to know that by using Java 1.5 they’re going to get some additional functionality (file associations), but my application still runs in Java 1.4. I updated my web start launch page to check for 1.5.0 (thanks to Sun’s documentation), and then made it link to my download page with some useful text if they don’t have 1.5. However, if the user went to the download page when running Java 1.4, it did not upgrade to Java 1.5 – it saw that Java Web Start was available, and launched the application.

Adding a #Version tag to the download page fixed this, forcing an upgrade to 1.5.0:


<!--
Automatically installs Java 1.5.0 and runs the PDA application with
Java Web Start.  The addition of the #Version section on the object's
codebase will cause an upgrade to JRE 1.5.0 even if the user already
has a Java Runtime installed.
-->
<object
  codebase="http://java.sun.com/update/1.5.0/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"
  classid="clsid:5852F5ED-8BF4-11D4-A245-0080C6F74284"
  height="0"
  width="0">
    <param name="app" value="http://yoursite.com/app.jnlp">
    <param name="back" value="true">
    <!-- Alternate HTML for browsers which cannot instantiate the object -->
    <a
        xhref="http://java.sun.com/j2se/1.5.0/download.html"
        mce_href="http://java.sun.com/j2se/1.5.0/download.html">
          Download Java Web Start
    </a>
</object>

So, now my users had the option to upgrade to Java 1.5. Some of them might even do it. Now, how does one get the file associations to work? At the time I was looking at it (and still as I write this), Sun’s getting started guide is grossly incorrect when discussing the <association> tag in the JNLP file. The getting started guide also does not explain what changes to make to your application to get it to actually open the file when you double click on it.

The first part was easy – Keith Lea already documented the problem, and Google lead me straight to it. Add an <association> tag to your JNLP file, like this:

<association mime-type="application-x/some-mime-type" extensions="ext"/>

One step closer! Now I can click on my files and the application launches, but it doesn’t do anything with the file I opened. I took a guess that it was probably passing the filename in through the command line parameters, and put some message boxes into my main function. Sure enough, that’s how it’s being done. I’m being passed two options: -open, and then the filename to open. The following code in my main function dealt with this:


// Handle JNLP association command line argument file opening.
// Format: '-open' 'path-to-file'
boolean openFlag = false;
for (int i = 0; i < args.length; i++)
{
    if (openFlag)
        openPath(args[i]);

    if (args[i].equals("-open"))
        openFlag = true;
    else
        openFlag = false;
}

Now I’m happily taking advantage of the new features in JNLP 1.5, without forcing my users to upgrade if they don’t want to. It’s a happy day.

Adapting Classes

A few days ago, the wisdom of the java.io.Reader interface dawned on me suddenly, and at the same moment the world of interfaces came into a new light. I’ve always understood what an interface (or pure virtual class) is, and the purpose of them – they allow you to change the implementation of your class without changing the calling code. Some people have even told me that the use of interfaces can replace multiple inheritance – but I never really got how.

For those of you who are unaware, Reader is a basic interface that reads arrays of character data from “some source”. This seems like a good idea, of course. You get the data, and you don’t care about the source. Yay, nice and simple, and everyone is happy. Typically one creates a java.io.FileInputStream, creates a java.io.InputStreamReader (which implements Reader), and you’re off to the races.

One day, another class caught my eye: java.io.BufferedReader. This class implements the Reader interface, but doesn’t specify in the name any kind of data source. How does this class work? A BufferedReader takes another Reader instance as part of its constructor, and adapts it.

Why is this such a special idea? Because BufferedReader is not derived from InputStreamReader. As a result, any Reader can be buffered by this simple class. In the same way, other classes can adapt a BufferedReader to add additional functionality. A LineNumberReader can take a BufferedReader, an InputStreamReader, a KeyboardJunkReader, a RandomDataReader, or a ManagementBullshitReader – whatever Reader one wants to count the lines of. (The fact that LineNumberReader is derived from BufferedReader is irrelevant [and frankly, pointless...])

So, you’re thinking “fine, but so what?”. Let me give you an example of another simple interface that this kind of adapting would be cool for:

public interface XYDataset
{
    public int getCount();
    public Number getX(int index);
    public Number getY(int index);
}

This interface is pretty simple, and would be good as part of a plotting package. Any set of X and Y values could be plotted easily by creating an instance of this XYDataset wherever your data is. This is simple, effective, and cool. A basic implementation of this could have two List objects, or one List object, or … whatever, who cares – storing data is boring.

What if you find that some users are plotting thousands of points, and it’s very slow? Let’s create a filtering adapter class:

public class FilteringXYDataset implements XYDataset
{
    private XYDataset delegate;
    private int maxPoints = 1000; // only plot this many points.

    public FilteringXYDataset(XYDataset initDelegate)
    {
        delegate = initDelegate;
    }

    public int getCount()
    {
        int realCount = delegate.getCount();
        if (realCount < maxPoints)
            return realCount;
        else
            return maxPoints;
    }

    public Number getX(int index)
    {
        int correctItemCount = delegate.getCount();
        if (correctItemCount < numPts)
            return delegate.getX(index);

        int newIdx = (int)(correctItemCount * ((double)item / (double) maxPoints));
        return delegate.getX(newIdx);
    }
    // (repeat for getY)
}

Cool, the dataset is filtered now. It’s a crude filtering, but when you’re plotting a thousand points it’ll do nicely – it’s hard to tell a thousand points from ten thousand points on a normal screen sized plot.

What other dataset adapters could you use?

  • Add an extra 50% to the number of points, and generate them from a bezier smoothing curve.
  • Add a (0, 0) point to every dataset. Pretend the count is one greater, and then add the point in at the appropriate index.
  • Plotting arbitrary X-Y points on a log-log plot is impossible if the points are negative – so chop them out in another adapter class.

Adapting classes like this are simple and nifty – you take one interface, and provide the same interface back to the library user.

The really great part is that, without multiple inheritence, you can later create a dataset that is smoothed, filtered, and has negative points chopped out – all with one line of code. The smoothing and filtering algorithms are only written once, but can be applied in various orders and with various other tools. … and you still don’t know how the XYDataset is being stored. Good!

Some Nifty Things

Lately I seem to have pushed a large number of important projects to the side to make room for some smaller personal projects. Here’s what I’ve been thinking about lately that’s kinda nifty:

  • I gave notice of resignation to my employer earlier this week. October 8th is my final work day. I’ll be free for a few months to persue some contract work that I’ve got waiting in the wings, and then I’m into a new job in the new year. I’ll be working as the head of software development at a small start-up company. Exciting!

  • I built a new photo gallery system. This one builds on a number of features in flickr. It has tag based image catagorizing, EXIF photo information, and a small number of different image sizes that can be viewed. You can see it in action on my pictures page.

  • A new version of Java was released today. Java 1.5, Tiger, contains a number of boring features: autoboxing (saves some typing), a new for/in loop (saves some typing), and generics (saves some typing – may find some ClassCastExceptions waiting to happen at compile time). These seem to be the features everyone thinks are cool, but I think they’re pretty lame.

    That said, there are a couple of features that are cool. Java 1.5 adds the ability to change a function’s return type when it is being overridden. You can only change it to a subclass of the original type, but this makes a lot of sense. When you really think about it… it turns out that all it does is save you some typing. In any situation where you’d actually use this, you’d be doing some casting that you wouldn’t have to do anymore.

    Hmmm… so… what does it have that’s cool? Variable length argument lists… I’ve never missed these in Java before. Annotations look pretty cool, but if you think about the pretty static applications they have unless you recode your own compiler, they seem to be pretty much just a couple nice builtin features and a new way to add documentation. So… static imports? Yeah, that’s nice. Yay!

    I really wanted to be impressed with Java 1.5′s new features, since I’m doing a lot of Java development these days. But I can just type faster, and I’ll still retain backwards compatibility with people using Java 1.4.

  • I added HTTP Digest authentication into my Twisted based weblog aggregator. This allows me to view LiveJournal RSS feeds with a logged in user, and hence getting links to protected LiveJournal entries that m yuser can see. I submitted a small patch to urllib2 to make it work with those same LiveJournal feeds, and I may add real authentication support to twisted.web.client rather than the hacked support I’m currently using. Maybe this weekend, if I have the inclination.

Recursiveness

En route from Ottawa to Montreal, I spent about 20 minutes working on a Java assignment. Usually these assignments are quite boring, and this one was no exception. The basic assignment is to create a class that represents a single variable polynomial of given degree. Anyways, the polynomial needed a function to evaluate it for a given value, and eventually I coded up this:

    private double evalCoeff(int deg, double x)
    {
        if (deg == this.getDegree())
            return this.coefficients[deg];

        return evalCoeff(deg + 1, x) * x + this.coefficients[deg];
    }

    /**
     * Evaluate the polynomial for a given x value.
     *
     * @param x         The value.
     * @returns         The evaulated value.
     */
    public double evaluate(double x)
    {
        // Very, very slick.
        return evalCoeff(0, x);
    }

Isn’t that beautiful recursiveness? :)