Archive for 5月, 2013

ご注意(NOTE): WebSocket with Concurrency for EE

Java EE 7 のリリースが控えておりますが、先日 Java Day Tokyo で私のセッションの中でデモした WebSocket (JSR-356) と Concurrency Utilities for EE (JSR-236) を組み合わせたデモのコードについてご紹介すると共に、実装時の注意点をご報告いたします。

下記は、実際に私が WebSocket (JSR-356) と Concurrency Utilities for EE (JSR-236) を組み合わせたコードを実装する際にハマった内容をお届けします。
コードは下記のようなコードを記載しています。

package jp.co.oracle.websocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.enterprise.concurrent.ManagedExecutorService;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import jp.co.oracle.tasks.WebSocketAIRSearchTask;
import jp.co.oracle.tasks.WebSocketHotelSearchTask;

@ServerEndpoint(value = "/asyncResult")
public class AsyncResultWebSocketEndpoint {

    private static final Logger logger = Logger.getLogger(AsyncResultWebSocketEndpoint.class.getPackage().getName());

    // Concurrency Utilities for EE の ManagedExecutorService をインジェクト
    @Resource(name = "concurrent/DefaultManagedExecutorService")
    ManagedExecutorService managedExecsvc;

    // WebSocket のコネクションがオープンした際の処理
    @OnOpen
    public void initOpen(Session session) {
        executeTasks(session);
    }

    // WebSocket クライアントからメッセージを受信した際の処理
    @OnMessage
    public void receivedMessage(String message, Session session) {
        if (!message.equals("re-execute")) {
            return;
        }
        executeTasks(session);
    }

    // 実際の処理内容
    private void executeTasks(Session session) {
        // 複数タスクの実行の際に終わった順に処理結果を取り出す
        ExecutorCompletionService<String> execCompService = new ExecutorCompletionService<>(managedExecsvc);

       // 複数タスクの登録
        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
                WebSocketHotelSearchTask task = new WebSocketHotelSearchTask(i);
                futures.add(execCompService.submit(task));
        }
        try {
            // 終了したタスクの順番に処理結果を取得し
            // 処理結果を WebSocket のクライアント・エンドポイント
           // に対して処理結果を送信
            for (Future<String> results : futures) {
                String resultString = execCompService.take().get();
                session.getBasicRemote().sendText(resultString);
            }
        } catch (IOException | InterruptedException | ExecutionException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }
}

ダミーのタスク

package jp.co.oracle.tasks;

import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WebSocketHotelSearchTask implements Callable<String> {

    private static final Logger logger = Logger.getLogger(WebSocketHotelSearchTask.class.getPackage().getName());
    private int counter;

    public WebSocketHotelSearchTask(int counter) {
        this.counter = counter;
    }

    // タスクの処理内容によっては時間のかかるタスクもあるため
 // 半分のタスクをわざと 4 秒待たせ、タスクの登録順にタスクが
    // 完了しないように作成
    @Override
    public String call() {
        String result = "";
        if (counter % 2 == 1) {
                Thread.sleep(4000);
         }
            result = "ホテル検索タスク完了 : 終了タスクの ID" + counter;;
        } catch (InterruptedException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        return result;
    }
}

今回、なぜ下記のようにタスクの一括登録を行った後に、タスクの処理が終わった順に WebSocket のクライアント・エンドポイントに対してメッセージ配信を行うコードを実装したかというと(つまり、タスクの処理コード中から WebSocket のクライアントに対してメッセージ配信をしていない)、WebSocket 側のスレッドの制限があったためです。

       // 複数タスクの登録
        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
                WebSocketHotelSearchTask task = new WebSocketHotelSearchTask(i);
                futures.add(execCompService.submit(task));
        }
        try {
            // 終了したタスクの順番に処理結果を取得し
            // 処理結果を WebSocket のクライアント・エンドポイント
           // に対して処理結果を送信
            for (Future<String> results : futures) {
                String resultString = execCompService.take().get();
                session.getBasicRemote().sendText(resultString);
            }

当初、下記のように Runnable (Callable の call() 中で実装も可)のインタフェースを実装したタスクを作成し、タスクの処理の中で WebSocket のエンドポイントに対してメッセージを配信するコードを記載しました。例えば、下記のような感じです。

public class SomeMyTask implements Runnable{
   Session session;
   public SomeMyTask(Session session){
       this.session = session;
   }

    @Override
     void run(){
           // 何らかの処理を実施
           // タスクの処理の最後に、WebSocket のクライアント・エンドポイント
           // に対してメッセージを配信
           session.getBasicRemote().sendText(resultString);
     }
}

そして、下記のコードを書いてタスクを実行しました。

    for( int  i = 0 ; i < 10 ; i++ ){
        SomeMyTask task = new SomeMyTask(session);
        managedExecsvc.submit(task);
    }

すると下記の例外が発生しました。

例外の出力内容:

java.lang.IllegalStateException: HeapBuffer has already been disposed
at org.glassfish.grizzly.memory.HeapBuffer.checkDispose(HeapBuffer.java:802)
at org.glassfish.grizzly.memory.HeapBuffer.position(HeapBuffer.java:188)
at org.glassfish.grizzly.nio.transport.TCPNIOAsyncQueueWriter.fillByteBuffer(TCPNIOAsyncQueueWriter.java:194)
at org.glassfish.grizzly.nio.transport.TCPNIOAsyncQueueWriter.writeComposite0(TCPNIOAsyncQueueWriter.java:151)
at org.glassfish.grizzly.nio.transport.TCPNIOAsyncQueueWriter.write0(TCPNIOAsyncQueueWriter.java:80)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.processAsync(AbstractNIOAsyncQueueWriter.java:458)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:110)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:722)

