Java EE環境エントリの使用

概要

    目的

    このチュートリアルでは、頻繁な変更が必要となる可能性のあるアプリケーション内の変数値をハードコーディングせずに設定する方法について説明します。

    所要時間

    約30分

    はじめに

    ネットワーク接続を作成するアプリケーションでは、ホスト名またはIPアドレスとポート番号、さらに、場合によってはユーザー名とパスワードを把握しておく必要があります。 多くの開発者は、これらの情報を変数のハードコーディングという形でJavaクラス・ファイル内に記述しています。 そのため、ネットワークの接続先が変更されれば、アプリケーションのソース・コードを修正して再コンパイルする必要があります。 Java EEアプリケーションでは、このようなタイプの変数の値をweb.xmlファイルやejb-jar.xmlファイルなどのデプロイメント・ディスクリプタ内に記述できます。 デプロイメント・ディスクリプタは、アプリケーションを再コンパイルしなくても修正できます。 また、実行時に環境変数を変更できないアプリケーション・サーバーもありますが、 GlassFishでは、コマンドラインでset-web-env-entryコマンドを使用できます。

    シナリオ

    このチュートリアルでは、環境エントリを使用するように既存のアプリケーションを修正します。 この既存のアプリケーションは、JavaMail APIを使用して、SMTPサーバー経由で電子メールを送信します。 現時点では、SMTPサーバーに関するすべての情報が、あるSession Bean内部にハードコーディングされています。 このプロジェクトで電子メールを送信できるようにするには、お使いのSMTPサーバーのホスト名、ポート、接続タイプ(SMTP、SMTPS、TLS)、認証情報を把握しておく必要があります。

    ハードウェアとソフトウェアの要件(オプション)

    ハードウェアとソフトウェアの要件のリストは、以下のとおりです。

    • こちらのリンクから、Java JDK 7をダウンロードしてインストールします。
    • こちらのリンクから、IDEとアプリケーション・サーバーをダウンロードしてインストールします。GlassFish 3.1.2(Java EEダウンロード・バンドル)を搭載したNetBeans 7.1.2 with Java EEなどを使用できます。 インストール中に、GlassFishをインストールするためのチェック・ボックスをオンにしてください。 JUnitのインストールはオプションであり、このチュートリアルでは必須ではありません。
    • SMTPサーバーにアクセスできるようにします。
    • SMTPサーバーに対する有効な資格証明(ユーザー名とパスワード)を確認します。
    • このチュートリアルで使用する開始時のプロジェクトは、こちらからダウンロードできます。
    • このチュートリアルで作成する最終的なプロジェクトは、こちらからダウンロードできます。

    前提条件

    このチュートリアルを始める前に以下のことを確認してください。

    • SMTPサーバーにアクセスできること。 SMTPサーバーのホスト名、ポート番号、セキュリティ設定を把握しておく必要があります。 Webメール・プロバイダの中には、SMTPアクセスや電子メール・アカウント設定の参照、詳細情報の参照を許可していないところもあります。 ユーザー名は通常、@文字の前の名前だけではなく、電子メール・アドレス全体である点に注意してください。
    • Java EE IDEおよびアプリケーション・サーバー(GlassFish、Oracle WebLogic Serverなど)を用意すること。
    • サーブレットとSession EJBに関する基本的知識を有していること(必須ではないが有用)。

