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

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

ただいまの
回答率

89.06%

Eclipse上で実行した時と、実行可能JARで実行した時の違いについて

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,676

serona

score 25

前提・実現したいこと

Macのパソコンで、Eclipseを使ってJavaの開発を行っています。

Eclipse上で実行するときと、
実行可能JARファイル(生成されるJARに必須ライブラリーをパッケージ)としてエクスポートし、
ダブルクリックで実行する時の動作が異なります。

できれば、Eclipse上で実行しているときと全く同じように
実行可能JARファイルでもアプリケーションを動かしたいのですが
そのためにどうすればいいのか分からない状況です。

あと、Macのターミナルから、「java -jar ○○.jar」で実行した時と
直接JARファイルをダブルクリックして実行したときも、また動作が違うようです。
「java -jar ○○.jar」で実行すれば、MainFormのところに書いた件以外は
Eclipseで実行していたときと同じように動きます。

症状については以下の通りです。
WebEngine(WebView?)の動作に差があるようなので、それをなんとかしたいのですが
何か原因や、解決策にお心当たりはないでしょうか…
拙い文章で申し訳ありませんが、アドバイス頂けますと幸いです><

MainForm

ここの、
<content><fx:include fx:id="childTest1" source="application/Test1Form.fxml" /></content>
について、
Eclipseで実行する時は、「source="Test1Form.fxml"」 でないと「java.lang.reflect.InvocationTargetException」が発生して起動できないのに、
実行可能JARとして出力した時は、下記のように「application/」がついていないと起動できません。

今のところ、この症状については、実行可能JARとしてエクスポートする際に
「application/」を追記することで解決はしています。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.web.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane focusTraversable="true" xmlns="http://javafx.com/javafx/8"
    xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
    <center>
        <AnchorPane focusTraversable="true" prefHeight="600.0"
            prefWidth="600.0" BorderPane.alignment="CENTER">
            <children>
                <TabPane layoutY="75.0" prefHeight="525.0" prefWidth="600.0"
                    tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0"
                    AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
                    AnchorPane.topAnchor="75.0">
                    <tabs>
                        <Tab fx:id="tabMain" text="テスト1">
                            <content>
                                <fx:include fx:id="childTest1" source="application/Test1Form.fxml" />
                            </content>
                        </Tab>
                        <Tab fx:id="tabSkip" text="テスト2">
                            <content>
                                <fx:include fx:id="childTest2" source="application/Test2Form.fxml" />

MainController

結構略しています… getElementsByClassName(\"☆\")の☆部分には、どちらも同じクラス名が入っています

WebView(webviewTest)、ProgressIndicator(progressTest)、Label(lblTest)があるとして、
Workerが、Worker.State.SUCCEEDEDになったら、progressTestを非表示にする、というようにしたいのですが
Eclipseで実行した時と、実行可能JARファイルとしてエクスポート後に実行した時とで、WebEngineの動作が違うらしく
実行可能JARとして実行すると、Workerがほぼ全く「SUCCEEDED」になりません。(SCHEDULEDかRUNNINGになっているようです)
これを何とか、Eclipseで実行していたときと同じような動作にしたいのです。

webEngine = webviewTest.getEngine();

webEngine.getLoadWorker().stateProperty()
        .addListener(new javafx.beans.value.ChangeListener<Worker.State>() {
            @Override
            public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
                        if (webEngine.getLoadWorker().getState().equals(State.SUCCEEDED)) {
                            progressTest.setVisible(false);                            
                            if (webEngine.getLocation().equals("http://○○○○")) {
                                if ((boolean) webEngine.executeScript(
                                        "( document.getElementsByClassName(\"☆\").item(0) != null );")) {
                                    String testUrl = (String) webEngine.executeScript(
                                            "var $el = document.getElementsByClassName(\"☆\"); $el[0].href;");
                                    lblTest.setText(testUrl);
                                }
                            }
                        } else {
                        progressTest.setVisible(true);
                        }
            });
…

追記

調べてみたところ、どうやら、
起動の仕方?によってWebEngineのUserAgentが違っているようです。
webEngine.getUserAgent();を出力したところ、

Eclipseから起動した時は、

Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.19 (KHTML, like Gecko) JavaFX/8.0 Safari/538.19

実行可能JARとしてエクスポートして、ダブルクリックで起動した時は

Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/602.1 (KHTML, like Gecko) JavaFX/8.0 Safari/602.1

となっている事に気が付きました!!
これも何か関係あるのかな、と思っています。

webEngine.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.19 (KHTML, like Gecko) JavaFX/8.0 Safari/538.19")

こちらを記述して書き換えてみても、状況は変わらないようですが…
解決は難しいのでしょうか…?><
自分でも調べながら気長に待っておりますので、どなたかご回答頂けるとうれしいです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

+2

実行可能JARとして出力した時は、下記のように「application/」がついていないと起動できません。

これについて自分なりに確認してみましたが。fx:includeのパスを相対(ドキュメントベース相対)としたとき、状況によって書き換えるようなことは必要ありませんでした。
確認ですがfxmlをロードする際のURLの指定はgetResource()により指定されているでしょうか?自分はそうしています。

// cbissue.MyApp.java
package cbissue;
...import省略...
public class MyApp extends Application {
  public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
    stage.setScene(new Scene(root));
    ...
  }
}


