TommyBox is a standalone executable container that makes it possible to launch static and dynamic web apps on a desktop by providing built-in server and browser functionality.
TommyBox is similar to Electron and NW.js.
An app can be provided as a directory or packed as WAR (or ZIP) archive that can contain JSP, servlets, and static stuff like CSS, JavaScript, etc.
Under the hood, TommyBox is built on top of Tommy web server and SWT browser widget. App can be packed as WAR or ZIP archive and can optionally contain PWA manifest, JSP, servlets and all static stuff like CSS, JavaScript files etc.
See TommyBox in action: https://github.com/xnbox/tommybox_demo
Download the latest release oftb.jar
- Single cross-platform executable jar (starts from ~25Mb)
- No dependencies
- No installation
- No own configuration files, instead, TommyBox uses standard standard PWA webmanifest and standard Tomcat configuration files
-
Operating systems:
- Linux
- macOS
- Windows
-
Architectures:
- x86_64
- win32-x86_64
- aarch64
- ppc64le
- Supports custom command line args, stdin, stdout, stderr
-
Configurable display modes:
- in-window
- in-browser
- fullscreen
- headless
- Single and multiple windows modes
- Optional custom splash screen
- Optional custom context menu
- Optional custom system tray icon with custom menu
- WAR files
- Web apps packed as ZIP archives (including standard password-protected ZIPs)
- Exploded web apps (local directories)
- Remote WAR / ZIP files (on HTTP servers)
- Embedded WAR / ZIP files and directories
java -jar tb.jar [options] [custom arg]...
Options:
--help print help message
--app <file|dir|URL> run app from ZIP or WAR archive, directory or URL
--password <string> provide password for encrypted ZIP or WAR archive
Run ZIP (or WAR) file:
java -jar tb.jar --app MyKillerApp.war
Run ZIP (or WAR) file with custom command-line args:
java -jar tb.jar --app MyKillerApp.war myparam1 myparam2 ...
Run ZIP (or WAR) from web server:
java -jar tb.jar --app https://example.com/MyKillerApp.zip
Run exploded web app from directory:
java -jar tb.jar --app MyKillerAppDir
Run password-protected ZIP (or WAR) archive:
java -jar tb.jar --app MyKillerApp.zip --password mysecret
- Option 1. Copy your app content into the
/app
directory of thetb.jar
. - Option 2. Pack your app as
app.war
orapp.zip
(the archive can be encrypted) and copy the archive to the root directory of thetb.jar
.
Brand your app by renaming the tb.jar
to the MyKillerApp.jar
.
Run embedded app:
java -jar MyKillerApp.jar
Run embedded app with custom command-line args:
java -jar MyKillerApp.jar myparam1 myparam2 ...
Run password-protected embedded app:
java -jar MyKillerApp.jar --password mysecret
Run password-protected embedded app with custom command-line args:
java -jar MyKillerApp.jar --password mysecret myparam1 myparam2 ...
Key | Type | Default value | Description |
---|---|---|---|
display | string | standalone | Standard PWA display mode.Possible values: standalone minimal_ui browser fullscreen minimized_window (non-standard)maximized_window (non-standard)desktop_area (non-standard)headless (non-standard) |
enable_fullscreen | boolean | true | Allow fullscreen mode |
tray_icon | boolean | true | Tray icon |
window_buttons | array | ["minimize", "maximize", "close"] | Window buttons list. Possible elements: minimize maximize close |
window_menu | string | none | Window menu mode. Possible values: custom native none |
window_always_on_top | boolean | false | Always on top window property |
window_size | string | null | Window size as string Eg.: 640x480 |
window_x | number | null | Window location X coordinate (in pixels) |
window_y | number | null | Window location Y coordinate (in pixels) |
strings | array | [] | I18N dictionary for custom strings |
Protocol | Description | HTML Example |
---|---|---|
home: | Home action | <a href="home:">Home</a> |
back: | Back action | <a href="back:">Back</a> |
forward: | Forward action | <a href="forward:>Forward</a> |
reload: | Reload action | <a href="reload:">Reload</a> |
quit: | Exit to OS | <a href="quit:">Exit</a> |
minimize: | Minimize window | <a href="minimize:">Minimize</a> |
fullscreen: | Switch to fullscreen | <a href="fullscreen:">Fullscreen</a> |
open: | Open the given URL in OS | <a href="open:file://home/john/my.pdf">Open PDF</a> |
open_in_new_window: | Open the given URL in the new window | <a href="open_in_new_window:http://example.com">Open in New Window</a> |
open_in_browser: | Open the given URL in the browser | <a href="open_in_browser:http://example.com">Open in Browser</a> |
java: | Launch Java code | <a href="java:javax.swing.JOptionPane.showMessageDialog(null, \"Hello, Java!\")">Launch Java Code</a> |
js: | Launch JavaScript code | <a href="js:javax.swing.JOptionPane.showMessageDialog(null, 'Hello, JavaScript!')">Launch JavaScript Code</a> |
// ...somewhere in your Servlet or JSP
InitialContext ctx = new InitialContext();
/* get custom command-line args */
String[] args = (String[]) ctx.lookup("java:comp/env/tommy/args");
/* get standard input (stdin) */
InputStream stdin = (InputStream) ctx.lookup("java:comp/env/tommy/stdin");
/* get standard output (stdout) */
PrintStream stdout = (PrintStream) ctx.lookup("java:comp/env/tommy/stdout");
/* get standard error (stderr) */
PrintStream stderr = (PrintStream) ctx.lookup("java:comp/env/tommy/stderr");
/* get "--app" parameter value */
String app = (String) ctx.lookup("java:comp/env/tommy/app");
// ...
Q. My app failed with java.lang.ClassNotFoundException: javax.servlet.*
A. As a result of the move from Java EE to Jakarta EE, starting from v10, Apache Tomcat supports only the Jakarta EE spec. javax.servlet.*
is no longer supported.
Replace the javax.servlet.*
imports in your code with jakarta.servlet.*
.