なぜだろうと、Grizzly のソースコードを追ってみると、既にヒープが開放されてしまっているようです。

800     protected final void  [More ...] checkDispose() {
801         if (heap == null) {
802       throw new IllegalStateException(
803                     "HeapBuffer has already been disposed",
804                     disposeStackTrace);
805         }
806     }

当初バグかとも思ったのですが念のため、WebSocket (JSR-356) 仕様のスレッド関連部分をチェックしてみました。すると下記の 5.1 に WebSocket に関するスレッドの注意書きが記載されておりました。

5.1 Threading Considerations
Implementations of the WebSocket API may employ a variety of threading strategies in order to provide a scalable implementation. The specification aims to allow a range of strategies. However, the implementation must fulfill certain threading requirements in order to provide the developer a consistent threading environment for their applications.

Unless backed by a Java EE component with a different lifecycle (See Chapter 7), the container must use a unique instance of the endpoint per peer. [WSC-5.1-1]

In all cases, the implementation must not invoke an endpoint instance with more than one thread per peer at a time. [WSC-5.1-2]
(※ まさにここに記載されており、同時にピア毎に1つ以上のスレッドからエンドポイントのインスタンスを呼び出してはならない。)
と記載されておりました。

The implementation may not invoke the close method on an endpoint until after the open method has completed. [WSC-5.1-3]

This guarantees that a websocket endpoint instance is never called by more than one container thread at a time per peer. [WSC-5.1-4]

If the implementation decides to process an incoming message in parts, it must ensure that the corresponding onMessage() calls are called sequentially, and do not interleave either with parts of the same message or with other messages [WSC-5.1.5].

つまり、タスクの実行自身は複数のスレッドで実行できるのですが、WebSocket のクライアント・エンドポイントへのメッセージ送信は1箇所にまとめて実装しなければならない事に気付き上記のようなコードを書いています。

個人的には、マルチスレッドから WebSocket のクライアント・エンドポイントにメッセージ送信ができるようになるとより便利になるのではないかと思いますが、皆様如何でしょう? もちろん、既に仕様は FIX して Java EE 7 のリリース時点では無理ですし、Grizzly 等サーバ側の実装も今のままだと難しい部分があるかもしれません。しかし、皆様で声を上げていけば、時期 Java EE 8 の WebSocket 1.1 当たりで、マルチスレッドからのメッセージ送信もできるかも?!しれないので、賛同して頂ける方がいらっしゃったら、まとめて報告したいなと思っております。
(仕様上ダメって断られる可能性ももちろんありますが。(^_^;))

でも、昔と違って今の Java はこういった事がスペック・リードやエキスパート・グループメンバーに伝えやすい環境なんですよ!!
JJUG として Adopt-A-JSR プログラムに参加し、日本から改善要望なども出していけるといいですね。

2013年5月23日 at 4:34 午後

Java EE 7 ローンチ・イベント開催日決定

もう、すでにご存知の方も多いかと思いますが、6/12日 Java EE 7 が正式にリリースされます。これに合わせ、Java EE 7 ローンチ・イベントが 6/13(木) 日本時間の午後1時からオンラインで開催されます。Java EE 7の新機能にご興味のある方は是非ご参加下さい。本イベントは2回同じ内容が繰り返し開催される予定で1回目は日本の深夜の時間帯に実施されます。

ご登録はコチラから

