Java Platform, Standard Editionデプロイメント・ガイド
目次      

16 JavaおよびJavaScript

このトピックでは、JavaおよびJavaFXアプリケーションにJavaScriptコードからアクセスする方法、およびJavaScriptコードにJavaおよびJavaFXアプリケーションからアクセスする方法を示します。

アプリケーションは、JavaScriptエンジンを使用して、アプリケーションが埋め込まれているWebページと通信できます。ホストWebページも、JavaScriptを使用して、埋め込まれたアプリケーションと通信できます。


注意:

かなりの範囲まで、この機能は、Java Plug-inで実装されるJavaからJavaScriptへの通信ブリッジに基づいています。そのため、Javaアプレットで使用可能なドキュメントおよび例の多くは、JavaFXアプリケーションにも適用可能です。Java実装の詳細は、Java LiveConnectドキュメントを参照してください。

この節の内容は以下のとおりです。

16.1 Webページからのアプリケーションへのアクセス

JavaScriptからJavaまたはJavaFXアプリケーションにアクセスするための最初のステップは、アプリケーションを表すJavaScriptオブジェクトへの参照を取得することです。参照を取得する最も容易な方法は、例16-1に示すように、appletタグのname属性を使用して、標準JavaScript getElementById()関数を使用することです。<fx:deploy> antタスクはappletタグを自動的に生成し、名前は<fx:application>id属性から取得されます。

結果はアプリケーションのメイン・クラスに対応します。

JavaScriptオブジェクトへの参照を取得することによって、対応するJavaScriptオブジェクトのフィールドとしてJavaオブジェクトを参照して、Javaオブジェクトのパブリック・メソッドおよびフィールドにアクセスするためにJavaScriptコードを使用できます。app参照を指定した後で、次のコード文のようなことを実行できます。

var r = app.doSomething()

JavaコードでのdoSomething()メソッドの実装は、Javaオブジェクトを返します。変数rはJavaオブジェクトへの参照になります。r.doSomethingElse()app.dosomethingWithR(r)などのコードを使用できます。たとえば、例16-2にはJavaコードが含まれ、例16-3にはそのコードと対話するJavaScriptが含まれています。これらが一緒に動作する方法を確認するには、両方の例を参照してください。

例16-3のJavaScriptスニペットは、例16-2のJavaコードにいくつかの値を渡します。これらの値がJavaコードで使用される前に、最も近いJavaタイプに自動的に変換されます。

例16-3 例16-2のJavaScriptコード

function navigateTo(cityName) {
    //Assumes that the applet tag uses "myMapApp" as the name for this application
    var mapApp = document.getElementById("myMapApp");
    if (mapApp != null) {
        var city = mapApp.getCity(cityName);
        mapApp.navigateTo(city, mapApp.ZOOM_STREET);
        return mapApp.currentZipCode;
    }
    return "unknown";
}
window.alert("Area zip: " + navigateTo("San Francisco"));

JavaScriptの文字列、数値およびブール・オブジェクトは、ほとんどのプリミティブJava型(Boolean、byte、char、short、int、long、floatおよびdouble)とjava.lang.Stringに変換できます。

Javaオブジェクトを表すJavaScriptオブジェクト(つまり、以前にJavaから返されたオブジェクト)では、変換すると、そのJavaオブジェクトへの参照が抽出されます。

1つおよび多次元の配列への変換は、個々のオブジェクトの変換のルールに類似したルールに従って、サポートされます。変換を正常に実行できない場合、JavaScriptエンジンは例外を発生させます。

Webブラウザに返されたすべてのJavaオブジェクトは、特定のアプリケーション・インスタンスに関連付けられています。JavaScriptエンジンによって保持されるJavaオブジェクトへの参照は、永続的な参照として機能し、ホストしているJVMでそのJavaオブジェクトがガベージ・コレクトされないようにします。ただし、たとえば、アプリケーションをホストしているWebページから離れたり、HTML DOMツリーからアプリケーションを分離したりすることによって、特定のアプリケーションが破棄された場合、参照はすぐに無効になり、これらのオブジェクトをJavaScriptでさらに使用しようとすると、例外が発生します。

データ型の変換およびオブジェクトの存在期間の詳細は、次を参照してください。

http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS


注意:

Javaオブジェクトがオーバーロード・メソッド(同名だが引数型のセットが異なる複数のメソッド)を持っている場合、最も近い型のメソッドが使用されます。詳細は、Java LiveConnectドキュメントを参照してください。

