よくある問題:誰もインストールしたがらないJavaデスクトップアプリ
以前、あるクライアントからチームに難題が持ち込まれた。彼らには古いJavaデスクトップアプリ(Swing GUI)があり、Windows上では問題なく動いていたが、50人のメンバー全員がブラウザから使いたい、JREのインストールも各端末へのITサポートも不要で、という要望だった。Webアプリとして書き直す?6か月かかる上に予算もない。TeamViewerやAnyDeskを使う?50人が同時接続するとなるとスケールが大変すぎる。
そこで初めて出会ったのがWebswingだ。そして数時間でまさにその問題を解決してくれた。
アプリケーション仮想化とは?Webswingはどこに位置するのか
インストール手順に入る前に、全体像を少し整理しておこう。アプリケーション仮想化の基本的な考え方はシンプルだ:アプリはサーバー側で動き、クライアントはそのUIをストリーミングで受け取るだけ。操作もできるし画面も見えるが、端末には何もインストールされない。
WebswingはそのアイデアをJava専用に実装したものだ。Swing/JavaFXアプリ全体がサーバー上で動作し、レンダリング結果がHTML5 canvasとしてブラウザにストリーミングされる。マウスクリックやキー入力はブラウザがキャプチャしてサーバーへ送信し、サーバーが処理して新しいフレームを返す。最大のポイントは:元のJavaアプリに一切変更不要ということだ。アプリ自身はブラウザ上で動いていることを全く知らない。
CitrixやRDSなどのソリューションとの違い:
- Windows Serverライセンス不要:WebswingはLinux上でも問題なく動作する
- クライアントプラグイン不要:モダンブラウザ(Chrome、Firefox、Edge)だけあればよい
- ネイティブHTTP/WebSocket:nginxでリバースプロキシが簡単、既存インフラへの統合も容易
- セッション分離:ユーザーごとに独立したJVMが起動するため、互いに影響しない
私のホームラボ――Proxmox VEで12台のVMとコンテナを管理し、本番投入前に何でも試せるプレイグラウンド――では、WebswingはUbuntu 22.04のLXCコンテナ上で動かしている。セットアップして動作確認が取れてから、クライアント環境に展開した。
Webswingのインストールと設定
環境の準備
WebswingにはJava 11以上が必要だ。ここではUbuntu 22.04を使用する:
sudo apt update
sudo apt install -y openjdk-17-jdk wget unzip
java -version
# openjdk version "17.0.x"
公式サイトからWebswingをダウンロードする。Community Editionは非商用目的であれば無料で利用できる:
# ダウンロード前にwebswing.orgで最新バージョンを確認すること
wget https://webswing.org/download/webswing-23.2.zip -O webswing.zip
unzip webswing.zip -d /opt/
mv /opt/webswing-* /opt/webswing
Webswingの初回起動
cd /opt/webswing
./webswing.sh
Webswingはポート8080で起動する。http://localhost:8080にアクセスすると、SwingSet3やJFreeChartなどのデモアプリが同梱されたAdmin Consoleが表示される。デフォルトの認証情報はadmin/adminだ――本番環境で恥をかきたくなければすぐに変更すること。
Javaアプリケーションの設定
inventory-app.jarというJARファイルがある場合を例に挙げる。/opt/webswing/webswing.configにエントリを追加する:
{
"path": "inventory",
"name": "Inventory Management",
"mainClass": "com.company.inventory.MainApp",
"classPathEntries": [
"/opt/apps/inventory-app.jar",
"/opt/apps/lib/*.jar"
],
"vmArgs": "-Xmx512m -Dfile.encoding=UTF-8",
"maxClients": 10,
"isolatedFs": true
}
設定を保存したらWebswingを再起動する。アプリはhttp://localhost:8080/inventoryに表示されるようになる。
nginxによるリバースプロキシ
本番環境ではポート8080を直接公開してはいけない。nginxの設定は以下の通りだ:
server {
listen 443 ssl;
server_name apps.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/apps.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/apps.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
# WebSocketサポート — Webswingに必須
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 長時間セッション向けにタイムアウトを延長
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
UpgradeヘッダーとConnection: upgradeは必須だ――これがないとWebSocketが接続できず、アプリが描画されない。最初にこのミスをやらかして、デバッグに30分近く費やした。
WebswingをSystemdサービスとして実行する
sudo tee /etc/systemd/system/webswing.service << 'EOF'
[Unit]
Description=Webswing Application Server
After=network.target
[Service]
Type=simple
User=webswing
WorkingDirectory=/opt/webswing
ExecStart=/opt/webswing/webswing.sh
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 専用ユーザーを作成する — rootでサービスを実行してはいけない
sudo useradd -r -s /bin/false webswing
sudo chown -R webswing:webswing /opt/webswing
sudo systemctl daemon-reload
sudo systemctl enable --now webswing
sudo systemctl status webswing
本番環境投入前に検討すべきこと
RAMの計画
ユーザーセッションごとに独立したJVMが起動する。アプリが256MBのヒープを必要とする場合、10人の同時ユーザーではOSオーバーヘッドを除いても2.5GB以上のRAMが消費される。サーバーのRAMに合わせてmaxClientsを適切に設定し、jstatや監視スタックがあればGrafanaでモニタリングすること。
ファイルシステムの分離
isolatedFs: trueを有効にすると、各セッションに独立したホームディレクトリが割り当てられ、ユーザー間でファイルが読み取られるリスクを防げる。ファイルの保存・オープン機能があるアプリでは特に重要だ――この設定を忘れたせいでセッション間でデータが混在してしまったケースを実際に見たことがある。
クリップボードとファイル転送
テキストのコピー&ペーストやブラウザダイアログ経由のファイルアップロード・ダウンロードは動作するが、使用するアプリで十分にテストする必要がある。すべてのSwingコンポーネントが完璧に動作するわけではなく、特にカスタムレンダラーやネイティブOSダイアログ系は注意が必要だ。
Community Editionの制限
無料だが実用上いくつかの制約がある:同時セッション数の上限、SSO/LDAP連携なし、セッション録画・クラスターモードなし。試用や小規模な社内利用であれば問題ないが、大規模なスケールや監査ログが必要な場合は商用版が必須となる。
2008年製のSwingアプリで実際に試してみた――コードは一行も変えず、JDKのバージョンさえ合わせればブラウザ上で動いた。LAN環境でのレイテンシはほぼ感じられず、インターネット経由でRTT約20msあっても通常の業務作業には十分快適に使えた。
まとめ
ネイティブWebアプリとして書き直せる選択肢があるならそうするべきだ――長期的には確実にすっきりする。だが、書き直しに6か月と予算が常に確保できるわけではない。その二択の間で身動きが取れなくなったとき、Webswingは私が試した中で最も苦痛の少ない脱出口だった。
ゼロから動くURLまで2時間以内。Javaコードには一行も触れていない。アプリをゼロから書き直す場合やCitrixライセンスを購入する場合と比べると、「Web化」を待ち続けているレガシーJavaアプリに対して、真剣に検討する価値のある数字だ。

