9
ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014 JAVA TECH 31 COMMUNITY JAVA IN ACTION ABOUT US blog //new to java / 記事は全 3 回シリーズの 最終回です。このシリーズ では、Java EE 7 で拡張された 機能や、HTML5、WebSocket、 JavaScript Object Notation (JSON)処理などの比較的新し い Web 標準を使用して、最新 型のエンタープライズ・アプリ ケーションを構築する方法につ いて説明します。 このパート 3 では、パート 1 とパート 2 ですでに開発した movieplex7 アプリケーションを 改良し、チケット売上の表示機 能、映画ポイントを貯める機能、 他のユーザーとのチャット機能 を追加します。 注:アプリケーションのすべ てのソース・コードは、こちら からダウンロードできます。 デモ・アプリケーションの概要 パート 1とパート 2 では、 NetBeans および GlassFish 4 の ダウンロード方法、インストー ル方法、設定方法を学習しまし た。本記事でもこの環境を利用 して、アプリケーションの構築と デプロイを行います。これまで に、JavaServer Faces(JSF)2.2 を使用し、さらにナビゲーショ ン用の Faces Flow などの新し いテクノロジーを活用してアプリ ケーションを基礎から構築しま した。Java Persistence API (JPA) 2.1、Java API for RESTful Web Services(JAX-RS)、および JSON Processing(JSON-P)1.0 を利用して、ビジネス・ロジッ クやデータ操作を実装する方法 を確認しました。 これ以降は、このシリーズ のパート 1 とパート 2 におい て NetBeans IDE で作成した Maven ベースのプロジェクトを 使用しながら手順を確認してく ださい。 映画チケットの売上 本項では、Java API for Batch Processing 1.0(JSR 352)を利 用して、各上映の映画チケット の売上をインポートし、CSV ファ イルから累積売上を読み取って データベースに挿入します。 バッチ処理とは、一連のタス クまたはジョブを実行する手法 です。ほとんどの場合、バッチ 処理のジョブは対話的な操作を 必要とせず、一括処理を目的と して長時間実行されます。バッ チ処理の用語に関する詳細は、 Java EE 7 Tutorial を参照してく ださい。 クラスの生成:まず、映画の売 上を処理してデータベースに保 存するためのクラスを作成しま す。 1.「Source Packages」を 右クリックし、「New」→ Java Package」を選択 します。パッケージ名に org.glassfish.movieplex7. batch と入力し、「Finishをクリックします。 2. 新しく作成したパッケージ を右クリックし、「New→「Java Class」を 選択します。名前に SalesReader と入力します。 AbstractItemWriter を継 承するようにクラス定義を 変更し、インポート文を解 決します。 AbstractItemReader ItemReader インタフェー スを実装しています。 ItemReader インタフェー スには、項目のストリーム を読み取るためのメソッド が定義されています。 3. クラスレベルのアノテー ションである @Named @Dependent を追加し、 インポート文を解決しま す。 @Named アノテーショ ンを追加することで、こ の Beanをジョブ XML に インジェクションできるよ うになります。また、@ Dependent を追加するこ とで、この Bean のインジェ クションが可能になりま JOSH JUNEAU Java API for Batch Processing や Java Message Service の利用方法と、WebSocket によ るチャット・クライアントの作成方法を学習する パート 3 Java EE 7 を 360 度探索する Josh Juneau:ア プリケーション開 発者、システム・ アナリスト、DBA。 開発ではおもに Java、PL/SQL、 Jython/Python を利用。Jython Monthly ニュース レター、Jython Podcast、Jython Web サイトを管理 している。『Java EE 7 Recipes: A Problem-Solution Approach』 (Apress、2013 年)、『Introducing Java EE 7: A Look at What's New』 (Apress、2013 年)の著者。

パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

31

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

本記事は全 3 回シリーズの最終回です。このシリーズ

では、Java EE 7 で拡張された機能や、HTML5、WebSocket、JavaScript Object Notation

(JSON)処理などの比較的新しい Web 標準を使用して、最新型のエンタープライズ・アプリケーションを構築する方法について説明します。