一般的には、JavaScriptコードから使用する場合は、オーバーロード・メソッドを回避することをお薦めします。


16.3 埋込みJavaFXアプリケーションからのホストWebページへのアクセス

JavaFXアプリケーションは次のJavaScriptコンポーネントを呼び出すことができます。

  • 関数

  • JavaScriptオブジェクトのgetsetおよびremoveフィールド

  • JavaScript配列のgetおよびset要素

JavaFXアプリケーションはJavaScriptコードを評価することもできます。JavaScript DOM APIを使用して、HTML要素を追加、削除および移動することによって、JavaFXアプリケーションはWebページを動的に変更できます。

JavaFXからJavaScriptへの通信をブートストラップするには、JavaFXアプリケーションは、アプリケーションを含むJavaScriptウィンドウ・オブジェクトへの参照を取得する必要があります。この参照は、評価、関数の呼出し、および変数のフェッチなど、その後の操作に使用できます。

例16-4に示すように、JavaFX APIのHostServicesクラスにアクセスし、getWebContext()を要求することによって、メイン・アプリケーションとプリローダー・アプリケーションの両方がこの参照を取得できます。

DOMウィンドウへの参照を含むJavaScriptオブジェクトのすべてのインスタンスが、netscape.javascript.JSObject.のインスタンスとしてJavaコード内に表示されます。

例16-5は、JavaScriptを使用して、実行時にid='myMapApp'で埋め込まれたアプリケーションをサイズ変更する関数を実装する方法を示しています。

16.4 高度なトピック

Webページに埋め込まれたJavaFXアプリケーションは、プリローダーまたはメイン・アプリケーション・クラスのinit()メソッドが呼び出された後で、WebページのJavaScriptメソッドを呼び出すことができます。

JavaScriptコードはJavaアプリケーションにいつでもアクセスできますが、アプリケーションがまだ準備できていない場合、アプリケーションの準備が整うまで要求はブロックされます。特にJavaFXアプリケーションでは、メイン・アプリケーション・クラスのinit()メソッドがまだ終了しておらず、メイン・アプリケーションが自身でWebページへの呼出しを実行していなかった場合に、これが発生します。プリローダーからのJavaScript呼出しは、JavaScriptからJavaへの通信を完全にブロック解除していません。

ほとんどのブラウザでは、シングル・スレッドのJavaScriptエンジンを使用します。ブロックが発生すると、ホストWebページおよびブラウザはフリーズしているように見えます。

ホストWebページからアプリケーションに早くアクセスしてブロックを回避するには、アプリケーションからJava関数を呼び出して、アプリケーションの準備ができたときにWebページに通知するか、AntタスクでonJavascriptReadyコールバックを使用します。

例16-6は、onJavascriptReadyコールバックを使用してブラウザをブロックせずにメイン・アプリケーションのdoSomething()メソッドを呼び出すAntタスクのHTMLテンプレートを示しています。

例16-7は、例16-6のテンプレートからHTMLページを生成するために使用されるAntタスクの該当部分を示しています。この例では、テンプレートにパスsrc/web/test_template.htmlが含まれていることを前提としています。

16.5スレッド

JavaScriptから呼び出されるJavaコードは、JavaFXアプリケーション・スレッドではない特別なスレッドで実行されます。JavaFXコードのPlatform.runLater()メソッドを使用して、JavaFXアプリケーション・スレッドで何か実行されていることを確認します。

一般に、JavaScriptから呼び出される関数からできるだけ早く返します。ほとんどの最新のブラウザでは、JavaScriptエンジンはシングル・スレッドです。呼出しが進まないと、Webページはフリーズしているように見え、ブラウザは応答がありません。特に、JavaFXアプリケーション・スレッドで行われる作業を待機するコードを書き込まないようにします。JavaScriptコードがこの作業の結果に依存している場合、Javaからコールバックを使用して、その作業の実行の結果のJavaScriptコードを通知します。

例16-8は、JavaScriptで回避するコードの例を示しています。

例16-9は、JavaScriptコードで従ったほうがよいパターンを示しています。

例16-9 例16-8のより適切な実装

function process(r) {
    window.alert("Result: "+r);
}
  
myApp.doSomethingLong(function(r) {process(r);});

例16-10は、Javaコードにおける適切な例を示しています。

Javaコードは、JavaFXアプリケーション・スレッドを含むどのスレッドからもJavaScriptを呼び出すことができます。ただし、ブラウザのJavaScriptエンジンがビジー状態の場合、JavaScriptへの呼出しは、しばらくの間進まない可能性があります。JavaFXアプリケーション・スレッドでの呼出しがある場合、画面の更新やユーザー・イベントの処理ができないため、アプリケーションがフリーズしたように見えることがあります。この状況を回避するには、JavaFXアプリケーション・スレッドからのLiveConnect呼出しの実行の負荷を軽減します。

