せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

JJUG ナイトセミナー「WildFly 8 ローンチ記念」行ってきました

久しぶりのJavaEEということで行ってきました。
やっぱりEEはいいですねー。

リンク

DoorKeeper

【東京】JJUG ナイトセミナー 「WildFly 8 ローンチ記念」Red Hat共同開催 - 日本Javaユーザーグループ | Doorkeeper

発表資料はこちら。

What’s new in WildFly 8 ?

wildfly-deck/deck/slides.html at master · arun-gupta/wildfly-deck · GitHub

Undertow

次世代Webコンテナ Undertowについて

WildFlyについて

What’s new in WildFly 8 ?はJavaEEの有名人、Arun Guptaさんが世界中でやったセッション。
日本でもやる予定だったけど、「日本人がやればいいんじゃね?」ということで今回のセッションが開催されることになったようです。

WildFlyって何?

Java EE 7準拠のアプリケーションサーバです。

昔はJBossASという名前だったけど、JBossから始まるプロダクトが非常に多く、ぐぐらビリティが悪いから名前を変えたそうです。
なお、RedHatが出してる有償サポート版であるJBossEAPは、専門の検索サイトが有るらしいので問題はないそうです。
WildFlyEAPにはならないっぽい。

特徴は早いこと。
デモだと1.5秒で起動しています。
載せてるアプリにもよるけど、TomcatとゴテゴテSpringより起動は早そうです。

また、非常に開発者フレンドリーらしいです。

どこが変わったの?

  • サーブレットの部分をTomcatベースのものから高速なWebサーバーのUndertowに変更
  • WebSocketを使用することで、使用するポートを5から2に減らした
  • ロールを使用したアクセス管理・・・
  • 自動パッチ機能
    Zipファイルをダウンロードしてアップデートすることが出来ます。
    更に元のバージョンに戻すことも可能。

他にもこんな機能が

  • JDK8に対応
    ただし、まだ対応版はJavaEEのコンパチビリティテストを通っていない
    コンパチビリティテストの方がJava8に対応するのを待つらしい
  • RESTEasy3はJerseyよりも優秀らしい
  • Hibernate searchで全文検索出来るようになった
    使いどころとしては、不動産の検索とか。デフォルトで入っているのがスモイ。
  • デプロイメントごとにセキュリティの設定が変えられる
    クラウド環境で使うことを想定しているらしい。
  • 元からクラスタリングテクノロジーが強い
  • EJB2.1のEntityBean、JAX-RPC、JSR88をバッサリとカット
  • クラウド対応
    OpenShiftやCloudBeeなど。
  • 有償サポートであるEAPのJavaEE7対応版はWildFly9がベースになる。
    WildFlyは来年の頭に出る予定なので、EAPは来年の中頃くらい。
    楽しみに待ちましょう。
    (そのころはJavaEE8の話題で持ちきりな予感もする・・・)

Undertowのお話

Undertowとは?

  • Webサーブレットコンテナ。2012/7に初コミットの若いコンテナ。
  • パフォーマンスが凄くいい。
  • XNIOというライブラリを使用。
  • とにかく軽い。ヒープに展開しても10MBくらい。
  • JBoss7まではTomcatの強化版。
    強化版はパフォーマンス向上、クラスタリングの独自実装。
    Struts祭りで被害なし。
  • そんな強化猫から乗り換えた理由は、Webの発展についていくのが難しくなったから。

特徴

  • ワーカー、リスナー、ハンドラーから構成。
  • Requestを受け付けるとハンドラを呼ぶ。
    ハンドラを小さい処理を記述し、それをチェーンしていく方式。
    サーブレットフィルターみたいなイメージかも
  • Wildflyで動くときはハンドラーを自動で登録してくれる。

その他

  • 設定周りがわかりやすかも。XML地獄じゃない。
  • 開発者がフレンドリーで、機能をリクエストすると取り込んでもらえるかも
    アクセスログはそれで追加されたらしいです。

まとめ

GlassFishと比べて勢いがある印象。
やっぱり有償サポートが控えてるっていうのが強みな気がする。

Undertowは単体で使うのはちょっと難しそうですけど、WildFlyに組み込まれている分には問題なさそう。
Tomcat以外の選択肢が増えるのはとてもいいことだと思います。

JSFさんの空気っぷり・・・。