EmailSenderプロジェクトの実行

    まだダウンロードしていない場合は、こちらからEmailSenderプロジェクトをダウンロードします。 このプロジェクトは、HTMLフォームの送信時に電子メールを送信します。 現時点で、すべてのサーバー設定がcom.example.EmailSessionBeanクラス内にハードコーディングされています。 com.example.EmailSessionBeanクラス内の値を修正して、お使いのSMTPサーバーと連携するようにアプリケーションを構成する必要があります。 別のSMTPサーバーやユーザー・アカウントを使用するたびに、com.example.EmailSessionBeanクラスのJavaソース・コードを修正して再コンパイルする必要があります。 環境エントリを使用することで、この作業が不要になります。

    EmailSenderプロジェクトをダウンロードして解凍します。

    EmailSenderプロジェクトをNetBeansで開きます。

    com.example.EmailSessionBeanクラスを開き、SMTPサーバー設定がハードコーディングされているフィールドを探します。

    これらのフィールドを、お使いのSMTP設定に合わせて編集します。

    変更内容を保存します。

    アプリケーションをデプロイして実行します。

    自分に対する電子メールを作成します。

    Send」を押すと、フォームで指定した送信先に電子メールが送信されます。

    受信ボックスで、メッセージの到着を確認します。

    エラーが発生した場合は、NetBeansのGlassFish Server Outputタブに出力されるデバッグ情報を参照します。

    これでEmailSenderプロジェクトが機能するようになりましたが、まだSMTP設定を容易に変更することはできません。

環境エントリの作成

    ejb-jar.xmlデプロイメント・ディスクリプタ内に環境エントリを作成するには、以下の手順を実行します。

    EmailSender」プロジェクトを右クリックして、「New」→「Other」を選択します。

    New Fileウィンドウで、カテゴリとして「Enterprise JavaBeans」、ファイルの種類として「Standard Deployment Descriptor」を選択します。

    Next」をクリックします。

    New Standard Deployment Descriptor (web.xml)ウィンドウでejb-jar.xmlデプロイメント・ディスクリプタの場所を確認します。

    Finish」をクリックします。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    EmailSessionBean用の新しい<env-entry>エントリを作成します。

    <enterprise-beans>
        <session>
            <ejb-name>EmailSessionBean</ejb-name>
            <env-entry>
                <description>This example uses JNDI</description>
                <env-entry-name>mailhost</env-entry-name>
                <env-entry-type>java.lang.String</env-entry-type>
                <env-entry-value>smtp.example.com</env-entry-value>
            </env-entry>
        </session>
    </enterprise-beans>

    お使いのSMTPサーバー設定に合うように値を変更します。

    smtp.example.comテキストをお使いのSMTPサーバーのホスト名に置き換える必要があります。

    それぞれのEJBに独自の環境エントリのコレクションがあるため、名前が衝突することはありません。

    次の表は、<env-entry>要素の目的を示しています。

    要素 目的
    <description>

    環境エントリの説明(オプション)。

    <env-entry-name>

    エントリ名。 この名前を使用して、Javaクラス内部から値を取得できます。 また、この名前を使用して、JNDI java:comp/envコンテキスト内に環境エントリが登録されます。

    <env-entry-type> 環境エントリのデータ型。 Java EE 6では以下のデータ型が有効です。
    • java.lang.Boolean
    • java.lang.Byte
    • java.lang.Character
    • java.lang.String
    • java.lang.Short
    • java.lang.Integer
    • java.lang.Long
    • java.lang.Float
    • java.lang.Double
    • java.lang.Class
    • 任意の列挙型(java.lang.Enumのサブクラス)
    <env-entry-value> 環境エントリの値を表す文字列。

    これで環境エントリを設定できました。次に、実行時にこの値を読み取るようにアプリケーションを修正します。

JNDIを使用した環境エントリの読取り

    ここでは、JNDIを使用して環境エントリを読み取る方法について説明します。 Java EE 5よりも前のバージョンでは、これが環境エントリを読み取るための唯一の方法でした。 環境エントリの値を取得するための別の手法について、後の項で説明します。

    EmailSessionBeanクラスを開きます。

    以下のように、既存のhost変数の値を削除します。

    private String host;

    Session Beanの初期化時に実行される、@PostConstructアノテーション付きのメソッドを作成します。

    java:comp/envコンテキストで、mailhost環境エントリに対するJNDIルックアップを実行します。

    取得した値をhostフィールドに格納します。

    Fix Importsウィザード([Ctrl+Shift+I]キー)を実行し、JNDIに必要となるインポート文を追加します。

    アプリケーションをデプロイして実行します。