このパート3 では、パート1とパート2 ですでに開発したmovieplex7アプリケーションを改良し、チケット売上の表示機能、映画ポイントを貯める機能、他のユーザーとのチャット機能を追加します。 注:アプリケーションのすべ

てのソース・コードは、こちらからダウンロードできます。

デモ・アプリケーションの概要パート1とパート2 では、NetBeans および GlassFish 4 のダウンロード方法、インストール方法、設定方法を学習しまし

た。本記事でもこの環境を利用して、アプリケーションの構築とデプロイを行います。これまでに、JavaServer Faces(JSF)2.2を使用し、さらにナビゲーション用の Faces Flow などの新しいテクノロジーを活用してアプリケーションを基礎から構築しました。Java Persistence API(JPA)2.1、Java API for RESTful Web Services(JAX-RS)、およびJSON Processing(JSON-P)1.0を利用して、ビジネス・ロジックやデータ操作を実装する方法を確認しました。

これ以降は、このシリーズのパート1とパート2 においてNetBeans IDE で作成したMaven ベースのプロジェクトを使用しながら手順を確認してください。

映画チケットの売上本項では、Java API for Batch Processing 1.0(JSR 352)を利用して、各上映の映画チケット

の売上をインポートし、CSVファイルから累積売上を読み取ってデータベースに挿入します。

バッチ処理とは、一連のタスクまたはジョブを実行する手法です。ほとんどの場合、バッチ処理のジョブは対話的な操作を必要とせず、一括処理を目的として長時間実行されます。バッチ処理の用語に関する詳細は、Java EE 7 Tutorial を参照してください。クラスの生成:まず、映画の売上を処理してデータベースに保存するためのクラスを作成します。

1. 「Source Packages」を右クリックし、「New」→

「Java Package」を選択します。パッケージ名にorg.glassfish.movieplex7.batchと入力し、「Finish」をクリックします。

2. 新しく作成したパッケージを右クリックし、「New」→「Java Class」を

選択します。名前にSalesReaderと入力します。AbstractItemWriter を継承するようにクラス定義を変更し、インポート文を解決します。

AbstractItemReader はItemReader インタフェースを実装しています。ItemReader インタフェースには、項目のストリームを読み取るためのメソッドが定義されています。

3. クラスレベルのアノテーションである@Namedと@Dependent を追加し、インポート文を解決します。

@Namedアノテーションを追加することで、この Bean をジョブ XML にインジェクションできるようになります。また、@Dependent を追加することで、この Bean のインジェクションが可能になりま

JOSH JUNEAU Java API for Batch Processing や Java Message Service の利用方法と、WebSocket によるチャット・クライアントの作成方法を学習する

パート3

Java EE 7を 360 度探索する

Josh Juneau:アプリケーション開発者、システム・アナリスト、DBA。開発ではおもにJava、PL/SQL、Jython/Pythonを利用。Jython Monthly ニュースレター、Jython Podcast、Jython Web サイトを管理している。『Java EE 7 Recipes: A Problem-Solution Approach』

(Apress、2013年)、『Introducing Java EE 7: A Look at What's New』

(Apress、2013年)の著者。

Page 2: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

32

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

す。 4. このクラスに以下のフィールドを

追加し、reader を宣言します。

5. リスト1の openメソッドを追加して、CSVファイルを読み取る処理を実装します。

この例では、CSVファイルをアプリケーションの META-INF ディレクトリ内に配置する必要があります。META-INF ディレクトリは、アプリケーション・ソース・パッケージのルートに位置します。

6. readItemメソッドをオーバーライドして、リスト2のコードに変更します。インポート文を解決します。

readItemメソッドは、ストリームから次の項目を読み取ります。ストリームの終了時は null を返します。

7. org.glassfish.movieplex7.batch パッケージに新しい Javaクラスを追加して、名前にSalesProcessorと入力します。クラス定義に以下のコードを追加して、ItemProcessor を実装します。

ItemProcessor の実装クラスでは、入力項目を操作し、出力項目を生成することができます。

8. クラスレベルのアノテーションである@Namedと@Dependentを追加し、インポート文を解決します。黄色の電球アイコンをクリックして、「Implement all abstract methods」を選択します(図 1)。

9. processItem の実装をリスト3のように変更し、インポート文を解決します。

