How to Build a Web Application in Java, package as a .exe file to run as a Desktop Application

Published Jun 23, 2017
How to Build a Web Application in Java, package as a .exe file to run as a Desktop Application

In this post I am going to show you how to build a web application in Java, then package the application as a .exe file and install and run the application like desktop application.

In this tutorial you will need to create a java web application (Maven) using NetBeans or any other IDE of your choice.


Next add the following dependencies to your pom file.

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="" xmlns:xsi="" xsi:schemaLocation="">






Now we are going to create a login page, this will be the first screen a user will see. In your webapp directory open index.html and add the following lines of code.

<!DOCTYPE html>
        <title>Start Page</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <h1>Login to your desktop application</h1>
        <input type="text" value="User Name">
        <input type="password" value="Password">
        <input type="submit" value="Sign In">

Great! Now create a package called "launch" and create two java classes called "" and "". Here are the content of both files.

 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
package launch;

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Frame extends Application {
  * @author Onuche Idoko
    private Scene scene;
    @Override public void start(Stage stage) {
        // create the scene
        stage.setTitle("Desktop Application");
        scene = new Scene(new Browser(),750,500, Color.web("#666970"));
        //scene.getStylesheets().add("webviewsample/BrowserToolbar.css");       ;
    public static void main(String[] args){
class Browser extends Region {
    final WebView browser = new WebView();
    final WebEngine webEngine = browser.getEngine();
    public Browser() {
        //apply the styles
        // load the web page
        //add the web view to the scene
    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    @Override protected void layoutChildren() {
        double w = getWidth();
        double h = getHeight();
        layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
    @Override protected double computePrefWidth(double height) {
        return 750;
    @Override protected double computePrefHeight(double width) {
        return 500;

package launch;


import javax.swing.JOptionPane;

import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.DirResourceSet;
import org.apache.catalina.webresources.StandardRoot;
import org.apache.tomcat.util.descriptor.web.ContextResource;

public class Main {

     * @author Onuche Idoko
     * @param args
     * @throws java.lang.Exception
    public static void main(String[] args) throws Exception {

        File file_path = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        String path = file_path.getAbsolutePath();

        String linux_path = FilenameUtils.separatorsToUnix(path);

        String[] split_path = linux_path.split("/DesktopApp/target");

        String path_to_win = split_path[0];

        String windows_path = FilenameUtils.separatorsToWindows(path_to_win);
        System.out.println("APPLICATION IN : " + windows_path);
        int code = 0;
        try {

            URL siteURL = new URL("http://localhost:9821/DesktopApp");
            HttpURLConnection connection = (HttpURLConnection) siteURL

            code = connection.getResponseCode();
        } catch (Exception e) {


        if (code != 200) {

            String appDir = windows_path;

            String webappDirLocation = appDir + "/DesktopApp/src/main/webapp/";
            Tomcat tomcat = new Tomcat();

            //The port that we should run on can be set into an environment variable
            //Look for that variable and default to 9821 if it isn't there.
            String webPort = System.getenv("PORT");
            if (webPort == null || webPort.isEmpty()) {
                webPort = "9821";
            } else {
                JOptionPane.showMessageDialog(null, "System Error!!!", "System Error", JOptionPane.ERROR_MESSAGE);


            // Additions to make @WebServlet work
            String buildPath = appDir + "/DesktopApp/target/classes";
            String webAppMount = "/WEB-INF/classes";

            File contextConfigFile = new File(webappDirLocation + "/" + "META-INF/context.xml");

            StandardContext context = (StandardContext) tomcat.addWebapp("/DesktopApp", new File(webappDirLocation).getAbsolutePath());
            File additionalWebInfClasses = new File(buildPath);


            WebResourceRoot resources = new StandardRoot(context);
            resources.addPreResources(new DirResourceSet(resources, webAppMount, additionalWebInfClasses.getAbsolutePath(), "/"));

            System.out.println("configuring app with basedir: " + new File("./" + webappDirLocation).getAbsolutePath());



        } else if (code == 200) {
            JOptionPane.showMessageDialog(null, "Application already running!!!", "Desktop App", JOptionPane.WARNING_MESSAGE);

The loads the content of your web application in a frame, while the is responsible for launching your application. Now our app is running as expected.


Finally, you need to build and package your application into a .exe using NSISStudio

Discover and read more posts from Onuche Idoko
get started