Preventing multiple instances of an application to start

P

Philipp

Hello, I had the problem that I did not want multiple instances of my
application to start. I would like instead to have the command line
parameters (file paths in my case) of a second starting instance to be
forwarded to the first already running app (eg. if someone double-clicks
on an associated file type).
Here is the solution I came up with (posting it for future reference).
Any comments/corrections are welcome (this is my first try at RMI).

Phil

-- RemoteContactInterface.java --
import java.io.File;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteContactInterface extends Remote {
void loadFile(File f) throws RemoteException;
}


-- MyMainClass.java --
import java.io.File;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class MyMainClass extends JFrame implements RemoteContactInterface {

MyMainClass(){
// start RMI server
try {
int PORT = 1099;
LocateRegistry.createRegistry(PORT);
RemoteContactInterface stub =
(RemoteContactInterface)UnicastRemoteObject.exportObject(this, PORT);
Registry registry = LocateRegistry.getRegistry();
registry.bind("myClassID", stub);
System.out.println("Server ready");
} catch (Exception e) {
System.err.println("RMI Server exception: " + e.toString());
e.printStackTrace();
}

setDefaultCloseOperation(EXIT_ON_CLOSE);
this.getContentPane().add(new JLabel("Hello World"));
pack();
setVisible(true);

}

public static void main(String args[]) {
try {
Registry registry = LocateRegistry.getRegistry(null);
RemoteContactInterface stub = (RemoteContactInterface)
registry.lookup("myClassID");
for(String s: args){
File f = new File(s);
stub.loadFile(f);
}
System.out.println("App already running");
System.exit(0);
} catch (Exception e) {
// if exception is thrown, no other process already exists
// go on with normal loading
}

SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyMainClass myClass = new MyMainClass();
}
});

}

public void loadFile(File f) throws RemoteException {
// load the file here;
}
}
 
A

Andrew Thompson

Philipp said:
Hello, I had the problem that I did not want multiple instances of my
application to start. I would like instead to have the command line
parameters (file paths in my case) of a second starting instance to be
forwarded to the first already running app (eg. if someone double-clicks
on an associated file type).

Note that web-started* applications can make use of the
SingleInstanceService to avoid furrther instances.

* ..and will also offer support for file associations.

Andrew T.
 
P

Philipp

Andrew said:
Note that web-started* applications can make use of the
SingleInstanceService to avoid furrther instances.

Hmm... You mean I should have read the doc? :)
 
A

Andrew Thompson

Philipp said:
Hmm... You mean I should have read the doc? :)

10% yes/90% "might this app. be suited to launch
using web-start?" (not all projects are suited to
web-start install/launch.)

Andrew T.
 
A

Andrew Thompson

Tor said:
"Andrew Thompson" <[email protected]> writes:

(single instance of application)
A common trick is to try and open some serversocket on a particular
unlikely-to-be-used port number .. ....
Another trick is to write a ".lock" or ".pid" file to the file system
and test for its existence, remembering to remove it at the end. This
is less relibable than the first because the app can crash wothout
being able to remove the file, so the user has to hunt for it.

Yes. I would far prefer to use the first strategy,
probably also allowing the user to set the port
number (to cover possible clashes).

(Assuming I could not simply rely on JWS to
do it for me - to be honest - I have never really
needed to code a SIA, so for my part, it is all
theoretical.)

Andrew T.
 
T

Tom Hawtin

Tor said:
Another trick is to write a ".lock" or ".pid" file to the file system
and test for its existence, remembering to remove it at the end. This
is less relibable than the first because the app can crash wothout
being able to remove the file, so the user has to hunt for it.

Isn't the idea to put the process id in the file. Then if the file
exists, the new process to check whether the process that created the
file still exists. Still very hacky, but slightly more reliable.

Tom Hawtin
 
T

Tor Iver Wilhelmsen

Andrew Thompson said:
10% yes/90% "might this app. be suited to launch
using web-start?" (not all projects are suited to
web-start install/launch.)

A common trick is to try and open some serversocket on a particular
unlikely-to-be-used port number, (like 11544) and failing if it cannot
(because another running instance has done so).

Another trick is to write a ".lock" or ".pid" file to the file system
and test for its existence, remembering to remove it at the end. This
is less relibable than the first because the app can crash wothout
being able to remove the file, so the user has to hunt for it.
 
P

Philipp

Tor said:
A common trick is to try and open some serversocket on a particular
unlikely-to-be-used port number, (like 11544) and failing if it cannot
(because another running instance has done so).

Another trick is to write a ".lock" or ".pid" file to the file system
and test for its existence, remembering to remove it at the end. This
is less relibable than the first because the app can crash wothout
being able to remove the file, so the user has to hunt for it.

I read about these two methods. But aren't they much more ugly than
using RMI which is precisely tailored to speak to other running apps?

Also, is it possible to pass new arguments using these methods? (I don't
think so).

I'm surprised that the two methods you cite are written all over the
web, but the RMI method is nowhere to be found. Is there anything wrong
with it?

Phil
 
C

Chris Uppal

Philipp said:
I'm surprised that the two methods you cite are written all over the
web, but the RMI method is nowhere to be found. Is there anything wrong
with it?

In essence the RMI-based approach is the same as the socket-based one.

There are minor differences of course. The RMI one makes it easier to extend to
passing data across to the previous running instance. The RMI one is probably
easier to code if you are used to RMI, but harder to code if you are used to
sockets. The sockets based one may use rather fewer OS resources. It might be
a bit easier to control security with raw sockets. And so on...

My personal feeling (I know socket programming but have never really used RMI)
is that the RMI solution is somehow too heavyweight (taking a hammer to crack a
nut) unless you are going to make use of the "RMI-ness", but that could just be
prejudice.

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top