processItemメソッドは新しいSales オブジェクトを作成し、次にStringTokenizerを作成します。このStringTokenizerを使用して、渡されたオブジェクト内の各項目を解析します。最後に、解析後の項目値を Sales オブジェクトに設定して返します。

10. org.glassfish.movieplex7.batch パッケージ内に新しいJavaクラスを作成して、名前にSalesWriterと入力します。クラス定義に以下のコードを追加して、AbstractItemWriter を継承

します。

11. クラスレベルのアノテーションである@Namedと@Dependentを追加し、インポート文を解決します。

12. 黄色の電球アイコンをクリックして javax.batch.api.chunk.AbstractItemWriter のインポート文を追加します。インポート文が追加された後、電球アイコンをクリックして「Implement all abstract methods」を選択し、クラスに writeItemsメソッドを追加します。

13. データ・ストアにアクセスするために、以下の宣言を追加してEntityManager インスタンスをクラスにインジェクションします。

14. リスト4に示すように、

writeItemsメソッド内のコードをforループに変更します。このループを使用して、バッチ実行時に集約されたすべての Sales オブジェクトを永続化します。

15. メソッドに @Transactional アノテーションを追加して、トランザクション制御を組み込みます。インポート文を解決します。

バッチ・ジョブの作成:次の作業は、XML に手続き型のタスクを実装することです。この例では、ジョブは 3 つの項目を含む 1 つのチャンク

(chunk)となります。3 つの項目とは、<reader> 要素、<processor> 要素、<writer> 要素であり、それぞれ対応するクラス実装は SalesReader、SalesProcessor、SalesWriter です。XML 内にタスクを作成するためには、以下の手順を実行します。

1. バッチ XMLファイルを格納する新しいフォルダを作成します。「META-INF」を右クリックして、「New」→「Folder」を選択し

private BufferedReader

implements ItemProcessor

extends AbstractItemWriter

@PersistenceContextEntityManager em;

図1

すべてのリストのテキストをダウンロード

public void open(Serializable checkpoint) throws Exception { reader = new BufferedReader( new InputStreamReader(Thread.currentThread() .getContextClassLoader().getResourceAsStream ("META-INF/sales.csv"))); }

リスト1 リスト2 リスト3 リスト4

Page 3: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

33

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

ます。フォルダ名に batch-jobsと入力し、「Finish」をクリックします。

2. XMLファイルを作成します。batch-jobsフォルダを右クリックし、「New」→「XML Document」を選択します。ファイル名に eod-salesと入力します。すべてデフォルト値のままにして、「Next」をクリックし、 「Finish」をクリックします。

XMLファイルの内容は以下のとおりです。

■ <chunk> の item-count 属性:ライターに渡される項目数(サンプルでは 3 つ)

■ <chunk> の skip-limit 属性:スキップされる例外の数(サンプルでは 5 つ)

■ <skippable-exception-classes/>:チャンク処理でスキップされる例外のセット

3. XML にジョブ定義を追加します。新しく作成したファイルの内容を、リスト5のコードに変更します。

バッチ・ジョブの起動:バッチ・ジョブの起動処理を実装します。

1. org.glassfish.movieplex7.batch パッケージを右クリックし、

「New」→「Session Bean」を選択します。名前に SalesBeanと入力し、「Finish」をクリックします。

2. この新しいセッション Bean に、リスト6の runJobメソッドを追加します。

このコードでは、

BatchRuntime を使用して新しいJobOperator を取得しています。次に、この新しい JobOperatorを使用して、eod-sales に記述されたバッチ・プロセスを開始します。この JobOperator は、ジョブの停止や再開のために使用することもできます。

3. クラスに @Namedアノテーションを追加して、インジェクションできるようにします。インポート文を解決します。

4. 以下のように、このクラスにEntityManager をインジェクションします。

5. このクラスに getSalesDataというメソッドを追加します。このメソッドは、@NamedQuery を使用して表のすべての行を返します

(リスト7)。インポート文を解決します。

