Run JNLP Apps in the Browser

Run a working example of a JNLP application or applet

This tutorial runs two Java Web Start (JNLP) examples in the browser with CheerpJ: a standalone application and an applet. You read the JAR files and the main class from the .jnlp file, then start the application from your own page with the CheerpJ API.

To open JNLP files from the pages that already launch them, without writing a page of your own, use the JNLP Runner browser extension.

The tutorial has two parts:

Prerequisites

For either example you need:

  • The .jnlp file (given below)
  • Node.js (>= 18)
  • A local HTTP server that supports Range requests, such as npx http-server
  • A text editor to create and edit an HTML file
  • A modern browser such as Chrome, Edge, Firefox or Safari

If you already have a JNLP application and want to run it in the browser, see the JNLP quickstart.

JNLP application: SwingSet3

1. The .jnlp file

Start with the JNLP file. Below is a JNLP file for SwingSet3, the Swing demo application. Three elements are highlighted:

  • The code base: the codebase attribute of <jnlp>. It is the URL the application files are downloaded from.
  • The JAR files: the <jar> tags in the <resources> section.
  • The class name: the main-class attribute of <application-desc>. The <application-desc> tag also tells you that this is a standalone application.
SwingSet3.jnlp
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc.//DTD JNLP 1.5//EN">
<jnlp codebase="https://raw.githubusercontent.com/leaningtech/cheerpj-meta/main/examples/SwingSet3/" href="SwingSet3.jnlp" spec="6.0+">
<information>
<title>SwingSet3</title>
<vendor>Oracle America, Inc.</vendor>
<homepage href="https://swingset3.dev.java.net"/>
<description>Demo to showcase features of the Swing UI toolkit in Java 6</description>
<icon href="swingset3/resources/images/splash.png" kind="splash"/>
<offline-allowed/>
<shortcut online="true"/>
</information>
<resources>
<j2se version="1.6+"/>
<jar href="SwingSet3.jar" main="false"/>
<jar href="lib/AppFramework.jar"/>
<jar href="lib/TimingFramework.jar"/>
<jar href="lib/swing-worker.jar"/>
<jar href="lib/swingx.jar"/>
</resources>
<application-desc main-class="com.sun.swingset3.SwingSet3"/>
</jnlp>

2. Download the application files

Build the full URL of each JAR by appending its href to the codebase URL, then open it in the browser to download it. For example:

https://raw.githubusercontent.com/leaningtech/cheerpj-meta/main/examples/SwingSet3/SwingSet3.jar

Do this for every JAR in the JNLP file, keeping the lib/ paths. The manifest of SwingSet3.jar also lists lib/AnimatedTransitions.jar and lib/javaws.jar in its Class-Path; download them from the same code base.

3. Create a project directory

Create a directory for the files. Any name works, for example cheerpj-example-swingset3:

Terminal window
mkdir cheerpj-example-swingset3

Recreate the directory structure used in the JNLP file. For this example that is a lib subdirectory:

Terminal window
cd cheerpj-example-swingset3
mkdir lib

Move the JARs into place, following the paths in the JNLP file:

└──cheerpj-example-swingset3
├── SwingSet3.jar
└── lib
├── AnimatedTransitions.jar
├── AppFramework.jar
├── javaws.jar
├── swing-worker.jar
├── swingx.jar
└── TimingFramework.jar

4. Create an HTML file

In cheerpj-example-swingset3, create a file called index.html:

index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>SwingSet3 (CheerpJ)</title>
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>
<style>
html,
body {
margin: 0;
}
#container {
width: 100vw;
height: 100svh;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="module">
await cheerpjInit();
cheerpjCreateDisplay(-1, -1, document.getElementById("container"));
await cheerpjRunJar("/app/SwingSet3.jar");
</script>
</body>
</html>

What is going on?

  • The <script> tag in the <head> loads CheerpJ:
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>

This example uses cheerpjRunJar() because SwingSet3.jar names its main class in its manifest. When a JAR does not, use cheerpjRunMain() with the main-class from the JNLP file and the JARs as the class path, for example cheerpjRunMain("com.sun.swingset3.SwingSet3", "/app/SwingSet3.jar:/app/lib/AppFramework.jar:...").

5. Host your page locally

From the project directory, serve the files over HTTP. Vite works well during development because it reloads the page when the files change:

Terminal window
npx vite

Alternatively, use the http-server utility:

Terminal window
npx http-server -p 8080

