Example - using web-start SingleInstanceService

After seeing a number of vague questions

relating to the web-start SingleInstanceService,

I decided to give it a try myself.

It seems to work 'as advertised' with very

little effort on the part of the developer.

You can get my simple example here.

The JNLP launch file and source (in a zip)

can be obtained from ..

http://www.physci.org/jws/

..look for the 'singleapp' files.

Here is the complete example..

src/java/test/SingleInstanceApplication.javapackage test;

import java.awt.BorderLayout;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.border.EmptyBorder;

import java.util.Date;

// classes of the web-start API, used in this example.

import javax.jnlp.SingleInstanceListener;

import javax.jnlp.SingleInstanceService;

import javax.jnlp.ServiceManager;

import javax.jnlp.UnavailableServiceException;

/** A test of the SingleInstanceService using the web-start API.

@author Andrew Thompson

@version 2007/1/8

*/

publicclass SingleInstanceApplication

extends JFrame

implements SingleInstanceListener{

/** A simple editing area. */

JTextArea document;

/** Assemble the GUI. */

SingleInstanceApplication(){

super("JNLP API single instance service");

try{

SingleInstanceService singleInstanceService =

(SingleInstanceService)ServiceManager.

lookup("javax.jnlp.SingleInstanceService");

// add the listener to this application!

singleInstanceService.addSingleInstanceListener(

(SingleInstanceListener)this );

}catch(UnavailableServiceException use){

use.printStackTrace();

System.exit(-1);

}

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

document =new JTextArea(

"Try openning another version of this application\n");

document.setEditable(false);

JPanel main =new JPanel(new BorderLayout());

main.add(new JScrollPane(document));

main.setBorder(new EmptyBorder(8,8,8,8) );

getContentPane().add(main);

pack();

setSize(400,300);

setLocationRelativeTo(null);

}

/** Specified by the SingleInstanceListener interface

@param args The command line parameters used for this invocation */

publicvoid newActivation(String[] args){

StringBuffer sb =new StringBuffer();

for (int ii=0; ii<args.length; ii++){

sb.append("'" + args[ii] +"' ");

}

String message ="Got new args: " + sb.toString();

// this usually serves to alert the user the app.

// wants attention. On Win. it will flash the

// apps. icon in the task bar.

JOptionPane.showMessageDialog(this, message);

// also add the new args and time to the document.

document.append(new Date() +"\t" + message +"\n" );

}

/** Construct the GUI and display it. If the user double clicked

a file to start the application, begin measures to load that file. */

publicstaticvoid main(String[] args){

SingleInstanceApplication app =

new SingleInstanceApplication();

app.setVisible(true);

}

}

src/conf/singleapp.jnlp><?xml version='1.0' encoding='UTF-8' ?>

<jnlp spec='1.0'

codebase='http://www.physci.org/jws'

href='singleapp.jnlp'>

<information>

<title>Single Instance Application</title>

<vendor>Andrew Thompson</vendor>

<description kind='one-line'>

Test of the JNLP SingleInstanceService

</description>

<shortcut online='false'>

<desktop/>

</shortcut>

</information>

<resources>

<j2se version='1.2+' />

<jar href='singleapp.jar' main='true' />

</resources>

<application-desc main-class='test.SingleInstanceApplication' />

</jnlp>

build.xml<!-- Build filefor the project. -->

<project basedir="." default="launch" name="singleapp">

<target name="properties">

<property name="build" value="build" />

<property name="dist" value="dist" />

<property name="src" value="src" />

<!-- Pot luck guess at location of

suitable'web-start' jar. -->

<property

name="classpath"

value="${java.home}/lib/javaws.jar" />

</target>

<target

name="compile"

depends="properties"

description="Compile the project" >

<mkdir dir="${build}/share" />

<javac

debug="on"

destdir="${build}/share"

srcdir="${src}/java"

source="1.2"

classpath="${classpath}" />

<copy todir="${build}/share">

<fileset dir="${src}/java">

<exclude name="**/CVS" />

<exclude name="**/*.java" />

</fileset>

</copy>

</target>

<target

name="dist"

depends="compile"

description="Create project distribution" >

<mkdir dir="${build}/jar" />

<mkdir dir="${build}/jar/lib" />

<jar destfile="${build}/jar/singleapp.jar">

<fileset dir="${build}/share">

<include name="**/*.class" />

</fileset>

</jar>

</target>

<target

name="make-launch-file"

depends="properties"

description="Copies and configures the launch file" >