3 年前の Java EE 6 のローンチ・イベントは日本時間の夜中に1度しか開催されなかったため、多くの日本人にとっては参加がしずらかったのですが、今回は US の現地時間で深夜までエンジニアが頑張ってくれています。こういった US のエンジニアの頑張りはとてもありがたいと共に、こうして与えられた貴重なお祭りイベントに是非日本の Java 開発者の皆様もご参加ください。

当日のスピーカーは Java 全体の開発部門のトップを務める、Hasan Rizvi の他、先日 Java Day Tokyo 2013 のために来日してくれた Cameron Purdy 、そして WebLogic/GlassFish のアプリケーション・サーバの開発部門のトップである Anil Guarといった Java EE 業界のトップ達が登場する他、
Java EE 7のスペックリードである Linda DeMichiel や日本でもおなじみとなった、Java EE のエバンジェリストである Arun Gupta も登壇します。

当日は、Java EE 7 に含まれる各種要素技術 (JSON, WebSocket, JAX-RS, JSF, Servlet, Batch, Concurrency, JMS, JPA, EL, EJB, CDI, Bean Validation, JTA, Interceptors, GlassFish の管理機能) をそれぞれ 15-20 分でご紹介する他、ライブ・チャットも用意されているので、エキスパート・グループのメンバーと情報交換をする事もできるようです。

日本人も参加しやい時間帯で開催される、このローンチ・イベントに是非、日本の Java 開発者の皆様もご参加ください。

PS.
GlassFish のコミュニティ・サイトではリリースまでのカウントダウン・タイマーが表示されています。

2013年5月22日 at 8:10 午後 1件のコメント

Java Day Tokyo 2013 の御礼について

御礼メッセージが遅くなり申し訳ございませんでした。

2013年5月14日Java Day Tokyo を開催し、日本全国より御参加頂きまして誠にありがとうございました。昨年の JavaOne Tokyo 2012 に引き続き、オラクルになって2度目の大規模な Java イベントに、昨年の JavaOne 以上にご登録を頂き、また非常に高い参加率でご来場頂きまして誠にありがとうございました。
Java Day Tokyo は JavaOne とは違い無償のイベントとして開催したため、JavaOne Tokyo とはまた違う形で開催しましたが如何でしたでしょうか。我々の至らぬ点も多々あったかと思います。皆様から頂いたフィードバック、アンケートを元に、また次回開催する場合には、今回の教訓を生かしていきたいと考えております。

今回イベント終了後、海外から参加してくれた、全エンジニアと会話をしましたが、日本のイベントは素晴らしい!!また次回開催する際には必ず参加すると言っていただきました。これもご参加頂いた皆様の思いが彼らに伝わった事による物と思います。このように皆様が盛り上がってくだされば、優秀なエンジニアを日本に招きやすくなりますし、我々としても色々な点で活動がしやすくなってまいります。かつてのように世界において日本のマーケットは大事にしなければならないと思わせる良い機会になったと強く思うとともに、ご参加頂いた皆様に大変感謝いたしております。

また、JavaOne Tokyo に引き続き、JJUG を始めとする、Java のコミュニティ・メンバーの皆様にも大変感謝いたしております。当日御発表頂きました内容は別途サイトの方へ反映されるかと思いますが、ここで改めて、各種セッションでお世話になった皆様をご紹介します。

* 基調講演
 JJUG 会長の鈴木雄介さん (Twitter:@yusuke_arclamp)

* Java IDE の最新トレンド
Eclipse 竹添 直樹さん (Twitter:@takezoen)
NetBeans きしだ なおきさん (Twitter:@kis)
IntelliJ 今井 勝信さん (Twitter:@masanobuimai)
モデレータ:山本裕介さん (Twitter:@yusuke)

* 帰ってきた Java パズラー
岡崎 隆之さん (Twitter:@watermint)
橋本 吉治さん (Twitter:@hasssie)

* Java The Night
 1.徳益 芳郎さん
 2.千葉優輝さん、小野貴史さん
 3.青江 崇さん (Twitter:@aoetk)
 4.小出 洋さん (Twitter:@hirosk)
 5.櫻庭 祐一さん (Twitter:@skrb)
 6.末永 恭正さん(Twitter:@YaSuenag)
 7.蓮沼 賢志さん(Twitter:@btnrouge)
 8.太田昌文さん(Twitter:@masafumi_ohta)
 9.奥 清隆さん(Twitter:@kiy0taka)

特に、千葉優輝さん、小野貴史さんは、北海道の大学に所属する現役の学生さんで、今回わざわざ北海道からこのイベントに駆けつけてくださいました。千葉さん、小野さん本当にありがとうございました。ご協力頂きました皆様、本当にありがとうございました。

