Swing Browser (Networking)

Run a Java application with Internet connection

This tutorial uses CheerpJ and Tailscale to run a web browser written in Java and give it access to the internet. The same approach works for any application running in CheerpJ that needs wider network access.

For how CheerpJ and Tailscale work together, see the networking guide.

Prerequisites

  • Download SwingHTMLBrowser.jar
  • 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
  • A Tailscale account (see step 3)

1. The Java application

The application is a small HTML browser written in Java with Swing. If Java is installed on your computer you can run the JAR locally to see how it behaves; this step is optional.

Type the full URL of a website in the input field and press Enter to load the page. Swing’s HTML support is limited to old versions of HTML, so most sites do not display as they do in a modern browser.

Tiny Browser Loaded

Run on the desktop, the page loads because the application uses the computer’s own network connection.

2. Run the application in the browser with CheerpJ

Next, run the same JAR in the browser with CheerpJ, without a Java installation. The steps are the same as in Run a Java app.

2.1 The project files

Create a project directory, put the JAR in it and create an HTML file next to it:

└──browserTutorial
├── SwingHTMLBrowser.jar
└── browser.html

Add this code to browser.html:

browser.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Browser</title>
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>
</head>
<body>
<script>
(async function () {
await cheerpjInit();
cheerpjCreateDisplay(800, 600);
await cheerpjRunJar("/app/SwingHTMLBrowser.jar");
})();
</script>
</body>
</html>

What’s going on?

  • The script tag in the <head> loads CheerpJ.
  • cheerpjInit initialises CheerpJ.
  • cheerpjCreateDisplay creates an 800x600 display that holds all Java windows.
  • cheerpjRunJar runs the application. SwingHTMLBrowser.jar names its main class in its manifest.
  • /app/ is the virtual file system mount point for the root of the web server the page is loaded from.

2.2 Serving the application

Serve the project directory with an HTTP server, such as http-server:

Terminal window
npx http-server -p 8080

Open http://127.0.0.1:8080/browser.html. The Java browser runs in the page. Type https://github.com in its address field and press Enter. Nothing loads, and the browser console shows this error:

Error in the Console Log

Next, load a page from the same server. Add this file to the project directory:

hello.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hello world</title>
</head>
<body>
<h1>Hello from the same origin!</h1>
</body>
</html>

In the Java browser, type http://127.0.0.1:8080/hello.html, using the same host and port as the page itself.

Hello From Same Origin

Without a Tailscale network, CheerpJ makes HTTP(S) requests with the browser’s fetch, so the same-origin policy and CORS apply. A page on the same origin loads; https://github.com does not allow cross-origin requests from your page, so the request fails. This keeps the application isolated from the wider internet.

To load pages from other sites, the application needs a network connection that is not limited by the browser.

3. Connect the application to the internet

CheerpJ connects to the internet through a Tailscale network (a tailnet in Tailscale terminology). A tailnet is a VPN made of the machines and users (nodes) connected to it. CheerpJ joins it with WireGuard over WebSockets.

By default a tailnet is isolated from the internet, so it needs an exit node: a machine that routes the tailnet’s internet traffic.

3.1 Set up Tailscale

To create a tailnet with an exit node:

  1. Create an account and log in to the Tailscale portal.
  2. Install Tailscale on your computer. This computer becomes the exit node.
  3. Set it up as an exit node by following the Tailscale exit node guide.

3.2 Authenticate your Java application

The application joins the tailnet with an auth key.

  1. Generate an auth key in the Tailscale admin console. For this tutorial, use an ephemeral, single-use key.
  2. Pass the key to cheerpjInit with the tailscaleAuthKey option in browser.html:
await cheerpjInit({
tailscaleAuthKey: "PasteYourKeyHere",
});

4. Final test

Reload the page and load https://www.google.com/ or https://www.github.com/ in the Java browser. The site loads through the exit node.

The application appears as a node in the Tailscale admin console, where you can monitor its connections.

View full source code on GitHub

Security
This setup is for learning only. An auth key in the page source can be read by anyone who loads the page, and an exit node gives every node on the tailnet access to the internet through your computer. In production, manage auth keys, exit nodes and access controls for your tailnet with care; Leaning Technologies is not responsible for how your network is administered. You can also run your own control server with Headscale.

Further reading

Build with Java for the browser.