Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Guide to Separate JRE Versions From NetBeans Platform Installer

DZone's Guide to

Guide to Separate JRE Versions From NetBeans Platform Installer

In this post, I'll show you how to separate the NetBeans installer from a packaged JRE, so that you can ensure a compatible and updated version of JRE on client machines while keeping it isolated from the rest of the system.

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

In an enterprise set up where updating Java on a client machine is not allowed due to software restriction policy, it becomes challenging to develop and ship applications which require the latest version of Java to be installed on client machines. One way to circumvent this policy-based restriction is to bundle the JREs for 32-bit and 64-bit Windows OS in a separate NetBeans platform installer. This ensures that the JRE remains isolated from the system and conflict with any older version of Java is avoided. This method is detailed in an excellent article written by  Ernest Lotter.

However, the bundling of JRE with the application forces you to maintain separate copies of the installer for 32-bit and 64-bit versions of Java. It also ties the application with the version of Java which was available at that point in time. In a scenario where development and improvement is a continuous process, one would love to have the flexibility of using the latest Java features in the application being developed and at the same time be able to deliver the latest version of Java to client machines.

This can be achieved by separating the NetBeans installer from the packaged JRE. This helps in maintaining only one copy of the installer (one for every release) per OS, keeping the size of the installer small, and ensuring a compatible and updated version of JRE on client machines that will be isolated from the rest of the system. 

So, allow me to show you how it's done...

Step-by-Step Guide to Separate JRE Versions from NetBeans Platform Installer

Note: The client machine where the application is to be installed must mandatorily have Java 7 or above installed on it for launching NetBeans 8 based platform installer.

Step 1 - Create Zipped Bundles of JRE for Downloading From Web Server


Go to your 32-bit JDK home installed on your computer; open the JRE folder and create a zip file containing lib and bin folders. If you have a 64-bit version of JDK with you, then create another bundle and name it appropriately. Copy the two zipped files and host them on a web server.

For example, I created jre-x86.zip for Windows 32-bit and jre-x64.zip for 64-bit OS, then hosted them on a web server. The zipped files will be downloaded by the installer using paths http://<serverIP:port>/jres/jre-x86.zip and http://<serverIP:port>/jres/jre-x64.zip respectively.

Step 2 - Create File DownloadZippedJreDuringInstall.java under NetBeans Harness Path: C:\Program Files\NetBeans 8.1\harness\nbi\stub\ext\components\products\helloworld\src\org\mycompany\DownloadZippedJreDuringInstall.java


Toward the final stages of installation, the program below checks for bitness of the OS and chooses the appropriate JRE which is downloaded and unzipped in the application home folder.