16.6 セキュリティ

Webページ上のJavaScriptコードは、そのページ上のアプリケーションへの呼出しを常に行うことができます。JavaScriptコードは、アプリケーションでロードされるJavaクラスのすべてのパブリック・メソッドおよびフィールドにアクセスすることもできます。ただし、JavaScriptからJavaへの呼出しが行われると、その呼出しはサンドボックス環境からの呼出しとして扱われます。また、HTMLドキュメントとアプリケーションが異なるサイトを元にしている場合、Webページ上のJavaScriptは、それのためにネットワーク接続を行うことはできません。

この制限を除いて、アプリケーションがサンドボックスで実行される場合、JavaScriptからのJavaの呼出しは他に影響を及ぼしません。ただし、アプリケーションが高い権限を要求した場合、JavaScriptからのJavaメソッドへの呼出しは高い権限なしでサンドボックスで実行され、セキュリティ警告が発行されます。高い権限が必要な場合、Java APIのAccessController.doPrivilegedを使用して、信頼されたコードで権限を要求できます。

信頼されていないJavaScriptコードで誤って追加の権限を付与したアプリケーションでAPIを公開しないように注意してください。JavaScriptコードに高い権限を付与する必要がある場合、検証可能なHTTPS接続でアプリケーションを提供し、アプリケーションをホストしているWebページのドキュメント・ベースがアプリケーションのコードの目的とする提供元と同じであることを確認するためのチェックを実行します。

16.7 タブ・ペインの例

この項には、JavaFXとJavaScript間の通信を使用してJavaFX Webアプリケーションをブラウザと統合する方法を示すサンプルが含まれています。例16-11は、Webページに20個のタブを持つタブ・ペインを作成するJavaFXアプリケーションを示しています。

アクセスしたタブの履歴をブラウザ履歴に保存するように、このアプリケーションをさらに改善できます。これにより、ユーザーは、ブラウザの「戻る」および「進む」ボタンをクリックすると、タブ間を移動できます。

実装は、HTML 5で導入されたonhashchangeイベントに基づいており、次の場所で説明されています。

http://www.whatwg.org/specs/web-apps/current-work/#event-hashchange

同様の効果を実現するためにAJAXアプリケーションで使用されるJavaScript技術は、ドキュメントURLのハッシュ部分に現在の選択への参照を保存することです。ユーザーが「戻る」ボタンをクリックすると、URLが更新され、復元する必要がある選択状態を抽出できます。

この解決策を実装するために、onNavigate()navigateTo()の2つの新しいメソッドがサンプルに追加されます。新しいタブが選択されるたびに、onNavigate()メソッドが呼び出されます。JavaScriptメソッドnavigateTo()を呼び出し、それにタブIDを渡すことによって、このメソッドは新しい選択に関する情報をWebページに配信します。JavaScriptコードはタブIDをURLハッシュに保存します。

navigateTo()メソッドは逆の同期の役割を果たします。WebページURLが変更されると、選択されるタブのIDを使用してこのメソッドが呼び出されます。

例16-12は、アプリケーションの更新されたコードを示しています。例16-11と異なるコードは太字で示しています。

実装ロジックの部分はHTMLページ内にあります。例16-13は、Antスクリプトの入力テンプレートとして使用されるページを示しています。Antスクリプトが実行されると、JavaFXアプリケーションを埋め込むコードを、カスタムJavaScriptコードの隣に挿入します。入力テンプレートの詳細は、「<fx:template>」を参照してください。

JavaScript関数の実装は簡単です。<body>タグのonhashchange属性は、URLのハッシュ部分の更新の通知に署名するために使用されます。イベントが取得されると、JavaFXアプリケーションがWebページに埋め込まれ、navigateTo()メソッドが呼び出されます。

アプリケーションが選択されたタブの更新で呼び出す場合、URLのハッシュ部分に保存されます。

完全性を期すために、例16-14は、このサンプルのデプロイに使用されるAntスクリプトを示しています。アプリケーションは、ID tabbedAppで作成されます。JavaScriptコードはこのIDを使用して、ページ上のアプリケーションを検索し、HTMLテンプレートはこれを使用して、Antタスクによって生成されたカスタムHTMLページにアプリケーションを埋め込みます。

目次      

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.