6. 売上を表示するビューを作成します。「Web Pages」を右クリックし、「New」→「Folder」を選択します。フォルダ名にbatchと入力し、「Finish」をクリックします。新しく作成した作成したフォルダを右クリックし、「New」を選択して、「Faces Template Client」を選択します。ファイル名に salesと入力し、WEB-INF/template.xhtml を参照してテンプレートに指定して「Finish」をクリックします。<ui:composition>タグ内のすべ

ての内容を、リスト8のコードに置き換えます。黄色の電球アイコンをクリックして、名前空間の接頭辞とURI のマッピングを修正します。

このページには dataTable が含まれます。dataTable は、バッチ処理でデータベースにデータが挿入された後に、salesファイルの内容を表示するために使用されます。また、このページには、ジョブを実行するボタンとページを更新するボタンを示す 2 つのcommandButton も含まれます。

7. template.xhtmlファイルを編集し、リスト9のコードを追加して、sales.xhtml ビューへのリンクを

埋め込みます。8. 最後に、プロジェクトを実行し

て、左側のナビゲーション・メニューの「Sales」リンクをクリックし、Movie Sales ビューを開きます。「Run Job」ボタンをクリックすると、バッチ・ジョブが開始されます。このジョブによりCSVファイルが処理され、売上がデータベースの SALES 表に挿入されます。「Refresh」ボタンをクリックすると、処理された売上のリストが表示されます(図 2)。

映画ポイントmovieplex7アプリケーションに映画ポイント・システムを実装するために、

@PersistenceContextEntityManager em;

すべてのリストのテキストをダウンロード

<?xml version="1.0"?><job id="endOfDaySales" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <step id="populateSales" > <chunk item-count="3" skip-limit="5"> <reader ref="salesReader"/> <processor ref="salesProcessor"/> <writer ref="salesWriter"/> <skippable-exception-classes> <include class="java.lang.NumberFormatException"/> </skippable-exception-classes> </chunk> </step></job>

リスト5 リスト6 リスト7 リスト8 リスト9

Page 4: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

34

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

Java Message Service(JMS)2.0とその新規 API を使用します。JMS 2.0 では、以前のリリースと比較して、メッセージの送受信に必要なコード量が減り、複雑性も低減されているため、開発生産性が向上します。注:JMS を操作するためには、アプ

リケーション・サーバー・コンテナ内にトピックまたはキューを作成する必要があります。そのためには、コードを記述するか、アプリケーション・サーバーの管理ユーティリティを使用します。この例では、コードの記述によるキューの作成方法を説明します。JSF マネージドBeanの作成:まず、

映画ポイント・データを収集してキューに送信するために、JSF ビューにバインドされる JSF マネージド Bean を作成します。

1. movieplex7アプリケーション内に新しいパッケージを作成します。「Source Packages」を右クリックし、「New」→「Java Package」を選択します。名前に org.glassfish.movieplex7.pointsと入力して、「Finish」をクリックします。

2. 新しいパッケージ内にクラスを作成します。パッケージを右クリックし、「New」→「Java

Class」を選択します。名前にSendPointsBeanと入力します。Serializable を実装します。以下のクラスレベルのアノテーションを追加して、ここで作成した Bean を EL 式からインジェクトできるようにし、また、sessionスコープとして設定します。インポート文を解決します。

3. このクラスにリスト10の Stringフィールドを追加します。このフィールドは、ポイント・データを取得するための JSF のinputTextフィールドにバインドされます。このフィールドのgetter/setter を生成します。エディタ・ペインを右クリックして「Insert Code」を選択し、

「Getter and Setter」を選択します。フィールドを選択して、「Generate」をクリックします。 注:このフィールドでは、入力

されたテキストが必要な書式に従っているかを確認するために、

Bean 検証アノテーションが使用されます。

4. 以下のコードを追加して、このクラスに JMSContextとQueue のインスタンスをインジェクションします。インポート文を解決します。javax.jms.Queue をインポートすることに注意してください。

JMSContext は JMS 2.0 の新規インタフェースであり、Connection オブジェクトとSession オブジェクトを 1 つのオブジェクト内にまとめています。 注:Java EE に準拠した

アプリケーション・サーバーには、java:comp/DefaultJMSConnectionFactoryという名前のデフォルトの JMSコネクション・ファクトリが含まれています。コネクション・ファ

@Named@SessionScoped