最後に、
ご参加頂きました皆様、ご協力頂きました皆様、今後の日本における Java の発展のためにも、是非今後ともどうぞ宜しくお願いします。そしてまたイベントを開催する際には是非多くの Java 開発者の皆様に足をお運び頂ければ誠に幸いです。

今後ともどうぞ宜しくお願いします。
寺田

2013年5月18日 at 4:39 午前

Concurrency Utilities for EE 7

本日は、Java Day Tokyo に非常に多くの Java 開発者の皆様にお集まりいただきまして誠にありがとうございました。本日私が C-4 のセッション「エンタープライズ環境における並列処理の実装方法について」で説明した資料に参考メモを付加した、参照用のバージョンを下記に公開します。

また併せて説明時に使用したデモ(CPU 256 個の環境で Java を並列処理実行させた際のデモンストレーション)動画も下記に公開します。下記のデモは内部的に単なる Σ 計算を行なっているだけなのですが、デモ動画をご覧いただくとわかるのですが、単なる逐次処理、JDK 1.0 からある昔ながらの Thread 生成方法、Concurrency Utilities を利用した場合で、どの位 CPU リソースの利用状況が変わるかを視覚的にご覧いただけるかと思います。

※ 昔 Java は遅いと言われた時代がありましたが、今の Java を未だに遅いとか言っている方は正直勉強不足ではないかと思います。本デモのように、Java VM(実行環境)は非常にハイ・パフォーマンスで、ハイ・スケーラブルな実行環境です。現実的には、256 個の CPU を使い切る場面はないかと思いますが、Java はこのように適切にプログラミングを行うと、必要に応じて CPU を全て使い切る事もできる素晴らしい実行環境です。

Concurrency Utilities for Java EE は、
今まで Servlet コンテナ(AKA Web コンテナ)、EJB コンテナで禁止されていた、スレッド生成を、安全に EE 環境にも適用できる物です。単なる非同期と並列処理の違いをご理解頂き、バックグラウンドで非同期かつ並列に実行したい複数のタスクがある場合には、このAPI はとても有用です。

今回、発表時に使用したデモの全てのソースコードを下記に公開していますので、Asyn Servlet, Async EJB, JMS&MDB を含む非同期処理、さらには非同期並列処理にご興味ある方はどうぞご参照いただければ幸いです。中には WebSocket と Concurrency の連携デモのソースコードも含まれます。
是非、ご参照頂ければ幸いです。

https://github.com/yoshioterada/ConcurrentUtil4EE

2013年5月15日 at 12:10 午前

Java SE7API日本語版提供開始

2013 年 5 月 14 日、日本オラクルより新しい発表を行います。本日 5 月 14 日に日本語版 Java SE API ドキュメントを正式公開しました。

「Java Platform, Standard Edition 7」の最新情報を記載したドキュメント類の日本語版を本日公開しました。

公開先URL:http://www.oracle.com/technetwork/jp/java/javase/documentation/

・本日公開した「Java Platform, Standard Edition 7」の最新ドキュメントは、2011年7月に提供開始した「Java Platform, Standard Edition 7 (Java SE 7)」が提供する機能紹介、コンポーネント一覧を記載した参照資料です。Java開発者やこれからJavaプログラミング技術を習得する開発者は、この資料を参照することで、Java SE 7 が提供する各種機能を理解し、最新Java標準技術に基づいたプログラミングやアプリケーション開発に役立てることができます。

「Java Platform, Standard Edition 7」 の最新ドキュメントの構成
・「Java Platform, Standard Edition 7」の最新ドキュメントの日本語版は主に、「Java Platform, Standard Edition 7 ドキュメント」と「Java Platform, Standard Edition 7 API 仕様」の2つから構成されています。4,024のプログラム部品群(クラス)、そのクラスを集約した210のパッケージ、およびそれらに関連したドキュメント類など、合計約13,000種類のファイルが含まれます:
・ 「Java Platform, Standard Edition 7 ドキュメント」日本語版は、Java SE 7の構成要素をまとめた資料で、Java SE Development Kit (JDK)、Java SE Runtime Environment (JRE)、およびJava SEの API それぞれが提供する機能を参照できます。

公開先URL: http://docs.oracle.com/javase/jp/7/

・ 「Java Platform, Standard Edition 7 API 仕様」日本語版は、Java SE が提供するクラスやインタフェースなどの一覧を示しています。
公開先URL:http://docs.oracle.com/javase/jp/7/api/