JavaDayTokyo2014に行ってきた

去る5月22日に行われたJavaDayTokyoに行ってきました。
去年の秋葉原に引き続き、2年連続の参加です。
参加して思ったことを書き連ねてみます。

日本Oracleの本気度アップ

f:id:setys:20140522092153j:plain

秋葉原UDXから品川プリンスに変更になり、会場に余裕が出来ました。
去年はすし詰め状態だった基調講演もゆったり聞くことが出来ました。
椅子も柔らかく座り心地もよいものが用意され、腰痛持ちの自分でも安心して参加出来ました。

さらに待望のJavaSE8日本語ドキュメントのリリースも発表。
SE7の日本語ドキュメントが去年のJavaDayTokyoだった気がするので、それに比べれば非常に早いリリースだと思います。
これがきっかけで、日本でもJava8が一気に浸透していくのではないでしょうか。(願望)

IoT重点の基調講演

基調講演の50%以上はIoT関連のものでした。
驚いたことに、本家JavaOneの基調講演で登場したDukePadやチェスロボットが登場したこと。
Oracleが日本の市場を重視していることが伺えます。
わざわざアメリカに行かなくても日本でOK、ではなくいつかは本家でお披露目の瞬間でみたいです。

f:id:setys:20140522112443j:plain

f:id:setys:20140522115338j:plain

マインドストームDukeも登場し、会場はとても盛り上がっていました。
日本からもNECのパペロが参戦し、流暢なお喋りを披露してくれました。

MindstormやRaspberry Piのような小さなデバイスでほぼJavaSEのコードが動くことは、開発者が今まで持っているスキルでできることを広げてくれる夢のある話です。
だってこちらが何もしなくても出来ることが広がっていくんんですよ?
Lambdaをマスターしているうちに、ロボットも動かせるようになるなんてすごい時代になったものだと思います。

端末の性能も向上していけば、できることはさらに増えていくのではないでしょうか。

その反面EEは・・・

『C-1 Java SE 8時代のJava EE 7アプリケーション開発』では、MindstormとJava EE7を組み合わせたデモが披露されました。
ブラウザとGlassfishはWebSocketで接続、GlassfishとMindstormの間もWebsocketで接続し、JavaSEとJavaEEだけでもブラウザからリモートコントロールするアプリを作れることを示してくれました。
今後、エンタープライズなWebアプリしか作ったことがない人でも、IoTを使いこなせる様になるというのは開発者にとって嬉しい事です。

ここまで出来るようになっているにも関わらず、JavaEE7準拠のアプリケーションサーバーが遅れていることが非常にもったいない。
Glassfishは有償サポートがなくなった上、4.0.1が今年のJavaOneにようやくリリース(できればいいなぁ)という状況。
WebLogicは今年中は厳しい。
WASが辛うじて今年間に合いそう?
日本のベンダーはどうなってる?
こんな状況だと、せっかくのいいものが個人で楽しんだり教育での使用にとどまってしまいます。
Javaユーザーが多いエンタープライズな方面でも使えるようになってほしいです。

IoTの端末部分がいろいろ進化しても、肝心のクラウドで使うものが遅れてちゃあ・・・。 Oracleさんもそこんとこわかっているとは思いますので、今年のJavaOneでの巻き返しに期待です。

とにかくLambdaだ!

あとはJavaSE8と言うよりLambda祭り。
Lambdaは難しそうに見えても文法の仕組みを知ってしまえば書くのは簡単。
でも奥が深くて使いこなすのは難しい。
そして、使いこなせれば強力な武器になる魅力的な機能です。

Lambdaについては使いこんで慣れることが肝心だと思います。
Lambda100%セッションとしてはA-4を聞きましたが、イキナリ聞いただけではほとんど理解できないんじゃないかなと思います。
A-2の続きだったようですが、Lambda知識0でA-2→A-4と聞いてついてこれた人はなかなか少ないのではないかと。
初めてのLambdaとか入門Lambdaというイベントは、今年一杯で終わりそうな気もするので、なるべく早いうちにJava8に慣れておくことが重要です。

あとは、日本語APIリファレンスが出たので、StreamAPIはちゃんと読んでおこうと思います。 注釈に重要な情報が大量に書いてありました。
特にparallel使って見るときは読む必要があります。

その他もろもろ