@Resource()を使用した環境エントリの注入

    ここでは、@Resourceアノテーションを使用して、コンポーネントに対する環境変数の値の依存性注入を実行するようにアプリケーション・サーバーに要求します。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    新しい<env-entry>要素を追加します。この要素に、SMTPサーバーのポート番号を示すjava.lang.Integer型の値を追加します。

    <env-entry>
        <description>This example uses @Resource()</description>
        <env-entry-name>com.example.EmailSessionBean/port</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>465</env-entry-value>
    </env-entry>

    <env-entry-name>では、クラスの完全修飾名の後にスラッシュとクラス内のフィールド名を記述します。

    お使いのSMTPサーバー設定に合うように値を変更します。

    EmailSessionBeanクラスを開きます。

    portフィールドの値を削除します。

    portフィールドに@Resource()アノテーションを追加します。

    Fix Importsウィザード([Ctrl+Shift+I]キー)を実行し、javax.annotation.Resourceのインポート文を追加します。

    環境フィールドに@Resource()アノテーションを付与することで、java:comp/env/package.Class/fieldのルックアップにより返された値があれば、サーバーによってその値がこのフィールドに注入されます。

    アプリケーションをデプロイして実行します。

@Resource(name="env-entry-name")を使用した環境エントリの注入

    ここでは、@Resourceアノテーションを使用して、コンポーネントに対する名前付き環境変数の値の依存性注入を実行するようにアプリケーション・サーバーに要求します。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    EJB 3.1を使用するようにejb-jar.xmlファイルを修正します。 EJB 3.1は、環境変数として列挙型を使用する際に必要となります。 ここでは、バージョン番号とスキーマのロケーションを更新します。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    新しい<env-entry>要素を追加します。この要素に、Java列挙型であるcom.example.Protocol型の値を追加します。

    <env-entry>
        <description>This example uses @Resource(name="env-entry-name")</description>
        <env-entry-name>transport</env-entry-name>
        <env-entry-type>com.example.Protocol</env-entry-type>
        <env-entry-value>SMTPS</env-entry-value>
    </env-entry>

    お使いのSMTPサーバー設定に合うように値を変更します。

    EmailSessionBeanクラスを開きます。

    protocolフィールドの値を削除します。

    protocolフィールドに@Resource(name="transport")アノテーションを追加します。 name属性の値がejb-jar.xmlファイルの<env-entry-name>要素の値と対応しています。

    アプリケーションをデプロイして実行します。

    EmailSessionBeanクラスを開きます。

    debugフィールドの値を確認します。 このフィールドのデフォルト値trueを設定したままにします。

    debugフィールドに@Resource(name="debug")アノテーションを追加します。 現時点で、対応する<env-entry>要素はejb-jar.xmlファイル内にありません。

    アプリケーションをデプロイして実行します。

    電子メールの送信時に、NetBeans内のGlassFish出力ウィンドウにデバッグ情報が出力されることを確認します。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    新しい<env-entry>要素を追加します。この要素に、debugフィールドで使用するjava.lang.Boolean型の値を追加します。

    <env-entry>
        <description>@Resource(name="env-entry-name") with a default value</description>
        <env-entry-name>debug</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>false</env-entry-value>
    </env-entry>

    <env-entry-value>falseとなっている点に注意してください。

    NetBeansのGlassFish出力ウィンドウの内容を消去します([Ctrl+L]キー)。

    アプリケーションをデプロイして実行します。

    電子メールの送信時に、NetBeansでデバッグ情報が出力されなくなりました。

    このように環境エントリとリソース注入を組み合わせることで、デプロイメント・ディスクリプタを使用してフィールドのデフォルト値をオーバーライドできます。

