JDK-8181293 : Singleton for javapackager
  • Type: CSR
  • Component: deploy
  • Sub-Component: packager
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 10
  • Submitted: 2017-05-30
  • Updated: 2017-07-05
  • Resolved: 2017-07-05
Related Reports
CSR :  
Description
Summary
-------

Add functionality to launch single instance apps (for javapackager).

Problem
-------

For java apps bundled with javapackager, Windows and Linux by default launch new instance of the application (MacOS does the same thing if user launches it using .../<appname>.app/Contents/MacOS/<appname> file). We need to provide to the users a way to launch single instance apps. In addition, we need to provide API to pass arguments of the new (second) instance to the already running application (first instance). The first instance needs to be reactivated after user launches second one (the latter terminates after passing arguments).

Solution
--------

Add checks for single instance in the code of javapackager launcher. In case if existing instance is not detected, continue regular launch. Otherwise, try to reactivate existing instance and pass provided arguments (if any).
Add new interface to pass arguments to the existing instance: jdk.packager.services.singleton.SingleInstanceListener. User will need to override one method to handle new arguments: "pubic void newActivation(String[] params)". To register and unregister the listener, user will need to use public methods of jdk.packager.services.singleton.SingleInstanceService.
Add jdk.packager.services.singleton.SingleInstanceImpl to encapsulate implementation details of single instance of the packager (on java side). Add additional option for Mac for setting java.awt.desktop.OpenFilesHandler, so the listener will be notified when the application is asked to open a list of files

Specification
-------------

There will be new option for javapackager: "-singleton". The option prevents from launching multiple instances of application.

New interface jdk.packager.services.singleton.SingleInstanceListener will be used to handle the single instance behaviour - how should the application handle the arguments when another instance of the application is invoked with parameters. javadoc will be added for the interface and its methods. Users will need to override one method of the SingleInstanceListener to handle new arguments: "pubic void newActivation(String[] params)".

To pass arguments of the new (second) instance to the already running application (first instance), users will have to register / unregister app using the following three public methods of jdk.packager.services.singleton.SingleInstanceService(the class doesn't have other public methods/fields)::

    
 

    /**
     * The {@code SingleInstanceService} class provides public methods for using
     * Single Instance functionality for Java Packager. To use these methods,
     * the option named "-singleton" must be specified on javapackager command line.
     *
     * @since 10
     */
    public class SingleInstanceService {

        /**
         * Registers {@code SingleInstanceListener} for current process.
         * If the {@code SingleInstanceListener} object is already registered, or
         * {@code slistener} is {@code null}, then the registration is skipped.
         * 
         * @param slistener the listener to handle the single instance behaviour.
         * @param setFileHandler if {@code true}, the listener is notified when the
         *         application is asked to open a list of files. If OS is not MacOS,
         *         the parameter is ignored.
         */
        public static void registerSingleInstance(SingleInstanceListener slistener, boolean setFileHandler);
    
        /**
         * Registers {@code SingleInstanceListener} for current process.
         * If the {@code SingleInstanceListener} object is already registered, or
         * {@code slistener} is {@code null}, then the registration is skipped.
         * 
         * @param slistener the listener to handle the single instance behaviour.
         */
        public static void registerSingleInstance(SingleInstanceListener slistener);
    
        /**
         * Unregisters {@code SingleInstanceListener} for current process.
         * If the {@code SingleInstanceListener} object is not registered, or
         * {@code slistener} is {@code null}, then the unregistration is skipped.
         * 
         * @param slistener the listener for unregistering.
         */
        public static void unregisterSingleInstance(SingleInstanceListener slistener);
    }
    
    /**
     * The {@code SingleInstanceListener} interface is used for implementing
     * Single Instance functionality for Java Packager.
     *
     * @since 10
     */
    public interface SingleInstanceListener {
    
        /**
         * This method should be implemented by the application to
         * handle the single instance behaviour - how should the application
         * handle the arguments when another instance of the application is
         * invoked with params.
         *
         * @param params parameters for the application main
         */
        public void newActivation(String... params);
    }


    





Comments
Moving the request to approved.
05-07-2017

I modified SingleInstanceListener - now newActivation is a varargs method. private constructor will be added for SingleInstanceService class.
30-06-2017

With several comments, moving the request to provisional. I do recommend varargs for this use case; I declare my main methods to use varargs. If you insist on not using varargs, I will still approve the request in the future. Checking the webrev, the new public class SingleInstanceService does not declare a constructor and thus will get a public default constructor. Please add a private constructor to the class to prevent this.
28-06-2017

These methods are in jdk.packager.service module. I updated the declaration of methods/class.
27-06-2017

"public" will be removed for the methods: "public static void enableDebug(boolean enable, PrintStream stream) ", "public static void trace(String message)", "public static void trace(Throwable t)", "public static boolean isServerRunning(String id)", "public static boolean connectToServer(String[] args)", "public static void registerSingleInstanceForId(SingleInstanceListener slistener, String stringId, boolean setFileHandler)" "public static void checkForSingleInstance(String stringId, String[] args)" will be removed. "public getSingleInstanceListener()" will be removed. We can use varargs here, but my thought was that the interface should be more similar to typical java main (String[])
27-06-2017

Please show the declaration of the new methods within the context of the declaration of SingleInstanceService. What module are these methods in? When you are ready to have the proposal to go through further csr review, please change the state to Proposed or Finalized.
27-06-2017

Catching up on review, for the CSR, a more detailed accounting of the API specification needs to be associated with the request, either in-line in the specification section or attached as a webrev or other representation. Comments looking at the webrev, the SingleInstanceListener itself needs javadoc, as does the getSingleInstanceListener method. In addition, should newActivation be a varargs methods? Moving the request to pended.
20-06-2017