コミュニティ寄りの人もスーツな人もどちらも楽しめるバランスになっている良いイベントだったと思います。
IoT関連の展示も面白く、Raspberry Pi、Mindstormのいずれも完売する人気っぷり。
Mindstormは欲しかったけど、10万ドル、ぽんっと出してくれるほどお財布さんが優しくなかったので泣く泣く諦めました。
ゴールデンウィークの月に行うのが悪いと思います。

それでも重箱の隅をつつくように注文をつけるのであれば、遠路はるばるお越しいただいた人向けに荷物の預かり所(もしくはその案内)があったほうがいいとは思います。
荷物が多いとかさばりますし、セッション聞くのも大変です。
あの人混みでキャリーバックを引いてる人がいて、案の定轢かれました。。。

forループ殺すべし。慈悲はない。

うん。言ってみたかっただけなんだ。

JJUG CCC 2014春に行ってきました。
基調講演の『foreach書いたら負け!for禁止!』という言葉のインパクトが強すぎです。
その後のセッションのデモでforが出てくるとツッコミが入っていたくらいです。

とりあえず、マケグミ・サラリマンにならないようにforを潰す練習をしてみました。

一時変数を使ったループの置き換え

一時変数を使ったループはこんな感じで置き換えればよさそうです。

for (int i = 0; i < 100; i++) {
    // 何か処理をする!
}

これをLambdaにしてみるとこんな感じ。

IntStream.range(0, 100).forEach(i -> ここに処理を書く!);

1行で書けるのが素晴らし。

条件に適合したらループを抜けるケース

いきなり自信なくなります。
動いているのは確認してますけど、もっと良いやり方があるとかもしれないので・・・。

例としてはListを先頭から検索していき、条件に該当するものが見つかったらループを抜けるケースです。

for (int i = 0; i < 100; i++) {
     if (condition) {
        // 何か処理をする!
        break;
     }
}

forの方はだんだんウザくなってきました。
これをLambdaで書いてみると、こんな感じになります。

IntStream.range(1, 100).filter(i -> condition).findFirst().ifPresent(i -> 処理を書こう);

filterメソッドで条件を指定し、findFirstメソッドで条件に一致する最初の値に対して処理をおこないます。
条件に該当する数値がない場合は、処理が呼び出されません。
例外じゃないです。

Lambdaにすると読みやすくなったといえます。
それに加え、先頭から要素を探す残念処理を簡単にパラレルで実行できたりもシマス。

IntStream.range(1, 100000).parallel().filter(i -> condition).以下略

途中にparallelメソッドを挟むことで処理が並列で行われるので、条件に一致するものを見つけるまでの時間が早くなります。

決められた件数だけを処理するパターン

リストの最後に到達するか一定の件数を超えたら処理を終了するパターンです。
for文で書くとこんな感じ。

int count = 0;
for (int i = 0; i < 100; i++) {
     if (condition) {
        // 何か処理をする!
        count++;
        if (count == 10) {
            // 10件処理したら終わる
            break;
        }
     }
}

うんざりするようなソースですが、Lambdaならこんなに簡単に書けます。

IntStream.range(1, 100).filter(i -> condition).limit(10).forEach(処理をする!);

limitは上限を設定するメソッドで、条件に該当する要素に対して10件処理をしたら終了になります。
forでやっている時のような一時変数でカウントする必要がないのでスッキリします。
こちらも処理がスレッドセーフなら、parallelにして処理時間を短縮することが出来ると思います。

今日やったことまとめ

一時変数forループもLambdaにすると可読性も上がっていい感じ。
IntStreamには今回使ったfindFirstやlimitだけじゃなく、distinctとかmaxといったフィルタリングするのに便利なメソッドが多いので複雑なループでも大丈夫。

Lambdaこわいにならないように準備しておくのが肝心だと思います。
あとは、Java8を仕事で使う政治的根回しをすることも重要です・・・。
なんで、来月から始まるJava開発がJava6なんですかね、某大手ベンダー=サン・・・

関数型インターフェースで気になったことを試してみた

関数型インターフェースとは?

ざっくり言うと、メソッドが1つだけ定義されたインターフェース。

関数型にならないケース

メソッド1つだけと言っても、defaultやstaticは対象外。
なので、defaultメソッドだけ持ったインターフェースは関数インターフェースと呼べない。