@InjectJMSContext context; @Resource(mappedName = "java:global/jms/pointsQueue")

図2

@NotNull@Pattern(regexp = "^\\d{2},\\d{2}", message = "Message format must be 2 digits, comma,

2 digits, e.g. 12,12")private String message;

リスト10

すべてのリストのテキストをダウンロード

Page 5: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

35

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

クトリが明示的に指定されていない場合に、このデフォルトのファクトリが使用されます。

5. JMS キューにメッセージを送信するために、このクラスにリスト11のメソッドを追加します。

JMSContext のcreateProducerメソッドを使用してJMSProducerを作成できます。JMSProducer には、メッセージを構成して同期的または非同期的に送信するための各種メソッドがあります。JMSProducer のsendメソッドを使用して、キュー・インスタンスにメッセージを送信します。キュー・インスタンスについては、次の手順で作成します。

6. org.glassfish.movieplex7.points パッケージを右クリックし、「New」→「Java Class」を選択します。名前にReceivePointsBeanと入力します。Serializable を実装し、リスト12に示すクラスレベルのアノテーションを追加します。

JMS 2.0 で導入された @JMSDestinationDefinitionアノテーションを使用することで、必要なリソースのプロビジョニングをプログラムで行うことができ、アプリケーションの構成にかかる管理上のオーバーヘッドが削減されます。この例では、このアノテーションを使用してjava:global/jms/pointsQueueという名前の javax.jms.Queue を

作成します。7. 以下のコードを追加して、

JMSContextとQueue のリソースをインジェクションします。これらのリソースは、このクラス内で使用します。インポート文を解決します。javax.jms.Queue などの正しいクラスをインポートするようにしてください。

注:この例では @JMSDestinationDefinitionアノテーションによってキューを作成していますが、このキューを使用するためには、さらにpointsQueue でクラスにキューをインジェクションする必要もあります。

8. リスト13の receiveMessage() メソッドを追加します。

このメソッドは、JMSContextを使用してpointsQueue のコンシューマを作成し、キューから同期的に Stringメッセージを受信します。

9. リスト14の getQueueSizeというメソッドを追加します。このメソッドは現在キューにあるメッセージ数を返します。インポート文を解決します。

このメソッドは、QueueBrowser を作成し、これ

を使用してキューの各メッセージをトラバースして合計に追加します。

Facelet の作成:次に、映画ポイントを入力し、メッセージ送受信機能のシミュレーションを行うための Faceletビューを作成する必要があります。

1. 「Web Pages」を右クリックし、「New」→「Folder」を選択して、新しいフォルダを追加します。フォルダ名に pointsと入力して、

「Finish」をクリックします。 2. このフォルダ内に、points.xhtml

という新しい XHTMLファイルを作成します。このビューの<ui:composition> 要素内のコードをリスト15のコードに置き換えます。必要に応じて黄色の電

球アイコンをクリックして、名前空間の接頭辞とURI のマッピングを解決します。

このビューには、メッセージ入力用のフィールドと、sendMessageメソッドを呼び出す commandButton があります。このメソッドが呼び出された場合、inputText 内のメッセージがキューに追加され、queueSizeに 1 が加算されます。このビューのもう1 つの commandButtonは、receiveMessageメソッドを呼び出します。このメソッドが呼び出された場合は、キューからメッセージが読み取られ、queueSize から1 が減算されます。

@InjectJMSContext context;@Resource(mappedName= "java:global/jms/pointsQueue")

public void sendMessage() { System.out.println("Sending message: " + message); context.createProducer().send(pointsQueue, message); }

リスト11 リスト12 リスト13 リスト14 リスト15

すべてのリストのテキストをダウンロード

Page 6: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

36

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

3. template.xhtml にリスト16のコードを追加し、さらにアプリケーションからpoints.xhtmlビューにアクセスするための他の outputLinkコンポーネントも追加します。

movieplex7アプリケーションの実行: 1. 「Points」リンクをクリックします(図 3)。

現時点で、キューにメッセージは 1 つも含まれていません。

2. フィールドに 1212というテキストを入力し、「Send Message」をクリックします。 図 4のようなエラーが表示

されます。このメッセージは、

SendPointsBean に追加されたBean 検証によって生成されたものです。

3. フィールドのテキストにカンマを挿入して12,12とし、「Send Message」をクリックします。

今度はエラー・メッセージが表示されず、Queue Size が 1 増加します(図 5)。

4. 「Receive Message」ボタンをクリックします。メッセージがキューから読み出されるため、Queue Size が 1 減少します(図 6)。

任意の順序でメッセージの送受信を繰り返します。Queue Sizeは、メッセージが送信されるたびに 1 増加し、メッ

セージが受信されるたびに 1 減少します。

映画チャット本項では、WebSocket 1.0 API を使用してmovieplex7 の来場者用チャット・

ルームを構築します。WebSocket 1.0 APIには、接続開始のためのハンドシェイクとデータ転送の方法を定義した、単一 TCP 接続上での全二重 / 双方向通信のプロトコルが備わっています。

Java EE 7 には、JSR 356 で定義され

図4

<p/><h:outputLink value= "${facesContext.externalContext.requestContextPath}

/faces/points/points.xhtml"> Points</h:outputLink>

リスト16

すべてのリストのテキストをダウンロード

図3 図5

図6

Page 7: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

37

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

た WebSocket 用の標準 API が追加されています。そのため、開発者は、カスタマイズされたフレームワークではなく共通 API を利用して、WebSocketソリューションを作成できるようになりました。 WebSocket 通信を実装するクラスの作成:まず、WebSocket 通信を実装するための Javaクラスを作成します。

1. 新しいパッケージを作成します。「Source Packages」を右クリックし、「New」→「Java Package」を選択します。パッケージ名に org.glassfish.movieplex7.chatと入力します。

2. 「Source Packages」を右クリックし、「New」→「Java Package」を選択して、クラスを作成します。クラス名に ChatServerと入力します。

3. この新しいクラス内のコードをリスト17のコードに置き換えます。インポート文を解決します。特に、javax.websocket.Session をインポートすることに注意してください。

ChatServerクラスのコードの実行内容は以下のとおりです。 ■ @ServerEndpoint によって、このクラスが WebSocket エンドポイントであることが示されます。value 属性は、エンドポイントにアクセスするための URI を定義します。

■ @OnOpenアノテーションの付いたメソッドはセッションの開始時に呼び出され、@OnCloseアノテーションの付いたメソッドはセッションの

終了時に呼び出されます。各メソッドの Session パラメータには、接続の開始または終了を要求するクライアントを定義します。

■ @OnMessageアノテーションの付いたメソッドは、メッセージの受信時に呼び出されます。メソッドの第 1パラメータはメッセージのペイロード、第 2 パラメータは接続の相手を定義したクライアント・セッションです。 このメソッドは、接続中のすべてのクライアントに、受信したメッセージをブロードキャストします。Webビューの生成:次に、チャット・クライアントの Web ビューを生成します。

1. 「Web Pages」を右クリックし、「New」→「Folder」を選択します。名前に chatと入力し、「Finish」をクリックします。

2. 新しい XHTMLファイルを作成します。ファイル名に chatroomと入力し、WEB-INF/template.xhtml を参照してテンプレートに指定します。他の値はデフォルト値のままにして、「Finish」をクリックします。

3. <ui:composition>タグ内のすべての内容を、リスト18のコードに置き換えます。

このコードにより、チャット・クライアントとして使用するHTMLフォームを構成します。このフォームでは、チャット・ログと現在のユーザー・リストを表示するための 2 つの textarea

と、ユーザー名およびメッセージを入力するための入力textField が使用されます。さらに、WebSocket セッションを開くボタン、メッセージを送信するボタン、セッションを切断するボタンの 3 つのボタンがあります。

この 3 つのボタンのすべてがonclick 属性によって JavaScript関数にバインドされます。このJavaScript 関数で WebSocket 通信を実装します。この HTML の末尾付近にある<script> 要素には、JavaScriptファイルである

public class ChatServer {

private static final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());

@OnOpen public void onOpen(Session peer) { peers.add(peer); }

@OnClose public void onClose(Session peer) { peers.remove(peer); }

@OnMessage public void message(String message, Session client) throws IOException, EncodeException { for (Session peer : peers) { if (!peers.equals(client)) { peer.getBasicRemote().sendObject(message); }

} }}