Main.fxml(MyAppと同一パッケージにおいてあります。Sub.fxmlも同様です)

<?xml version="1.0" encoding="UTF-8"?>
...import省略...

<VBox prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60"
      xmlns:fx="http://javafx.com/fxml/1" fx:controller="cbissue.MainController">
   <children>
      <Button ... />
      <fx:include fx:id="sub" source="Sub.fxml" />
   </children>
</VBox>

実行可能JARとして実行すると、Workerがほぼ全く「SUCCEEDED」になりません。

WebEngineへのloadの引数が相対URLになっていて、実行環境によるドキュメントベース/コードベースの違いが原因でロードに失敗しているのだと思います。ロードに失敗するとWorkerの状態はFAILEDで終わります。

実行環境によるコードベース・ドキュメントベースの違いについてはHostServiceのリファレンスに以下の記載があります。

HostService

public final String getCodeBase()
このアプリケーションのコード・ベースURIを取得します。アプリケーションがJNLPファイルを介して起動された場合、このメソッドはJNLPファイルで指定されているコードベース・パラメータを返します。アプリケーションがスタンドアロン・モードで起動された場合、このメソッドはアプリケーションのjarファイルが含まれるディレクトリを返します。アプリケーションがjarファイルにパッケージ化されていない場合、このメソッドは空の文字列を返します。

public final String getDocumentBase()
このアプリケーションのドキュメント・ベースURIを取得します。アプリケーションがブラウザに埋め込まれている場合、このメソッドはアプリケーションを含むWebページのURIを返します。アプリケーションがwebstartモードで起動された場合、このメソッドはJNLPファイルで指定されているコードベース・パラメータを返します(ドキュメント・ベースおよびコード・ベースはこのモードでは同じです)。アプリケーションがスタンドアロン・モードで起動された場合、このメソッドは現在のディレクトリのURIを返します。


追記:指摘し忘れていましたが、ロードが成功しても失敗してもダイアログは閉じるべきだと思います。上の回答に書いた「ドキュメントベースやコードベース」の話とは別に、Workerの状態がSUCCEEDEDあるはFAILEDになった時点で閉じるようにすればよいでしょう。


JDK 1.8.0_131

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/03 18:03

    ご返信ありがとうございます!何度もすみません;;

    まず、ご指摘頂いた
     FXMLLoader.load(getClass().getResource("Test1Form.fxml"));
    この部分ですが、これは私の記入ミスでした…
    実際のコードでは、「Test1Form.fxml」ではなく「MainForm.fxml」と書いています。
    大変失礼しました(;;)

    fxmlのロードの件については、了承しました。
    とんでもないです!一緒に考えていただき、ありがとうございます。
    これについては、自分で引き続き調べてみます!

    また、Worker.Stateについて、

    webEngine.getLoadWorker().stateProperty().addListener(new javafx.beans.value.ChangeListener<Worker.State>() {
     @Override
     public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
     ※※※
     …
     }
    });

    この、※※※の部分に、newValue.toString()を記録するようなコードを書いて検証していますが
    「RUNNING」と記入された後は、10分以上放置してもそれ以降更新がありません。
    「FAILED」が記入されることもないので、失敗もしていないのかなと思います。
    try catch文で、エラーが発生した場合も記録するようにしましたが
    特にエラーが発生しているわけでもないようで…。

    ちなみにですが、WebViewに実際に表示されているWebページは、
    数秒後には読み込み終わっているように見えます(というか、普通に表示されているので多分終わってます…)。
    読み込みが終わらない、というよりは
    読み込みが終わっても「SUCCEEDED」や「FAILED」にならない、という症状なのかな?と思いました。
    Worker.Stateの確認のタイミングが間違っているのでしょうか…?

    以上、恐れ入りますが、よろしくお願いします。m(TT)m

    キャンセル

  • 2017/07/03 18:36

    > Worker.Stateの確認のタイミングが間違っているのでしょうか…?

    間違っているとは思えないのですが、自分はWebアプリに詳しいとはとても言えないのではっきりとは言えません。

    キャンセル

  • 2017/07/03 18:50

    一つ言い忘れてました。自分のテストコードではロード時のChangeListener内でDOMアクセスはしていませんので、そこに条件の違いがあるといえばあるかも知れません。とはいえ、あまり関係しそうな気がしないのですが。

    キャンセル

