質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.23%

  • JavaScript

    11807questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Java

    10883questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • JavaFX

    324questions

    JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

  • WebSocket

    142questions

    WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

  • CoffeeScript

    119questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。

JavaFX 複数アプリケーション 起動 localStrage null

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 105

mahoken

score 65

JavaFXでWebEngineを用いたアプリケーションの開発を行なっています。
開発しているアプリケーションを、仮にapp1、app2とします。
app1、app2は接続先(URL)が違うだけの、同アプリケーションです。
(UI、機能は全て一緒)

バージョン情報
  • Java 1.8.0_144
事象
  • app1のjnlpをクリックし、アプリケーションを起動する。
  • app2のjnlpをクリックし、アプリケーションを起動する。
  • app1が起動している状態でapp2の起動時に下記エラーが発生する
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: TypeError: null is not an object (evaluating 'localStorage.getItem')
    at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:146)
    at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
    at com.sun.webkit.WebPage.executeScript(WebPage.java:1509)
    at javafx.scene.web.WebEngine.executeScript(WebEngine.java:1005)
事象発生箇所
  • app1、app2にコードの差はありません。
  • app1起動後、app2を起動すると下記箇所でエラーを確認
    app1とapp2の起動順番を変えても発生。
    (app2起動後、app1を起動するとapp1の下記箇所でエラーを確認)
//javaからjsを実行
webEngine.executeScript(setLocaleStorage(language));
@setLocaleStorage = (lang) =>
  #ここでエラー発生
  dataLang = localStorage.getItem('language')
 SingleInstanceService実装箇所
        try {
            // JavaWebStartで起動されたアプリケーションをSingletonオブジェクトとして登録
            mSiService = (SingleInstanceService)ServiceManager.lookup("javax.jnlp.SingleInstanceService");
        } catch (UnavailableServiceException ex) {
            // 利用できないサービスをlookupした場合のexception
            ex.printStackTrace();
            return;
        }

        // 同アプリケーションの別インスタンスが呼び出された時のlistner
        mSiListener = (String[] params1) -> {
            // エラーダイアログを出して新たにJWSインスタンスを起動させない
            Platform.runLater(() -> {
                Alert alert = AppUtils.createAlert(
                                Alert.AlertType.WARNING,
                                AppUtils.getMessage( "エラーメッセージ" ),
                                AppUtils.getMessage( "エラーメッセージ" )
                              );
                alert.show();
            });
        };
        mSiService.addSingleInstanceListener(mSiListener);
想定される原因
  • javaのプロセスが起動されると、そのPCのLocalStrage全体がロックされている?
実現したいこと
  • app1,app2それぞれを正常に動作させたい。
  • 複数起動を許容したい。
  • プロセスごとにlocalStrageを保持したい

少しでもヒントをいただければと考えています。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mahoken

    2017/12/19 14:27

    あ、でもSingleInstanceListenerで検知できるのって、同じjnlpだけではなかったでしたっけ? 知識不足ですが、、

    キャンセル

  • KSwordOfHaste

    2017/12/19 14:33

    startするとまずいです。単に新しいStageをnewしてそれをshowして新たな要求を処理する感じです。「SingleInstanceListenerで検知できるのって、同じjnlpだけではなかったでしたっけ?」についてですが、同一jnlpでないといけないなら確かにダメですね。そこは調査不足でした。自分にもわかりません。

    キャンセル

  • mahoken

    2017/12/19 14:40 編集

    試してみましたが、同jnlpの検知はできましたが、他jnlpの検知ができていないようです。SingleInstanceListenerの実装コードを追記します。

    キャンセル

回答 2

checkベストアンサー

+2

追記3:すみません、追記2が自分の舌足らずのため伝わっていないようですので補足させてください。

追記2の前提は、2つ目以降のJNLPがたたかれた際に単にアプリ起動を抑止するのではなく「最初に起動したアプリ内で全てのJNLP要求を処理する」という前提でした。それを行うためにSingleInstanceListenerが使えるという想定です。


追記2:質問コメントでの以下に対する追記です。

現在、SingleInstanceServiceとして実装されており...複数のStageを表示し、それぞれ独立に実行するようにするというのが少しイメージが沸いてない...

その方式を採りJNLPアプリケーション起動ごとに複数のStage(ウィンドウ)を表示する場合、各々のStageは利用者からみて「独立したアプリケーションであるかのような振る舞いをすると想定しました。例えばStageのスタイルをデフォルトのStageStyle.DECORATEDとした場合、ウィンドウにはOS標準の操作デコレーションが付きますね?Windowsであれば右上の「×」ボタンを押すと画面を閉じることができますが、Stageのデフォルト実装ではこのとき「アプリケーションの終了」動作になるため複数のStageが全て消えアプリケーション全体が終了してしまいます。