<injection-target>を使用した環境エントリの注入

    <injection-target>要素を使用して、@Resourceアノテーションが付与されていないフィールドに環境変数を注入できます。 この方法で値を注入する際には、フィールドの値の取得元を確認しづらくなる場合があるため、注意してください。

    ejb-jar.xmlファイルを開き、XMLソースを確認します。

    SMTP認証の利用方法を制御する3つの新しい<env-entry>要素を追加し、関連するユーザー名とパスワードを指定します。

    <env-entry>
        <description>This is an example of using injection-target</description>
        <env-entry-name>authEnable</env-entry-name>
        <env-entry-value>true</env-entry-value>
        <injection-target>
            <injection-target-class>com.example.EmailSessionBean</injection-target-class>
            <injection-target-name>auth</injection-target-name>
        </injection-target>
    </env-entry>
    <env-entry>
        <description>This is an example of using injection-target</description>
        <env-entry-name>user</env-entry-name>
        <env-entry-value>matt@example.com</env-entry-value>
        <injection-target>
            <injection-target-class>com.example.EmailSessionBean</injection-target-class>
            <injection-target-name>username</injection-target-name>
        </injection-target>
    </env-entry>
    <env-entry>
        <description>This is an example of using injection-target</description>
        <env-entry-name>pw</env-entry-name>
        <env-entry-value>secretpw</env-entry-value>
        <injection-target>
            <injection-target-class>com.example.EmailSessionBean</injection-target-class>
            <injection-target-name>password</injection-target-name>
        </injection-target>
    </env-entry>

    お使いのSMTPサーバー設定に合うように値を変更します。

    EmailSessionBeanクラスを開きます。

    authフィールド、usernameフィールド、passwordフィールドの値を削除します。 これらのフィールドには@Resourceアノテーションを追加しないでください。

    アプリケーションをデプロイして実行します。

追加情報

    環境エントリの利用を検討する際に関連する情報として、以下の追加情報があります。

    サーブレットなどのWebコンポーネントでは、環境エントリが共有されます。 Webコンポーネントの場合、web.xmlデプロイメント・ディスクリプタの<web-app>要素内に直接<env-entry>要素を記述します。

    一部のクラスではリソース注入をサポートしていません。 注入をサポートする一般的なコンポーネントの種類は、次のとおりです。 サーブレット、サーブレット・フィルタ、サーブレット・イベント・リスナー、JSPタグ・ハンドラ、JSPタグ・ライブラリ・イベント・リスナー、JSFスコープのマネージドBean、JAX-WSサービス・エンドポイント、JAX-WSハンドラ、EJB Bean、EJBインターセプタ、マネージドBean、CDIマネージドBean、CDIデコレータ。

    @Resourceアノテーションは、フィールドではなくsetterメソッドに付与することもできます。 setterメソッドに付与する場合は、JavaBeanの命名規則が適用されます。

    変更されやすい情報のハードコーディングを避けるための技法は他にもあります。 アプリケーション・サーバーの管理者が、すべての値が設定された管理対象オブジェクトとして作成できるリソースもあります(JDBCデータソース、JavaMailセッション)。 @Resourceを使用して、値が設定されたJavaMailセッションを注入できる場合があります。 ユーザー・インタフェースに表示されるテキスト・コンテンツの場合は、Java Internationalizationのコンポーネントであるメッセージ・バンドルを使用することをお勧めします。

まとめ

    このチュートリアルで学習した内容は、以下のとおりです。

    • デプロイメント・ディスクリプタ内での環境エントリの作成
    • JNDIを使用した環境エントリのルックアップ
    • 環境エントリの注入

    参考資料

    著者

    • カリキュラム開発責任者: Matt Heimer
    • 共著者: Tom McGinn

このOracle by Exampleをナビゲートする際、次の機能を使用できます。

ヘッダー・ボタンの非表示:
ヘッダー内のボタンを非表示にするには、タイトルをクリックします。 ボタンを再表示するには、もう一度タイトルをクリックします。
トピック一覧ボタン:
すべてのトピックの一覧です。 いずれかのトピックをクリックすると、その項に移動します。
すべてのトピックを開く/閉じる:
すべての項に対する詳細を表示または非表示にします。 デフォルトでは、すべてのトピックが閉じられています。
すべてのイメージを表示/非表示:
すべてのスクリーンショットを表示または非表示にします。 デフォルトでは、すべてのイメージが表示されています。
印刷:
コンテンツを印刷します。 現在表示または非表示にされているコンテンツが印刷されます。

このチュートリアルの特定の項に移動するには、一覧からトピックを選択してください。