Open the URL shown in the terminal, for example http://127.0.0.1:8080/.

Note
The server must support HTTP Range requests, and the page cannot be opened from file://. Python’s http.server does not support Range requests. See basic server setup.

The result

The application runs in the browser:

Source code and credits

JNLP applet: Pitch

This part uses the Pitch applet from NASA’s Beginner’s Guide to Aeronautics. The applet is an interactive animation of an aircraft’s pitch motion. See more.

1. The .jnlp file

Start with the JNLP file. Below is a JNLP file for the Pitch applet. Three elements are highlighted:

  • The code base: the codebase attribute of <jnlp>. It is the URL the applet files are downloaded from.
  • The JAR files: the <jar> tags in the <resources> section.
  • The class name: the main-class attribute of <applet-desc>. The <applet-desc> tag also tells you that this is an applet, and gives its width and height.
PitchApplet.jnlp
<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for Pitch applet -->
<jnlp
spec="1.0+"
codebase="https://raw.githubusercontent.com/leaningtech/cheerpj-meta/main/examples/Pitch-Applet/"
href="PitchApplet.jnlp">
<information>
<title>Pitch</title>
<vendor>NASA Glenn Research Center</vendor>
<homepage href="https://www.grc.nasa.gov/WWW/K-12/airplane/"/>
<description>Pitch motion simulator</description>
<description kind="short">Beginner's Guide to Aeronautics - Pitch motion simulator written in Java</description>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="1.4+" initial-heap-size="30m" max-heap-size="300m" />
<jar href="Pitch.jar"/>
</resources>
<applet-desc main-class="Pitchview" width="500" height="300"/>
</jnlp>

2. Download the applet file

Build the full URL of the JAR by appending its href to the codebase URL, then open it in the browser to download it:

https://raw.githubusercontent.com/leaningtech/cheerpj-meta/main/examples/Pitch-Applet/Pitch.jar

3. Create a project directory

Create a directory for the files. Any name works, for example cheerpj-example-applet:

Terminal window
mkdir cheerpj-example-applet

Move Pitch.jar into it:

└──cheerpj-example-applet
└── Pitch.jar

4. Create an HTML file

In the project directory, create a file called index.html:

index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Pitch applet (CheerpJ)</title>
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>
<style>
div {
max-width: 500px;
margin: auto;
text-align: center;
}
h1 {
margin-bottom: 50px;
}
h5 {
margin-top: 20px;
}
</style>
</head>
<body>
<div>
<h1>Applet example with CheerpJ</h1>
<div>
<cheerpj-applet
archive="Pitch.jar"
code="Pitchview"
height="300"
width="500"
>
Your browser cannot handle the applet tag!
</cheerpj-applet>
</div>
<h5>
The applet shown in this example belongs to the NASA's
<a href="https://www.grc.nasa.gov/WWW/K-12/airplane/"
>Beginner's Guide to Aeronautics</a
>
and it is available at their
<a href="https://github.com/nasa/BGA/tree/main">GitHub repository</a>.
</h5>
<h5>
Applet is running with
<a href="https://cheerpj.com/">CheerpJ</a> by
<a href="https://leaningtech.com/">©Leaning Technologies</a>
</h5>
</div>
<script type="module">
await cheerpjInit();
</script>
</body>
</html>
Java applets and Java 8
cheerpjInit runs Java 8 when no version is set. Applets run on Java 8 only, so do not set version to 11 or higher on a page that runs an applet.

What is happening?

  • The <script> tag in the <head> loads CheerpJ:
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>
  • The <cheerpj-applet> tag gives the JAR (archive), the class name (code) and the size, taken from <jar> and <applet-desc> in the JNLP file. The cheerpj- prefix stops a Java plug-in, if one is installed, from trying to run the applet. The classic <applet> tag also works.
  • cheerpjInit() initialises CheerpJ, which then runs the applets on the page. Applets do not need cheerpjCreateDisplay().

5. Host your page locally

From the project directory, serve the files over HTTP. Vite works well during development because it reloads the page when the files change:

Terminal window
npx vite

Alternatively, use the http-server utility:

Terminal window
npx http-server -p 8080

Open the URL shown in the terminal, for example http://127.0.0.1:8080/.

Note
The server must support HTTP Range requests, and the page cannot be opened from file://. Python’s http.server does not support Range requests. See basic server setup.

The result

The applet runs in the browser:

Source code and credits

Further reading

Build with Java for the browser.