リスト17 リスト18

すべてのリストのテキストをダウンロード

Page 8: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

38

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

websocket.js が示されています。4. WebSocket 通信の実装を含

む JavaScriptファイルを作成します。Web Pagesに含まれる「chat」を右クリックし、

「New」→「Web」を選択して、「JavaScript File」を選択します。ファイル名に websocketと入力して、「Finish」をクリックします。websocket.js を編集し、リスト19aと19bのコードを追加します。

この websocket.js 実装は、ChatServerクラスに指定されたURI を付加することで、エンドポイントURIを作成します。その後、新しい WebSocket オブジェクトを作成し、このファイル内に実装される JavaScript 関数に対して、WebSocket イベント関数を割り当てます。ユーザーがページ上の

「Join」ボタンをクリックすると、ユーザー名が取得され、最初のWebSocket オブジェクトの sendメソッドが呼び出されて、そのユーザー名が渡されます。

メッセージの送信時に、関連するデータが send_message 関数にパラメータとして渡されます。この関数は、メッセージにusername を付加してすべてのクライアントにブロードキャストします。メッセージを受信するたびに onMessageメソッドが呼び出され、ログイン・ユーザーのリストが更新されます。ページ上の「Disconnect」ボタンは、WebSocket 接続を閉じる処理を開始します。

