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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CoffeeScript

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

JavaFX

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

Java

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

WebSocket

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

JavaScript

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

Q&A

解決済

2回答

751閲覧

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

mahoken

総合スコア85

CoffeeScript

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

JavaFX

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

Java

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

WebSocket

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

JavaScript

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

1グッド

0クリップ

投稿2017/12/15 06:31

編集2017/12/19 05:41

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

1//javaからjsを実行 2webEngine.executeScript(setLocaleStorage(language));

CoffeeScript

1@setLocaleStorage = (lang) => 2 #ここでエラー発生 3 dataLang = localStorage.getItem('language')
SingleInstanceService実装箇所

Java

1 try { 2 // JavaWebStartで起動されたアプリケーションをSingletonオブジェクトとして登録 3 mSiService = (SingleInstanceService)ServiceManager.lookup("javax.jnlp.SingleInstanceService"); 4 } catch (UnavailableServiceException ex) { 5 // 利用できないサービスをlookupした場合のexception 6 ex.printStackTrace(); 7 return; 8 } 9 10 // 同アプリケーションの別インスタンスが呼び出された時のlistner 11 mSiListener = (String[] params1) -> { 12 // エラーダイアログを出して新たにJWSインスタンスを起動させない 13 Platform.runLater(() -> { 14 Alert alert = AppUtils.createAlert( 15 Alert.AlertType.WARNING, 16 AppUtils.getMessage( "エラーメッセージ" ), 17 AppUtils.getMessage( "エラーメッセージ" ) 18 ); 19 alert.show(); 20 }); 21 }; 22 mSiService.addSingleInstanceListener(mSiListener);

#####想定される原因

  • javaのプロセスが起動されると、そのPCのLocalStrage全体がロックされている?

#####実現したいこと

  • app1,app2それぞれを正常に動作させたい。
  • 複数起動を許容したい。
  • プロセスごとにlocalStrageを保持したい

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

KSwordOfHaste👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masaya_ohashi

2017/12/15 06:37

問題が起こるlocalStorage.getItemの呼び出し箇所のコードも記載してください。できればそのコード全体です。
mahoken

2017/12/15 06:49

セキュリティ上、全体コードは乗せれませんが情報を追加しました。お願いいたします。
masaya_ohashi

2017/12/15 06:57

んー…実は詳しくないので、これだけの情報開示では私は答えれそうにありません。
mahoken

2017/12/15 06:58

情報不足で申し訳ありません。考えていただきありがとうございます。
KSwordOfHaste

2017/12/15 07:34 編集

WebKit JavaFXなどまだ開発が進んでいる最中な気がするのでJDKのバージョンも付記されてはいかがでしょう?=>1.8.0_152と思っていいでしょうか?少なくともJavaFXは1.8の途中で色々手が入っており1.8.0_40未満と以降で振る舞いが違う・・・なんてこともありましたので。
KSwordOfHaste

2017/12/15 07:41 編集

バージョンの詳細はともかく1.8.0_152でやってみたところ、同一のJavaFXアプリケーションを起動してwindow.localStorage.setItem('xx','zz')とした後で後から起動した方のプロセスでwindow.localStorage.getItem('xx')としてみたところ「JSException: TypeError: null is not an object」が発生しました。これは再現したとみてよいと思います。 ==>追記:みたところ後から起動した方ではwindows.localStorageの結果がnullでした。
mahoken

2017/12/15 07:47

バージョン情報を更新しました。
mahoken

2017/12/15 07:50

同現象のように思われます。後から起動した方で、windows.localStorageがnullになってしまうのは何故なのでしょうか。。また、回避策はあるのでしょうか。。色々と調べてみましたが情報が全然ありませんでした。
KSwordOfHaste

2017/12/15 08:10 編集

これが制限ではなくバグだとするとwebkitのbugzillaで探してみる必要があると思います。やりかたが適当過ぎるかも知れませんが例えばfirefoxで別々のウィンドウを開きそれぞれでdeveloper toolを開き片方でsetItemしてももう片方でgetItemできることからみてWebKit/JavaFXの制限かバグのような予感がします。
mahoken

2017/12/15 08:26

色々と試していただき、ありがとうございます。バグではなく、WebKitやJavaFXの場合でも現状は回避が不可能という認識で良いでしょうか。。
KSwordOfHaste

2017/12/15 08:38

localStorageをアクセスすること自体には問題はないような気がするのです。MDNに書かれている制限にあきらかにひっかかるようなことをしてない限りはですが。自分はそこまできっちり調べきれたとはいえませんがもしWebkitの制限だとしたらという仮定で下記回答(回答じゃなく情報ですが)を記載しています。
KSwordOfHaste

2017/12/15 08:41

もちろん下記はあくまで回避なので何か使い方に問題があったとしたらこのような回避を一旦リリースしてしまうとまずいことになると思います。時間が許す限り原因を判明させることが大切ですよね・・・
mahoken

2017/12/15 08:53

ありがとうございます。引き続き調査をしてみます。
KSwordOfHaste

2017/12/15 08:55

うーむBAはつけないほうが・・・興味あるのでWebKitをcloneしてExecuteScriptのChangeLogを眺めてたのですが山のように修正が入ってますよ・・・
mahoken

2017/12/15 08:57

一度BA外させていただきました。もう少し、回答を受け付けてみたいと思います。私の方でも確認しましたが、修正入ってますねー。うーm
KSwordOfHaste

2017/12/15 08:59

BAはずせるんですね!その方がよいと思います。
mahoken

2017/12/15 09:03 編集

色々とご親切にありがとうございました!
KSwordOfHaste

2017/12/18 09:40 編集

ところで2つのURLのオリジンは同一(想像するにfile://localhost/.../ap1.html, file://localhost/.../ap2.htmlのようなもの)だと思いますが異なるオリジン(ホストを変えるとか)にはしない想定ですよね?
mahoken

2017/12/18 09:59

AWSを利用していて、サーバーを別途立てているので、オリジン自体は違う認識でいます。
KSwordOfHaste

2017/12/18 11:12 編集

質問意図は「このJNLPアプリのWebViewにロードする2つのURLであるURL1とURL2が異なるオリジンであればlocalStorageはURL1,URL2で別々に取得できるはず」ということなのですが?わかりにくくてすみません。
KSwordOfHaste

2017/12/18 11:20

申し訳ないです!上記は間違いでした。URL1/2が異なるオリジンでもWebViewのこの現象は同様になってしまいました!異なるオリジンでも片方でlocalStorageを参照すると別のプロセスではnullになってました!
KSwordOfHaste

2017/12/18 11:36

回避策的な話かも知れませんが、JNLPアプリをSingleInstanceServiceとして実装し、同一のプロセス(アプリケーションインスタンス)で複数のStageを表示し、それぞれ独立に実行するようにするような変更は可能でしょうか。それぞれのStageで「×ボタン」を押してもアプリケーションを終了しないように配慮せねばなりませんが。
mahoken

2017/12/19 01:28 編集

現在、SingleInstanceServiceとして実装されており、本件の問題がおきないよう複数アプリの起動ができぬよう制御を行なっています。複数のStageを表示し、それぞれ独立に実行するようにするというのが少しイメージが沸いてないです。。
mahoken

2017/12/19 04:53

この方法は、一つのjnlpを叩いたら二つのアプリケーションウィンドウが起動されるような感じですか? 私が実現したいのは、複数のjnlpを叩いた時に、それぞれでlocalStorageを扱えるようにしたいというものです。。
KSwordOfHaste

2017/12/19 05:15

いえ、「2つのjnlpを叩いたとき、それらすべての画面は最初に起動されたアプリ内から開かれる」というイメージです。SingleInstanceServiceのAPIリファレンスを見てそう解釈したのですが・・・
KSwordOfHaste

2017/12/19 05:23

補足しますとSingleInstanceListenerをアプリで実装しておくと、2つ目のjnlpが起動されたことを1つ目のアプリで検知できるので、その起動パラメータを受け取って2つ目のjnlpアプリの処理を最初の起動アプリ内で実行することができるという考えです。
mahoken

2017/12/19 05:26

現状、SingleInstanceListenerを使ってアラートを出しているのでそこでstart()すれば良い感じですかね。少し試してみます! ありがとうございます!
mahoken

2017/12/19 05:27

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

2017/12/19 05:33

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

2017/12/19 05:40 編集

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

回答2

0

ベストアンサー

追記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 08:26

編集2017/12/19 05:29
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/12/15 12:24

実装を見た方が早いのかも知れませんが、Windowsですと C:\Users\user\AppData\Roaming\fx1.<アプリケーションクラスFQN>\webview\localstorage のようなディレクトリーが出来ていてここに格納されているように見えました。同一階層には.lockというファイルがありますがこのlocalStorageにアクセスしている間質問者さんが想像するようにロックされているような気がしますね(機能的に・・・)
mahoken

2017/12/18 00:41

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

2017/12/22 08:05

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

2017/12/22 08:29

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

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クラス名を重複しないようにした。

投稿2017/12/22 08:03

編集2017/12/22 08:04
mahoken

総合スコア85

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問