+1

JavaFX詳しくないのですが、stateの比較ってコールバックで渡ってくるもの使わなくて良いのでしょうか?

//×
 if (webEngine.getLoadWorker().getState().equals(State.SUCCEEDED)) {
//〇 ちなみにenum比較は==が良いと思う
if (newValue==State.SUCCEEDED) {

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/01 14:12

    webEngineのloadWorkerプロパティーの実体が状況に応じて変化する場合はkurokobaさんの推測が当たりだと思い実際にやってみました。その結果JDK8のWebViewのエンジンではloadWorkerはずっと同じインスタンスのまま変化しないようです。一般的にはkurokobaさんがおっしゃるようにChangeListenerのnewValueを参照したほうが簡便であると思いますが、本件に関しては質問者さんのコードであっても動作上は同じになるようです。

    キャンセル

  • 2017/07/03 14:47

    ご回答ありがとうございます!返信が遅くなってしまいすみません><

    仰る通りですね…!!
    動作自体は以前と変わらずで、問題の解決には繋がらなかったのですが
    こちらのほうがコードとして良いので、教えて頂いたように修正しました。
    ご指摘感謝です!!(*´∀`*)

    キャンセル

+1

ターミナルの"java -version"で表示されるバージョンは環境変数から見るのに対し、eclipseのjavaのバージョンはeclipseで設定したディレクトリのjavaを参照します。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/07 13:14

    すみません、コメントに入力したつもりが新に回答立ててしまいました...。申し訳ない。

    キャンセル

  • 2017/07/07 13:19

    いえいえ!!とんでもないです!ありがとうございます(*^^*)

    キャンセル

+1

eclipseのウィンドウ>設定>Java>インストール済のJRE

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/07 13:16

    度々ご回答ありがとうございます!短文でしたので、まとめてのコメント返信で失礼しますm(._.)m
    ターミナルの「java -version」で表示される件、
    環境変数なのかなと思ってはいたのですが、やはり、そういうことなんですね…
    eclipseのJREの設定方法については、存じております!
    ただ、そこに設定するための最新のバージョン(1.8.0_131)のjavaのディレクトリがわからなかったので、
    これについては改めて、調べてみようと思います!
    ありがとうございました!

    キャンセル

check解決した方法

0

完全に解決はしていませんが、原因がわかりました!
調べてみたところ、eclipse上、あるいはターミナルから「java -jar」のコマンドで起動した場合は
javaのバージョンが「1.8.0_111」となっているのに対し、
ダブルクリックで起動した場合は「1.8.0_131」となっていました!!
恐らくは、このjavaのバージョンの違いが、webViewなどの動作に影響しているんだと思います。

……ただ、既に1.8.0_131はインストールしており、javaコントロールパネルでは
最新のバージョン(Java8 Update131)がインストールされています、と表示されるのに対し
ターミナルから「java -version」と入力すると、「java version "1.8.0_111"」となります。
これは一体何なんでしょうか…(;・ω・)?

最新のバージョンに合わせて作成した方がいいのかな、とも思うのですが
探してみても131がどのディレクトリにあるのか分からず、eclipseで設定できない><
現在の仕様のまま、1.8.0_111で起動させるとしても
このアプリを使用するパソコン全てに、111のjavaがインストールされていないとだめだろうし…
何とか解決方法を調べてみますが、また分からなくなったらお世話になります…(TT)

一先ず、ご回答下さったKSwordOfHasteさん、kurokobaさん、ありがとうございました!

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/07 13:16

    すみません、間違って回答として書いちゃったので重複しますが再掲。
    ターミナルの"java -version"で表示されるバージョンは環境変数から見るのに対し、eclipseのjavaのバージョンはeclipseで設定したディレクトリのjavaを参照します。
    eclipseのウィンドウ>設定>Java>インストール済のJRE

    キャンセル

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

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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