<copy todir="${build}/jar" >

<fileset dir="${src}/conf" >

<include name="**/*.jnlp" />

</fileset>

</copy>

</target>

<target

name="launch"

depends="dist, make-launch-file"

description="Launch the project using webstart">

<exec executable="javaws"

dir="${build}/jar">

<arg line="-codebase file:. file:./singleapp.jnlp" />

</exec>

</target>

<target

name="uninstall"

depends="properties"

description="Uninstall the project from the webstart cache">

<exec executable="javaws">

<arg

line="-uninstall http://www.physci.org/jws/singleapp.jnlp"

/>

</exec>

</target>

<target name="clean"

depends="properties"

description="Clean all generated files">

<delete dir="${build}" />

<delete dir="${dist}" />

</target>

</project>

[10732 byte] By [AndrewThompson64a] at [2007-11-26 14:22:55]
# 1

Hello,

many thanks for the code example, I have tried it and it helps a lot in understanding the structure.

Unfortunately it does not cover all my questions ...

I modified the code such that now a Java Web Start Applet is deployed. The first call works fine, but a second call of the same Applet get stuck, and I find the following Exception on the console:

Exception in thread "Thread-7" java.lang.NullPointerException

at com.sun.jnlp.SingleInstanceServiceImpl.getArguments(SingleInstanceServiceImpl.java:135)

at com.sun.deploy.si.SingleInstanceImpl$SingleInstanceServer.isSameInstance(SingleInstanceImpl.java:164)

at com.sun.deploy.si.SingleInstanceImpl$SingleInstanceServer$2.run(SingleInstanceImpl.java:211)

at java.security.AccessController.doPrivileged(Native Method)

at com.sun.deploy.si.SingleInstanceImpl$SingleInstanceServer.run(SingleInstanceImpl.java:173)

I can avoid this exception by adding a dummy argument when starting from command line:

javaws -open dummyArg -codebase ...

but that is no solution for the browser, is it?

Furthermore: I can see the dummy arg in the messagebox, but I don't get the applet parameters - is there a way to get them ?

Thank you for any hint.

h.bruecknera at 2007-7-8 2:15:08 > top of Java-index,Desktop,Deploying...
# 2

My apologies for the long delay in replying to

your pproblems with using SIS and applets.

Truth is..

1) I have not had time to try SIS with applets, and..

2) I was kind of hoping that one of the web start

gurus might field this one.

In any case, I have a few moments spare

and will offer up my best theory so far.

Web start was not designed to handle this

particular situation (note that is rather

extraordinary to associate files with an applet!).

Having said that, there might be a way you

can 'have your cake and eat it to', but it will

require some extra work.

What I suggest is this.

On first invocation, write the original applet

parameters to local disk using the

PersistenceService. If subsequesnt launches

provide a non null 'open' parameter, assume

the applet is being started from double clicking

a file, and load the original applet parameters

from local disk.

AndrewThompson64a at 2007-7-8 2:15:08 > top of Java-index,Desktop,Deploying...
# 3

Hi.

I ran the example but was not able to pass arguments.

I chained the arguments to the URL in the example in the format blabla?somearg=value.

Still, with every kind of URL I try - I get zero size arguments.

We must have this in order to be able to integrate with other web applications.

Thanks a bunch ...

daniel_orea at 2007-7-8 2:15:08 > top of Java-index,Desktop,Deploying...
# 4

Hello,

just let me summarize what I have learned about Java Web Start so far, maybe it is somewhat helpful:

- What works well is passing arguments to WebStart Applications using the related part in the .jnlp-file, e.g.:

<application-desc main-class='[MyMainClass]'>

<argument>First Argument</argument>

<argument>Last Argument</argument>

</application-desc >

- It also works well to use different .jnlp files if you just leave out the file name in the root element line, e.g.:

<jnlp spec='1.0' codebase='http://localhost/test'>

What then counts to identify the Instance is that you call the same jar file.

=> To pass different args, you may use different .jnlp files, or generate

the one you need dynamically.

What I still haven't solved so far is the combination of JWS- SingleInstanceService and Applets.

- You can pass Arguments as key-value pairs using the corresponding applet section in the .jnlp file.

- You can first start a JWS applet that initialize the SingleInstanceService

- However, further calls catched by the SingleInstanceService must attempt to start an application.

So, if you are happy with having just one big applet to work with, you should be able to make it fly...

Good luck!

h.bruecknera at 2007-7-8 2:15:08 > top of Java-index,Desktop,Deploying...