5. WEB-INF/template.xhtml を編集し、Item 2 の outputLink 要素をリスト20のコードで上書きします。

6. プロジェクトを実行し、画面左側のメニューの「Chat Room」リンク(図 7)をクリックしてチャット・ルームに移動します。

チャット・ルームの下部にCONNECTEDというメッセージが表示されます(図 8)。

7. 別のブラウザを開き、URI localhost:8080/movieplex7 を入

var wsUri = 'ws://'+ document.location.host + document.location.pathname.substr(0, document.location.pathname.indexOf ("/faces")) + '/websocket';console.log(wsUri);var websocket = new WebSocket(wsUri);var username;websocket.onopen = function(evt) { onOpen(evt);};websocket.onmessage = function(evt) { onMessage(evt);};websocket.onerror = function(evt) { onError(evt);};websocket.onclose = function(evt) { onClose(evt);};var output = document.getElementById("output");function join() { username = textField.value; websocket.send(username + " joined");}function send_message() {

websocket.send(username + ": " + textField.value);}

リスト19a リスト19b リスト20

すべてのリストのテキストをダウンロード

図7

Page 9: パート3 Java EE 7を360度探索する - Oracle · 本記事は全3回シリーズの 最終回です。このシリーズ では、Java EE 7で拡張された 機能や、HTML5、WebSocket、

ORACLE.COM/JAVAMAGAZINE ///////////////////////////// MARCH/APRIL 2014

JAVA TECH

39

COM

MUNITY

JAVA

IN A

CTIO

NAB

OUT US

blog

//new to java /

力してチャット・ルームを開きます。いずれかのブラウザ・ウィンドウで「Join」をクリックし(このブラウザを「ブラウザ 1」とし

ます)、Dukeとしてチャット・ルームに参加します。もう一方のブラウザ・ウィンドウ(「ブラウザ 2」)でも、ユーザー・リストが更新

されます。ブラウザ2で別の名前(例:Duke2)を使用してセッションに参加すると、各ウィンドウのユーザー・リストが更新されます

(図 9)。注:Chrome Developer Tools

を使用して、WebSocket のトラフィックを監視できます。

まとめ 本記事では、パート1とパート2 で開発した movieplex7アプリケーションを改良し、映画の売上の計算機能、映画ポイントの付与機能、他のユーザーとのチャット機能を追加しました。本記事では以下のテクノロジーを使用しました。

■ Batch Processing for Java EE ■ JMS 2.0 ■ WebSocket 1.0この全 3 回のシリーズでは、Java EE

7 で利用できる新機能を駆け足で紹介しました。Java EE 7 の詳細は、オンライン・チュートリアルをご覧ください。</article>

図8

図9

LEARN MORE• このシリーズのパート1• このシリーズのパート2