(Copied and adapted from, http://www.java2s.com/Tutorial/Java/0180__File/UnpackanarchivefromaURL.htm)

package org.mycompany;

/**
 *
 * @author 
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class DownloadZippedJreDuringInstall {



public static void downloadJreFromURL(){
try{
boolean is64bit = false;
        if (System.getProperty("os.name").contains("Windows")) {
            is64bit = (System.getenv("ProgramFiles(x86)") != null);
        } else {
            is64bit = (System.getProperty("os.arch").indexOf("64") != -1);
        }
        URL url = new URL("http://<serverIP:port>/jres/jre-x86.zip");
        if(is64bit){
         url = new URL("http://<serverIP:port>/jres/jre-x64.zip");
        }

        //create directory name "jre" under application home folder
File userHome = new File(System.getProperty("user.home")+File.separator+"Applications");
        userHome.mkdir();

        File target = new File(userHome, "jre");

        File tmpZipFile = unpackArchive(url, target);
        tmpZipFile.delete();
    }catch(Exception e){
    e.printStackTrace();
    }
}

    /**
     * Unpack an archive from a URL
     *
     * @param url
     * @param targetDir
     * @return the file to the url
     * @throws IOException
     */
    public static File unpackArchive(URL url, File targetDir) throws IOException {
        if (!targetDir.exists()) {
            targetDir.mkdirs();
        }
        InputStream in = new BufferedInputStream(url.openStream(), 1024);
        // make sure we get the actual file
        File zip = File.createTempFile("tmp", ".zip", targetDir);
        OutputStream out = new BufferedOutputStream(new FileOutputStream(zip));
        copyInputStream(in, out);
        out.close();
        return unpackArchive(zip, targetDir);
    }

    /**
     * Unpack a zip file
     *
     * @param theFile
     * @param targetDir
     * @return the file
     * @throws IOException
     */
    public static File unpackArchive(File theFile, File targetDir) throws IOException {
        if (!theFile.exists()) {
            throw new IOException(theFile.getAbsolutePath() + " does not exist");
        }
        if (!buildDirectory(targetDir)) {
            throw new IOException("Could not create directory: " + targetDir);
        }
        ZipFile zipFile = new ZipFile(theFile);
        for (Enumeration entries = zipFile.entries(); entries.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            File file = new File(targetDir, File.separator + entry.getName());
            if (!buildDirectory(file.getParentFile())) {
                throw new IOException("Could not create directory: " + file.getParentFile());
            }
            if (!entry.isDirectory()) {
                copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(file)));
            } else if (!buildDirectory(file)) {
                throw new IOException("Could not create directory: " + file);
            }
        }
        zipFile.close();

        return theFile;
    }

    public static void copyInputStream(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int len = in.read(buffer);
        while (len >= 0) {
            out.write(buffer, 0, len);
            len = in.read(buffer);
        }
        in.close();
        out.close();
    }

    public static boolean buildDirectory(File file) {
        return file.exists() || file.mkdirs();
    }
}


Step 3. Modify file ConfigurationLogic.java in Two Places

Open file C:\Program Files\NetBeans 8.1\harness\nbi\stub\ext\components\products\helloworld\src\org\mycompany\ConfigurationLogic.java.

1. Add import statement

import org.netbeans.installer.utils.system.launchers.LauncherResource;


2. Go to the end of the install method and add the following lines:

File target = new File(installLocation, "jre");
DownloadZippedJreDuringInstall.downloadJreFromURL();

// to add uninstaller logic:
SystemUtils.getNativeUtils().addUninstallerJVM(new LauncherResource(false, target));


 3. And, just before the last line of the uninstall method, add:

File jre = new File(installLocation, "jre");
if (jre.exists()) {
  try {
    for (File file : FileUtils.listFiles(jre).toList()) {
    FileUtils.deleteOnExit(file);
}
FileUtils.deleteOnExit(installLocation);
} catch (IOException e)
  {
    // ignore
  }
}


4. Set Application Installation Path: Open file  C:\Program Files\NetBeans 8.1\harness\nbi\stub\ext\infra\build\products\helloworld\build.properties in the text editor

Modify Key product.properties.2.value as:

product.properties.2.value=$S{user.home}/Applications/{product-install-directory-name-windows}


This sets the application home path to c:/<userhome>/Applications/<myapp> on Windows OS

5. Modify the NetBeans platform project.properties file.

At end of the file, add the line:

jdkhome="jre"


6. Create the installer:

Right-click Netbeans Platform project and select clean and build and then package as installer.

After few seconds your application installer will appear in the form of .exe file in the dist folder, ready to be shipped. Try to install the application by double clicking the exe. Towards the end of installation you will notice a folder named jre is created under the application folder located in the user home, i.e.c:/<userhome>/Applications/<myapp>/jre. Soon thereafter, lib and bin folders with the appropriate JRE get copied into it.

The installation also creates a shortcut on the desktop which can be double-clicked to launch your application. The application will be launched using the private JRE.

Thanks for taking the time to read my article. Hope it was helpful!

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:
netbeans 8 ,jdk ,java ,installer

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}