O'Reilly logo

Swing Hacks by Chris Adamson, Joshua Marinacci

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

424
|
Chapter 11, Native Integration and Packaging
#84 Construct Single-Launch Applications
HACK
String track_name = track.name( );
String album_name = track.album( );
String artist_name = track.artist( );
com4j is a great open source project that unleashes the power of Java code
integrated with native applications. The iTunes COM interface provides
hooks for virtually everything that iTunes can do. These two things mean
you could write a program to sort songs, create new playlists, or even export
track listings to your own application that prints CD labels. You can find
fscom/sdk/itunescomsdk.html, so see what other cool things you can come up
with.
H A C K
#84
Construct Single-Launch Applications Hack #84
Only allow one instance of a program, notifying the existing instance when
the user tries to launch a new one.
Most graphical desktop applications are designed for multitasking. You start
your program to work on something, then switch to another program and
come back later. Oftentimes you’ll leave a large program, like a word pro-
cessor, running in the background to be used again when you need to open
another document, say an email attachment you received. When you click
on the attachment, your operating system won’t start a new instance of the
word processor; instead, it will send a message to the currently running
instance to open the new file—saving lots of system resources.
Java programs aren’t designed with single-launch behavior in mind. They
still use the old Unix style of single use, command-line launching. You start
the program to do something and it finishes quickly. If you use the program
again it will start a new instance, do the work, and finish. There is never any
instance reuse, but modern desktop programs demand it. Because Java
doesn’t support single-launch applications, this hack shows you how to
build it into your programs with a simple use of sockets.
Local Sockets
Building a single-launch application requires two parts. When the program
starts, it needs to detect if another copy is already running. If there is, then
the program can quit instead of continuing to launch. The new program also
needs to tell the first copy about any command-line arguments—the file-
name to open, for example. You could create a temp file in a known loca-
tion and look to see if it already exists. This would take care of multiple
program instances, but not passing arguments around. Plus, you would
need to worry about race conditions and cleaning up the temp file when the
last program exits. Thankfully, there’s a much better solution: local sockets.
Construct Single-Launch Applications #84
Chapter 11, Native Integration and Packaging
|
425
HACK
A socket is a network connection defined by a hostname and a port. A local
socket is a network connection only on the local machine. When you open a
socket to listen for connections you are binding to that port. Only one pro-
gram can bind to any given port at one time, so the port itself can serve as
your lock. If your program cannot connect to the port, then another pro-
gram must already be using it. It doesn’t matter what the port number is, as
long as your program always uses the same one. Here is the beginning of the
code to put this into action:
public class SingleLauncherApplication implements Runnable {
public static final int PORT = 38629;
public JLabel label;
public ServerSocket server;
public void launch(String[] args) {
try {
server = new ServerSocket(PORT);
new Thread(this).start( );
firstMain(args);
} catch (IOException ioex) {
System.out.println("already running!");
relaunch(args);
}
}
SingleLauncherApplication is a class with one core method: launch( ).
launch( ) takes the same arguments as the standard main( ) method, which is
important since you are essentially creating fake versions of main. When
launch is called, it will first try to bind to the port by creating a server
socket. Notice the
PORT constant set to the number 38629. It is important
that the port isn’t reserved for use by any system services. Some operating
systems also restrict user programs to only use ports over 1,000, so I picked
this number at random from the 20,000 to 60,000 range. This makes it very
unlikely that the port will already be in use by any other program.
If
launch( ) can create a ServerSocket, then it will start a new thread, engage
run( ), and then call firstMain( ):
public void firstMain(String[] args) {
JFrame frame = new JFrame("Single Launch Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String word = "";
if(args.length >= 1) {
word = args[0];
}
label = new JLabel("The word of the day is: " + word);
frame.getContentPane( ).add(label);
frame.pack( );
frame.show( );
}

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required