その振る舞いは期待通りではないだろうと思います。そこで「×」ボタンクリックでは当該Stageのみ閉じて他のStageの動作は継続するよう配慮が必要だろうと考えました。また単純なアプリケーションの場合、アプリケーション全体の共通情報をアプリケーションクラスに置くことができますが、本件の場合だとそうはできず、各Stageに対応した適切な場所に独立して管理しておく必要もあるでしょう。質問コメントに書いた「複数のStageを独立に実行」はこうしたことを指したつもりでした。


訂正1:下記で「実際に通常のブラウザーでは動くように見えますね。動いて当然な気はしますが・・・」と言ってしまいましたがこれは誤り・認識不足かも知れません。

例えばLinuxでxwininfo/xpropを用いて調べる限り、firefoxを用いて2つウィンドウを開いたとき、実際には単一のプロセスで2つのウィンドウを開いていました。WindowsでProcess Exploreというツールを使ってfirefoxの2つのウィンドウのオーナープロセスを調べると同一のプロセス(firefoxのプロセスツリーの一番上の親?)になっているように思えました。この結果自体も正しく認識できているか自分の知識が怪しいといわざるを得ませんが、もしそうなら少なくともfirefoxは同一プロセスでlocalStorageを管理しているから別ウィンドウでそれぞれlocalStorageにアクセスできるにすぎないと考えることもできるかと思います。

Linux/WindowsともにJavaFXで複数のプロセスでWebViewを用いた際の振る舞いを観察すると、「先に表示したWebView」ではなく「先にlocalStorageを参照した側」でのみlocalStorageが非nullになりそれ以降は他のプロセスではnullになるようでした。

複数プロセスでlocalStorageが取得できるような使い方が可能かどうかの情報は残念ながら得られていませんが(あくまで個人的な推測では)複数プロセスがある場合は片方でしかlocalStorageインスタンスが取得できない仕様である可能性も捨てきれない気がしました。

元の回答

回答は早急だと思いますが、参考情報として・・・

実際に通常のブラウザーでは動くように見えますね。動いて当然な気はしますが・・・

JavaFX/WebKitの制限ないしはバグだと仮定するなら、WebEngineが提供するlocalStorageの代替実装をJava上に用意し適当なタイミングでwindow.localStorage = new JavaBridgeほにゃららみたいにしてJava側のオブジェクトを無理やり設定してしまうという手が考えられます。例えばconsole.logはJavaFXのWebKitでは有効な働きをしてくれないのでWebViewの初期化の際にWebEngineを通じてwindow.console.log = function (m) { javaに用意したブリッジオブジェクト.log(m); }
のようにして回避したりします。

本件の緊急度・原因究明の時間などにより上記のような緊急手段も検討する必要があるのかも知れません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/15 21:24

    実装を見た方が早いのかも知れませんが、Windowsですと

    C:\Users\user\AppData\Roaming\fx1.<アプリケーションクラスFQN>\webview\localstorage

    のようなディレクトリーが出来ていてここに格納されているように見えました。同一階層には.lockというファイルがありますがこのlocalStorageにアクセスしている間質問者さんが想像するようにロックされているような気がしますね(機能的に・・・)

    キャンセル

  • 2017/12/18 09:41

    追加の情報ありがとうございます。
    引き続き調査を行います。

    キャンセル

  • 2017/12/22 17:05

    解決できました!
    色々と調査していただきありがとうございました。
    本件でいろんな知識を培うことができました。
    感謝しております

    キャンセル

  • 2017/12/22 17:29

    自分は「同一のアプリで」というところにこだわりすぎて、うまく問題を把握できてなかったです。あまり助けにならなくてすみませんでした。

    キャンセル

0

原因

app1とapp2のアプリケーション名が重複していた為、
アクセスしているlocalStorageが同じものになっていた。

  • 参照しているlocalStorageディレクトリ
    windows : C:\Users\user\AppData\Roaming\ app名 \webview\localstorage
    mac : /Users/user/Library/Application Support/ app名 /localstorage
    ※同ディレクトリに.lockファイルがあり、同じlocalStorageにアクセスしようとするとlockされていた。
解決方法

アプリケーション名の重複を解決することで、
app1とapp2が参照するlocalStorageディレクトリは以下のようになる為、.lockファイルによる制御がかからない。
app1 : windows : C:\Users\user\AppData\Roaming\ applicatin1 \webview\localstorage
app2 : windows : C:\Users\user\AppData\Roaming\ applicatin2 \webview\localstorage

実際の対応
  • アプリケーション名は、javaFXのメインクラスのファイル名に依存する為、
    各アプリのjavaクラス名を重複しないようにした。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.23%

関連した質問

同じタグがついた質問を見る

  • JavaScript

    11807questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Java

    10883questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • JavaFX

    324questions

    JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

  • WebSocket

    142questions

    WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

  • CoffeeScript

    119questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。