2013年5月14日 at 7:47 午後 6件のコメント

Java Day Tokyo 2013 の Twitter ハッシュ・タグについて


Java Day Tokyo 2013 が本日午前から開催されますが、Java Day Tokyo の各セッションにおける Twitter のハッシュ・タグをオフィシャル・ページで公開していませんでした。
そこで私のブログで Java Day Tokyo 2013 のセッション毎の Twitter ハッシュ・タグを記載しました。明日は大変恐れ入りますが、下記のハッシュ・タグをご利用いただければ誠に幸いです。皆様の Tweet を心よりお待ち申し上げます。(L1 だけ大文字とさせていただけないでしょうか。)
また、会場では フリーの Wifi 環境が整っておりません、大変恐れ入りますが、モバイルの WiFi ルータをお持ちの方は大変恐れ入りますがご持参いただければ誠に幸いです。

10:30-12:00 基調講演(#jdt2103L1)
12:20-13:10 Ask The Experts! (#jdt2013s1)
13:30-14:20 ここからはじめる、JSR-356 WebSocket
(#jdt2013a1)
Raspberry Pi NightHacking (Java SE / JavaFXを楽しもう)
(#jdt2013b1)
OCJP Silver SE 7 資格試験の傾向と対策
(#jdt2013d1)
14:35-15:25 Java SE 8 による関数プログラミングの構文と並列処理のシンプル化
(#jdt2013a2)
Internet of Thingsにおける Java: Small, Smart,
Connected (Java ME Embedded)
(#jdt2013b2)
エスケイプ・フロム・レガシJ2EE
(#jdt2013c2)
Java IDE の最新トレンド
(#jdt2013e2)
15:40-16:30 Java プラットフォームにおける Batch アプリケーション (JSR 352)
(#jdt2013a3)
Groovy, Clojure, Scala,
VisageでのJavaFX活用
(#jdt2013b3)
Device to Data Centerを実現するJava Embedded Suite
(#jdt2013c3)
OCJP Gold SE 7 資格試験の傾向と対策
(#jdt2013d3)
16:45-17:35 タブレット用の JavaFX アプリケーション開発
(#jdt2013a4)
InvokeDynamic からNashorn のご紹介
(#jdt2013b4)
エンタープライズ環境における並列処理の実装方法について
(#jdt2013c4)
帰ってきた Java パズラー
(#jdt2013e4)
18:00-20:00 Java The Night (#jdt2013a5)

2013年5月14日 at 2:48 午前

Java Day Tokyo 2013 を明日にひかえて

皆様、明日はいよいよ Java Day Tokyo 2013 が秋葉原で開催されます。ご登録頂きました皆様、本当にありがとうございました。

JavaOne とは別に、日本オラクルで独自に企画・開催するこの Java のイベントに、日本全国から参加のご登録をいただきまして誠にありがとうございました。当初、JavaOne の名前が付かないこの無償イベントにどの位の皆様にご登録いただけるか心配しておりましたが、私達が想定していた以上に数多くの皆様にご登録いただけた事を大変嬉しく思うと共に、ご登録頂いた皆様に心より感謝を申し上げます。

この Java の開発者の皆様の盛り上がり、ご登録者数、御参加者数の結果が、また次のイベントにつながるかと思うと、主催者側の1人として今回のご登録者数は大変嬉しく思うとともに、皆様に大変感謝いたしております。明日は、皆様のお越しを心よりお待ち申し上げます。

さて、明日は非常に多くの皆様にご参加いただくため、当日は朝の受付も混雑が予想されます。基調講演はメイン会場の他、サテライト会場もご用意しておりますが、メイン会場でできるだけ良い席でご覧いただきたいという方は是非、朝お早めにご来場いただければ嬉しく思います。

当日の基調講演開催場所はアキバ・スクエアになります。また、このアキバ・スクエアでは、午後から始まるテクニカル・セッション A-x の枠がこの部屋を利用します。その他の午後のテクニカルセッションにつきましては、同じビルにある UDX GALLERY を B-x,C-x 枠、そして UDX GALLERY NEXT を D-x, E-x 枠 を利用します。

また、喫煙者の皆様におかれましては、ホール・会議室周辺にはないため、5F の喫煙所まで足をお運びいただければ幸いです。

基調講演が終わった後、昼食の時間帯(12:20-13:10)に「S-1 : Ask The Experts ! 」のセッションが開催されます。このセッションにご参加いただく皆様は、是非お弁当持参でご参加いただければ幸いです。また、このセッションは、US のオラクル社員に対して直接皆様からご質問が頂ける、もしくはご意見をお伝えいただく事ができる貴重な機会です。Java SE, JavaFX, Java EE それぞれのエキスパートが皆様からの貴重なご質問、ご意見をお待ちしておりますので、是非皆様お持ちよりいただければ幸いです。

午後 13:30 より、午後のセッションが本格的に始まりますが、C-1 セッションにご登録頂いていた皆様には、大変申し訳ございません。セッションを担当する予定だった者が急病となってしまい、キャンセルせざるおえない状況となってしまいました。大変恐れ入りますが、この状況をご理解いただければ誠に幸いです。

その他のセッションにつきましては、是非皆様楽しみにしていていただければ幸いです。今回、日本に来ている外人講師は全員、本場 JavaOne でも発表するような世界中で活躍しているエバンジェリストです。JavaOne インドが先週開催されていたのですが、JavaOne インドが終わった後、その足で皆日本に駆けつけてくれています。(正直、彼らにはハード・スケジュールでお願いしていて、申し訳ない気持ちも多々あるのですが)昨年の JavaOne や Java Developers Workshop 等にご参加頂いた皆様全員の(日本の Java 開発者)盛り上がり、熱狂ぶりを知っているので、こうして心よく来てくれているのではないかと思います。

今回、初来日の外人講師が2名(Stephen Chin、Jim Weaver)います。この2人は JavaFX をやっている方ならば知らない人はいないという程、世界的に有名なエンジニアで、2人とも昨年オラクルに入社されたのですが、その前は2人とも Java Champion で「Pro JavaFX2」の著者としても有名です。JavaFX にご興味のある皆様は是非、Chin-san, Jim-san にお声掛けください。

また、E-4 の「帰ってきた Java パズラー」は、私のウラ番組でなければ、私自身が一番行きたいセッションの一つなのですが、このセッションもとても楽しんでいただけると思いますので、ご興味のある方はぜひご参加ください。

最後に、”Java The Night” ですが、18:00-20:00 まで開催致しますが、是非、最後まで楽しんでいただければとおもいます。本日までベールに包んでいましたが、Java The Night では、日本の各 Java テクノロジーを代表するスーパー・エンジニア達に、1人8分で Java を使った技術でデモをしていただく、時間制限ありの LT っぽい、デモ大会を行います。Java VM, JavaFX, Java EE, GlassFish, SunSPOT, Raspbery PI など、Java を使って、もしくは Java その物に対して、いろんなデモをご覧いただけます。明日からすぐ使える技術、使ってみたいと思うような技術、これすげぇ!!といった内容がご覧いただけるかと思います。Java ってオモシロイね!!と思っていただけるよう、9人の猛者がお届けします。どうぞお楽しみになさってください。

※ 受講票は忘れずにプリントアウトしてご持参ください。事前にご登録を頂いていた場合も、再チェックに時間を要してしまうため、ご自身の受付がスムーズにできなくなる可能性がございます。

また、明日は Java の日のため、スーツ・コスプレでお越しいただいても結構ではございますが、是非 Java の正装(春の装い)でお越しください。(^_^)

2013年5月13日 at 3:35 午後

JJUG CCC 2013 Spring の発表資料について

本日、JJUG CCC 2013 Spring が開催されました。Oracle からはUS Oracle Corporation からJim Weaver (Twitter : @JavaFXpert) が基調講演で「What’s New for JavaFX in JDK 8」を発表し、午後一のセッションで、「Java EE 6 から Java EE 7 に向かって」というセッションを担当しそれぞれ発表しました。2人の発表資料を公開しましたのでご報告します。

(※ 私のプレゼン資料ですが、SlideShare にアップロードした際、SlideShare 側の問題で、フォントが無いせいか、私が使用しているオリジナル・フォントからは変わって表示されています。その点ご了承頂ければ幸いです。)


基調講演-2 What’s New for JavaFX in JDK 8


H-1 Java EE 6 から Java EE 7 に向かって

今日の私のプレゼン中で行った EL(Expression Language) 3.0のデモのソース・コードも下記に公開します。デモ用に簡単に作ったものであるため、本来 JPA で DB 接続すべき所を簡単にダミーデータ(Person#createDummyData())を作成しています。

本コードは JSF 2.0 と CDI をご存知の方であれば容易にご理解いただけるかと思いますが、「全データ抽出」のボタンを押下すると、CDI の getAllData() が呼び出され、indexManagedBean.data(ArrayList) に全データがコピーされ、その一覧が dataTable に表示されます。

次に、「年齢フィルタ」のテキストフィールド(デフォルト:0)に対して年齢を入力すると、入力された年齢以上のデータを表示しています。内部的には Ajax を使って、入力された年齢情報(indexManagedBean.ageFileter)をサーバに送信し、Ajax のリスナーとして定義しているindexManagedBean.updateData()を実行していいます。ただ、indexManagedBean.updateData()は処理は何もしていません、ここでは execute=”ageFilter” をサーバに送信し、その結果を render=”tabledata” 、つまり dataTable の内容を更新するためだけにupdateData()を呼び出しています。

<h:dataTable id="tabledata" value="#{afilter = indexManagedBean.ageFileter;indexManagedBean.data.stream().filter(p-> p.age >= afilter).toList()}" var="person" border="1">

この例では、一度 DBに対してクエリを実行し、その結果をコレクションにコピーした後、さらにそのコピーしたデータに対して絞り込みを行っています。DB に対して再度クエリをなげるのではなく、EL 3.0 の Lambda 式を使って、一旦取得したデータを元に再フィルタリングを 行っています。

セッション中でも話をしましたが EL 3.0 で Lambda 式(及び LINQ 式)が使えるようになった事でビューにロジックを埋め込む事が可能になりますが、あまりやりすぎると可読性の低下にもつながりますので使う範囲はよくご検討頂いた方がよいのではないかと思います。(※ .Net の LINQ 式は DB に対しても操作可能ですが、EL 3.0 における LINQ 式はコレクションに対してのみ有効です。)

今回の例では、一旦取得したデータのフィルタンリグ等でご使用頂く事で、DB に対する負荷、インメモリ・グリッドにあるキャッシュから取得するよりもパフォーマンスがよくなる事を想定し記載しています。なぜならばヒープメモリ内にあるデータを直接操作する方がパフォーマンス的に優れるためです。(※ コレクションに対して有効な操作である事をご認識頂き用途は十分にご検討ください。)

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      >
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:commandButton value="全データ抽出" action="#{indexManagedBean.getAllData()}"/><br/>

            <h:outputLabel value="年齢フィルタ"/>:
            <h:inputText id="ageFilter" value="#{indexManagedBean.ageFileter}" autocomplete="off">
                <f:ajax event="keyup" execute="ageFilter" render="tabledata" listener="#{indexManagedBean.updateData()}"/>
            </h:inputText>

            <h:dataTable id="tabledata" value="#{afilter = indexManagedBean.ageFileter;indexManagedBean.data.stream().filter(p-> p.age >= afilter).toList()}" var="person" border="1">
                <h:column> 
                    <f:facet name="header">
                        <h:outputText value="名前"/> 
                    </f:facet>
                    <h:outputText value="#{person.name}"/>
                </h:column> 
                <h:column> 
                    <f:facet name="header">
                        <h:outputText value="年齢"/> 
                    </f:facet>
                    <h:outputText value="#{person.age}"/>
                </h:column> 
                <h:column> 
                    <f:facet name="header">
                        <h:outputText value="性別"/> 
                    </f:facet>
                    <h:outputText value="#{person.sex}"/>
                </h:column> 
            </h:dataTable>
        </h:form>
    </h:body>
</html>
package jp.co.oracle.ee7samples.cdi;

import java.util.ArrayList;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import jp.co.oracle.ee7samples.model.Person;

@Named
@ViewScoped
public class IndexManagedBean {

    private ArrayList data;
    private Integer ageFileter;

    public ArrayList getData() {
        return data;
    }

    public void setData(ArrayList data) {
        this.data = data;
    }

    public Integer getAgeFileter() {
        if (ageFileter == null) {
            return new Integer(0);
        }
        return ageFileter;
    }

    public void setAgeFileter(Integer ageFileter) {
        this.ageFileter = ageFileter;
    }

    public String getAllData() {
        setData(Person.createDummyData());
        return "";
    }

    public String updateData() {
        return "";
    }
}

デモの中でもお伝えしましたが、本来 JPA で DB に接続して Person Entity に対して全レコードを抽出するコードを書く方が現実的なのですが、EL 3.0 は本来 Collection を対象とする事をわかりやすくするため、JPA を使わずに自分でダミーのデータをcreateDummyData()で作成しています。

package jp.co.oracle.ee7samples.model;

import java.util.ArrayList;

public class Person {
    private String name;
    private Integer age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public static ArrayList createDummyData() {
        ArrayList<Person> data = new ArrayList<>();
        Person person;
        for (int i = 0; i < 100; i++) {
            person = new Person();
            person.setAge(Integer.valueOf(i));
            if (i % 2 == 1) {
                person.setName("山田 太郎" + i);
                person.setSex("男性");
            } else {
                person.setName("山田 花子" + i);
                person.setSex("女性");
            }
            data.add(person);
        }
        return data;
    }
}

2013年5月11日 at 3:01 午後

Java Puzzlers って何?!サンプル問題の解答

先日、Java Puzzlers のサンプル問題を下記エントリでご紹介しました。

Java Puzzlers って何?!サンプル問題

この問題の解説を行います。
結論から言うと、正解は(3)です。皆様正解できましたか?

一見すると
1行目:12345678 + 87654321 = 99999999
2行目:01_234_567 + 76_543_210 = 77777777

となりそうなので、答え(2)を選んでしまう方もいらっしゃるかもしれません。

もしくは12_345_678のように、 _ (アンダースコア)が付いたリテラルに対して加算しているのでコンパイルエラーになると考え(5)を選ばれる方もいらっしゃるかもしれません。数値の間に _ (アンダースコア)が入る事は Java SE 7(Project Coinで) からできるようになりました。このアンダースコアは、数字データの可読性の向上のために自由に使っていただく事ができます。つまり(5)でもありません。

次に、回答(1)を選んだ方は、2行目の部分は気づいた方ではないでしょうか。2行目の先頭に 0 がついていますが、Java では 8進数表記になります。8進表記で 1234567 は 10 進表記では 342391 になります。つまり、10 進数で計算しなおすと下記のようになります。

342391+76543210=76885601

ここまで分かった場合、残った答えは (1) か (3) にしぼられるのですが、このプログラム実はもう一つ落とし穴があります。

1行目の、87_654_32l と記載されている所ですが、実は最後の文字は1(イチ) ではなく l (long:小文字のエル) なのです。

つまり、12345678 + 8765432 = 21111110 となり答えは (3) となります。Primitive の long 型を扱う場合には、混乱を招かないように l(小文字のエル)ではなく、L(大文字のエル)を使いましょうね!!

と、このようなやりとりをパズラーの登壇者がおもしろおかしく、そして分かりやすく紹介します。

パズラーが出す質問に、皆様何問回答できますか? (^_^)
是非、チャレンジしてみてください。

2013年5月9日 at 1:12 午前

Java Puzzlers って何?!サンプル問題

Java Day Tokyo 2013 の中で「帰ってきた Java パズラー」というセッションを 16:45 – 17:35 の時間帯で実施します。

皆様、Java パズラーをご存知でしょうか?
もしかしたら、特に若い方々はこのセッションの内容についてご存じないかと思い少し、本ブログですこしご紹介します。このセッションは過去、本場 JavaOne でとても人気のあったセッションで、このセッションは常に満員になるほどの名物セッションでした。その後、「Java Puzzlers 罠、落とし穴、コーナーケース」という書籍もでてベストセラーにもなりました。

このセッションでは、どんな事をするかというと、簡単にいうならば、参加型のクイズ形式のセッションになります。単なるクイズ・セッションではなくおもしろい要素もあります。

セッションでは、登壇者が皆様に質問を出します。

「下記の Java のプログラムを実行すると何が表示されるでしょうか?」

public class Test {
    public static void main(String[] argv) {
        System.out.println(12_345_678 + 87_654_32l);
        System.out.println(01_234_567 + 76_543_210);
    }
}

* 下記の 5 択の中から正解を選んでください。
(1) 99999999 76885601
(2) 99999999 77777777
(3) 21111110 76885601
(4) 21111110 77777777
(5) コンパイルエラー

※ 本、ブログをご覧頂いた皆様、コンパイルして実行せずに、コードのレビューだけで、正解を導きだしてみてください!!正解は、明日追記します。

実際、当日は実際に考える時間はあまりありません。短い時間の中でコードレビューをして、正しいと思う番号に手をあげて皆様は参加します。うっかりしていると間違えてしまう点や、見落としがちな点をご紹介します。このセッションは、JJUG(日本 Java ユーザ・グループ) の協力を得て、日本オリジナルで Java SE 7, Java SE 8 に対応した問題をみなさまに提出いたします。Java の初心者から玄人の皆様すべてが楽しんでいただけるこの参加型セッション、ぜひみなさまご参加ください。

2013年5月8日 at 6:19 午後 1件のコメント


Java Champion & Evangelist

Translate

ご注意

このエントリは個人の見解であり、所属する会社の公式見解ではありません

カレンダー

2013年5月
 12345
6789101112
13141516171819
20212223242526
2728293031  

カテゴリー

clustermap

ブログ統計情報

  • 1,288,526 hits

Feeds

アーカイブ