@FunctionalInterface
public interface A {
    default public int onlyMethod(int value) {
        return origin * 2;
    };
}

エラーメッセージはこんな感じ。

予期しない@FunctionalInterface注釈
Aは機能インタフェースではありません
  インタフェース Aで抽象メソッドが見つかりません

てか、関数型インターフェースって名前じゃないのか!
機械翻訳な気もするけど、Oracle公式は機能インターフェースなんですかねぇ。

関数型インターフェースと継承

関数型インターフェースを継承しても、メソッドが1つだけなら関数型インターフェースを名乗れる。
使いドコロは・・・ないと思うけど。

@FunctionalInterface
public interface A {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface B extends A{
      // コンパイルエラーにならない。
}

当然ですけど、default修飾子付きのメソッドでオーバーライドするとコンパイルエラーです。
エラーメッセージは最初と同じで抽象メソッドが見つからないという内容です。

@FunctionalInterface
public interface C extends A{
    @Override
    default int onlyMethod(int value) {
        return 0;
    };
}

なお、@FunctionalInterfaceを外せばコンパイルは通ります。
それによって、インターフェースの抽象メソッドをインターフェースが実装するという謎なインターフェースが出来上がります。

継承(逆の場合)

関数型ではないインターフェースを継承して無理やり関数型にしてしまう。

public interface A {
   default int onlyMethod(int value) {
       return 0;
   };
}

@FunctionalInterface
public interface B extends A{
    int onlyMethod(int value);
}

デフォルトの実装を全く無視する荒業。
使い道あるかは知らぬ・・・。

多重継承

複数のインターフェースを継承した場合のパターンも試してみました。
まずはコンパイルエラーにならないパターン。

@FunctionalInterface
public interface A1 {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface A2 {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface B extends A1, A2 {
      // コンパイルエラーにならない。
}

当然、継承するインターフェースのメソッドの定義が違えばコンパイルエラーになります。

@FunctionalInterface
public interface A1 {
    int mainMethod(int value);
}

@FunctionalInterface
public interface A2 {
    int subMethod(int value);
}

@FunctionalInterface
public interface B extends A1, A2 {
      // これはコンパイルエラー。
}

ちなみにエラーメッセージはこんな感じ。

予期しない@FunctionalInterface注釈
Bは機能インタフェースではありません
インタフェース Bで複数のオーバーライドしない抽象メソッドが見つかりました

この場合、どちらかのメソッドを実装すればBを関数型インターフェースにすることができます。

@FunctionalInterface
public interface B extends A1 , A2 {
    @Override
    default int subMethod(int value) {
        return 1;
    };
}

やっぱり使いドコロが無さそうですが、あえて使うならこんな感じだと思います。

@FunctionalInterface
public interface C extends A , B{
    @Override
    default int subMethod(int value) {
        // デフォルトと言いつつ実装を強要してみる
        throw new UnsupportedOperationException();
    };
}

ここまでして関数型インターフェースを作りたい男の人って・・・。

まとめ

Lambdaに付随して言語仕様がガッツリ変わっているおかげで、インターフェース周りで色々出来て面白いです。
ただ、きちんと規約決めておかないとインターフェースに実装メソッドが大量発生したりstaticメソッドだらけになってカオスなものが出来上がる予感もします。。。

Java8時代の文字列結合のまとめが気になったので試してみた

元ネタはこちら

Java8時代の文字列連結まとめ - きしだのはてな

だいぶ今更感がありますけど、気になったことが合ったので試してみました。

  • 気になったこと1
    データ量が多くなったら急に性能が落ちるケースってあるのか?

