Question

As it was made clear in my recent question, Swing applications need to explicitly call System.exit() when they are ran using the Sun Webstart launcher (at least as of Java SE 6).

I want to restrict this hack as much as possible and I am looking for a reliable way to detect whether the application is running under Webstart. Right now I am checking that the value of the system property "webstart.version" is not null, but I couldn't find any guarantees in the documentation that this property should be set by future versions/alternative implementations.

Are there any better ways (preferably ones that do not ceate a dependency on the the webstart API?)

Was it helpful?

Solution

When your code is launched via javaws, javaws.jar is loaded and the JNLP API classes that you don't want to depend on are available. Instead of testing for a system property that is not guaranteed to exist, you could instead see if a JNLP API class exists:

private boolean isRunningJavaWebStart() {
    boolean hasJNLP = false;
    try {
      Class.forName("javax.jnlp.ServiceManager");
      hasJNLP = true;
    } catch (ClassNotFoundException ex) {
      hasJNLP = false;
    }
    return hasJNLP;
}

This also avoids needing to include javaws.jar on your class path when compiling.

Alternatively you could switch to compiling with javaws.jar and catching NoClassDefFoundError instead:

private boolean isRunningJavaWebStart() {
    try {
        ServiceManager.getServiceNames();
        return ds != null;
    } catch (NoClassDefFoundError e) {
        return false;
    }
}

Using ServiceManager.lookup(String) and UnavailableServiceException is trouble because both are part of the JNLP API. The ServiceManager.getServiceNames() is not documented to throw. We are specifically calling this code to check for a NoClassDefFoundError.

OTHER TIPS

Use the javax.jnlp.ServiceManager to retrieve a webstart service. If it is availabe, you are running under Webstart.

See http://download.java.net/jdk7/docs/jre/api/javaws/jnlp/index.html

As you mentioned, checking the System property as follows is probably the cleanest way:

private boolean isRunningJavaWebStart() {
    return System.getProperty("javawebstart.version", null) != null;
}

In a production system I have used the above technique for years.

You can also try to check to see if there are any properties that start with "jnlpx." but none of those are really "guaranteed" to be there either as far as I know.

An alternative could be to attempt to instantiate the DownloadService us suggested by Tom:

private boolean isRunningJavaWebStart() {
    try {
        DownloadService ds = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService");
        return ds != null;
    } catch (UnavailableServiceException e) {
        return false;
    }
}

Of course that does have the downside of coupling your code to that API.

I have no real experience with Java web start other than looking at it a few years back.

How about start your application with a parameter that you define than you set when the app is started via Java web start.

If you want to pass in arguments to your app, you have to add them to the start-up file (aka JNLP descriptor) using or elements.

Then check to see if these properties are set.

Again this is a suggestion I have not coded for JWS and it may not be this easy.

You can check whether the current classloader is an instance of com.sun.jnlp.JNLPClassLoader (Java plugin 1) or sun.plugin2.applet.JNLP2ClassLoader (Java plugin 2). Despite the "applet" package, an applet using JNLP with the Java plugin 2 uses another classloader, sun.plugin2.applet.Applet2ClassLoader. It works with OpenJDK too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top