How can I run the installer for something else during module installation?

Apache NetBeans Wiki Index

Note: These pages are being reviewed.

Sometimes you are distributing some software with your module which has its own installer, or some other similar code which needs to be run once to get everything needed installed on the user’s system. If you are distributing some software (which perhaps you did not write), and it has its own installer, it is less work to just run its installer to be sure it is set up correctly, than to have your module do everything which that installer does too (and possibly get something wrong).

Autoupdate Services primary handles NetBeans plugins based on NBM packaging.

In addition, Autoupdate Services offers the possibility to install/uninstall components which are not in NBM format. This possibility has been designed to support such use-cases - for example, to install an application Servers such as GlassFish by running its own installer.

Using a native installer ensures that, if there are any problems with the way the software gets installed, it is a problem with the native installer, not your code.

To enable such possibility, Autoupdate Services API provides:

  • An SPI for providing such components

  • A custom installer can be assigned to the component which performs installation particular component into NetBeans

  • The ability to register that special provider among other of providers - a common Update Center

How to setup a Update Provider providing custom components?

Implement interface UpdateProvider to make a provider for your component that has its own installer. This provider has to:

  • Determine if the component is already installed on the target system.

  • If so, it should be able to tell which version, so the system knows if the bundled version is older, newer or the same version

  • Offer a component which is available to be installed into system,

  • Assign a specific installer which can install available components,

  • assign a specific uninstaller which can uninstall such component if is already installed

  • Register the application (i.e. store a path to the installed copy of the application) so that, at runtime, code that needs to use the custom-installed software can find it

A code snippet showing that provider

public class FooNativeComponentProvider implements org.netbeans.spi.autoupdate.UpdateProvider {...}

It has simple methods describing the provider, like this:

    public String getName () {
        return "Foo Update Provider";
    }

    public String getDisplayName () {
        return getName ();
    }

    public String getDescription () {
        return "Providing components with custom installers";
    }

    public CATEGORY getCategory () {
        return CATEGORY.STANDARD;
    }

The essential method getUpdateItems will return UpdateItems which matches these components. It has to return an UpdateItem both for installed component and for available component what has not been installed yet.

    public Map<String, UpdateItem> getUpdateItems () throws IOException {
        Map<String, UpdateItem> res = new HashMap<String, UpdateItem> ();


        // 1. provide already installed version

        // get installed version
        String installed = NbPreferences.forModule (FooNativeComponentProvider.class).get (FOO_CODE_NAME, null);

        // some foo-native-runtime is installed
        if (installed != null) {
            res.put (FOO_CODE_NAME + installed, getInstalledUpdateItem (installed));
        }

        // 2. provide also version available to install

        // for this example: If none version hasn't been installed yet then provider the version 3.0
        if (installed == null) {
            res.put (FOO_CODE_NAME + "_3.0", getAvailableUpdateItem ("3.0"));

        // if the version 3.0 is installed then provide newer version 3.1
        } else if ("3.0".equals (installed)) {
            res.put (FOO_CODE_NAME + "_3.1", getAvailableUpdateItem ("3.1"));
        }

        return res;
    }

There are two factory methods getInstalledUpdateItem and getAvailableUpdateItem. Both are using SPI UpdateItem.create(Installed)NativeComponent

Add an UpdateItem matching available component first. The provider has to specify a name, display name, download size and so forth.

The most important parts are CustomInstaller and CustomUninstaller. For example:

    private static UpdateItem getAvailableUpdateItem (String specificationVersion) {
        String displayName = "Foo Runtime " + specificationVersion;
        String description = "Foo Runtime " + specificationVersion + " with native installer";
        String downloadSize = "2815";
        CustomInstaller ci = FooInstaller.getInstaller ();
        assert ci != null;
        UpdateLicense license = UpdateLicense.createUpdateLicense ("none-license", "no-license");
        UpdateItem item = UpdateItem.createNativeComponent (
                                                    FOO_CODE_NAME,
                                                    specificationVersion,
                                                    downloadSize,
                                                    null, // dependencies
                                                    displayName,
                                                    description,
                                                    false, false, "my-cluster",
                                                    ci,
                                                    license);
        return item;
    }

Now, for an already-installed copy of the software:

    private static UpdateItem getInstalledUpdateItem (String specificationVersion) {
        String displayName = "Foo Runtime " + specificationVersion;
        String description = "Foo Runtime " + specificationVersion + " with own installer";
        CustomUninstaller cu = FooUninstaller.getUninstaller ();
        assert cu != null;
        UpdateItem item = UpdateItem.createInstalledNativeComponent (
                                                    FOO_CODE_NAME,
                                                    specificationVersion,
                                                    null, // dependencies
                                                    displayName,
                                                    description,
                                                    cu);
        return item;
    }

So, what does a custom installer look like? It it quite simple, look on

public class FooInstaller implements org.netbeans.spi.autoupdate.CustomInstaller {
    /** This code will be called back while installing the corresponding native component
     * from Plugin Manager Install Wizard.
     */
    public boolean install (String codeName, String specificationVersion, ProgressHandle handle) throws OperationException {
        // CustomInstaller has to start `org.netbeans.api.progress.ProgressHandle` !!!
        handle.start ();

        // a custom code which invokes installation of native component actually
        .......
    }
}

How to register UpdateProvider in my application?

Using META-INF/services or (in NetBeans 6.9) the @ServiceProvider annotation (see Geertjan’s blog for more info):

  1. Make a META-INF/services folder in sources of your NetBeans project where the provider is,

  2. Make a file org.netbeans.spi.autoupdate.UpdateProvider in this folder,

  3. Type name of class where UpdateProvider implemented, i.e. org.netbeans.modules.fooupdateprovider.FooNativeComponentProvider

And , that’s it, the NetBeans Lookup system will read it and includes that provider among other providers registered in NetBeans application.

A sample project having this UpdateProvider

Important Note

Don’t apply this Update Provider earlier than NetBeans 6.5 release will be out. There were several problem which had to be fixed in NetBeans 6.5. Use NetBeans 6.5 or some of recent Development builds rather than previous releases 6.1 or 6.0!

- Do not hesitate to contact me on mailto:jrechtacek@netbeans.org if you have any question.