  • 気になったこと2
    一応SIer所属なので、「漢は黙ってStringBuffer」も比較対象に加えたい。

というわけで、きしださんの作ったソースのコピペ をベースに、StringBufferで結合する素敵メソッドを追加。
それに対して文字列リストの要素数を1倍、10倍、100倍のケースで測ってみました。

まずはオリジナルの要素数で。

stringJoin:1812ms
stringBuilderJoinMem:958ms
stringArrayJoining:686ms
charBufferJoin:773ms
stringBufferJoin:1240ms

これはきしださんの結果と大体一致しています。
String#joinを使われるよりは、StringBufferの方がマシというところでしょうか。

次に文字列の要素数を10倍にして実行。
予想ではだいたい10倍位の時間になるはずですが。。。

stringJoin:18484ms
stringBuilderJoinMem:10775ms
stringArrayJoining:8595ms
charBufferJoin:13221ms
stringBufferJoin:12630ms

アイエエエ!?CharBufferナンデ!?
素数が10倍になったら処理時間が20倍くらいになってます。
まさかのStringBufferよりも遅いという結末。

思い当たるフシとして、allocateのサイズが割りと適当なこと。
そこで、allocateの引数を90000(適当な数値)結合した文字列の長さに合わせた79995バイトに変更してみました。

CharBuffer buffer = CharBuffer.allocate(79995);

再測定した結果はこんな感じです。

stringJoin:18971ms
stringBuilderJoinMem:10594ms
stringArrayJoining:8212ms
charBufferJoin:12023ms
stringBufferJoin:12849ms

StringBufferより辛うじて早いけれど・・・という感じです。
ちなみにその後に行った100倍の結果はこちら。

stringJoin:197357ms
stringBuilderJoinMem:111888ms
stringArrayJoining:89730ms
charBufferJoin:129791ms
stringBufferJoin:132432ms

こちらは比較的予想通りの結果です。
CharBufferも前回のリミット見直しのおかげでStringBufferより早いです。

まとめ

試してみたなりのまとめです。

  • カツカツな性能が求められていない限り、StringBuilderが安定。
  • CharBufferのリミットはしっかり設定しよう。
    本来は文字列結合だけの目的で使うクラスじゃないのでしょうが・・・。
  • あれ、Java8の要素があまりないよ?

ま、まぁ、+演算子で結合というような事をしない限りは、文字列結合の速度で問題にはならない気がします。

補足

ByteBufferは使うけど、CharBuffer使ったの初めてかも・・・。

UpdateもDeleteを使わないテーブル設計

今日読んでた本で出てきたのでメモメモ。
Insertで履歴を持つまではわかるけど、削除テーブルというのがイマイチピンと来ない。
毎回Joinしちゃうの?
ググってもあまり情報が出てこない。

で、ようやく見つけたのがこれ。

PostgreSQLでINSERTのみ使用してレコードの更新履歴を残すテーブル構造を実装する - mikage014の日記

  • 通常のテーブルはINSERTのみ
  • UPDATEしたい時は通常テーブルにレコードを追加し、削除テーブルにもINSERTする。
    削除テーブルにINSERTするのは更新前のレコード
  • 削除は削除テーブルにINSERT
  • Viewは通常テーブルに対して削除テーブルを消しこんだもの。

こうすれば確かにINSERTだけで回りそう。
JPA使うときとかこういう設計のほうがいいかも。

Apache Camel+Groovyで簡単システム統合ハンズオンに行ってきた

JGGUGのハンズオンセミナーで出てきたサイトのメモ。

簡単にメモ

  • Camelとは?
     ・汎用的なシステム統合フレームワーク
     ・エンタープライズインテグレーションパターン(EIP)を実現
     ・軽量&DSL

  • 結合可能なComponentは200以上!
    TwitterからHBaseまで有名どころは大体揃ってる感じ。

  • ApacheCamelは敷居が高いので下げることがハンズオンの目標

  • EIP本がベースになっている。
    システム統合の基本は非同期でメッセージングベース。

ちなみに本はこちら。700ページオーバーらしい。

Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions: Gregor Hohpe, Bobby Woolf: 0785342200683: Amazon.com: Books

  • CamelはJarで提供。最近のライブラリにしては不親切かも。

  • 基本的にメッセージング。Camelが落ちたらデータは揮発しちゃう。
    データのライフサイクルは以下の2つがある。

  • SEDA→Staging Event Driven Architecture
    Camelコンテキスト内で有効

  • VMVM内で有効

資料とかリンクとか

モジュール

ハンズオンで作成したモジュール。

nobusue/camel-groovy · GitHub

スライドシェア

Gws 20140418 camel_groovy

ApacheCamel本家

Apache Camel: Index

感想

軽く触ってだけでも凄くイケてるし可能性の秘めてるライブラリだと思う。
下手にGUIやツール化していないので、ケースに合わせて柔軟に対応できる。
Groovyを利用することで、個々のComponentを綺麗につなぐことが可能になる。

惜しむらくは日本語の情報の少なさか・・・。