JavaOne 2015 1日目メモ (10/25)

昨年よりも約1ヶ月遅いJavaOneが始まった。初日はコミュニティ主体のセッションであるユーザグループフォーラムと、キーノートがサンフランシスコのモスコーンセンタにて行われた。以下、参加メモ。

[UGF11082] WebSocket Perspectives

スピーカーはニューヨークにあるJavaユーザグループNYJavaSIGのリーダFrank Grecoさん。WebSocketはあくまでトランスポートレイヤの仕組みで、WebにTCPを持ち込んだが、そもそもなんでWebにTCPが必要になったかの話。

その背景には、ここ10年で以下のような変化があったこと。

  • WebはページからAPIサービスの塊になり、目に見えないものになった
    • いまやカウント対象はページビューではなく、APIの呼び出し回数
  • RESTで実装されるようになったが、リクエスト/レスポンスモデルは待ちが多い
    • 非同期処理で待ちを軽減させていた。ReactiveXが解決策。
  • マイクロサービスの普及。Webアプリケーションが1つの小さいプロセスの連携であるThe Unix Wayの考え方に近づいている。
    • マイクロサービスのペナルティもリクエスト応答の待ち時間。

WebSocketはあくまでトランスポートレイヤであるため、例えばAMQPをWebSocket上でやり取りすることもできる。リクエスト/レスポンスモデルが主体のWebの世界に、public/subscribeモデルが持って来れる。

実際にWebSocket/AMQPを使ったいくつかのチャット、ゲームのデモアプリケーションを紹介。デモはKAAZING.orgに公開されている。公開されていないデモの紹介として、ドローンのWeb画面によるモニタリングアプリを紹介。高度、進行方向、プロペラ回転数などの状態は常に変化するため、WebSocketだからこそ実現できる。

ここからは感想。今までWebSocketの双方向通信の使い道はゲームぐらいしか思い当たらなかったが、ドローンが監視できることは、企業のシステムでも機械の監視がWebで出来るを思った。例えば、過加熱、消費電力、通信量など、常に変化して、今までは定点間のデータは捨てていた場合、WebSocketが使えるのでは。

[UGF11073] Who Wants to Be a Millionaire? Dealing with Money and Currency in Java Applications

JSR 354 - Currency and Moneyについて。お金を扱うAPIの標準化について。
たびたびJavaOneでも見かけたが、2015/5に仕様策定が完了したとのこと。Java SEをターゲットとした仕様だが、JDK9 or JDK10のいつ盛り込まれるかは未定。

内容はすべてライブコーディングによるAPIのデモ。

mavenのセントラルリポジトリにも既に登録されており、以下の依存性を追加すると実際に参照実装が試せるようになっている。

<dependency>
    <groupId>org.javamoney</groupId>
    <artifactId>moneta</artifactId>
    <version>1.0</version>
</dependency>

お金がintやBigDecimalのような数値でなく、MonetaryAmountとして抽象化されている。MonetaryAmountはイミュータブル。MonetaryAmount.addなどすると、別のオブジェクトが返ってくる。

// 100円
CurrencyUnit yen = Monetary.getCurrency("JPY");
MonetaryAmount yen100  = Money.of(100, yen);

CurrencyUnit yen = Monetary.getCurrency("JPY");
MonetaryAmount yen50  = Money.of(50, yen);
System.out.println(yen100.add(yen50));      //=> JPY 150

// 10.25ドル
CurrencyUnit dollar = Monetary.getCurrency("USD");
MonetaryAmount money  = Money.of(10.25, dollar);

Stream APIを使って通貨ごとのサマリデータを取得することが可能。

CurrencyUnit yen = Monetary.getCurrency("JPY");
MonetaryAmount money  = Money.of(100, yen);
MonetaryAmount money2 = Money.of(200, yen);
MonetaryAmount doller1 = Money.of(10.12, Monetary.getCurrency("USD"));
MonetaryAmount doller2 = Money.of(20.12, Monetary.getCurrency("USD"));
MonetaryAmount euro = Money.of(1, Monetary.getCurrency("EUR"));

List<MonetaryAmount> moneys1 = Arrays.asList(money, money2, doller1, doller2, euro);

// 日本円のサマリデータを取得
Map<CurrencyUnit, MonetarySummaryStatistics> summary  = 
    moneys1.stream().collect(MonetaryFunctions.groupBySummarizingMonetary()).get();

MonetarySummaryStatistics yenSummary = summary.get(yen);
System.out.println(yenSummary.getAverage()); // JPY 150
System.out.println(yenSummary.getSum()); // JPY 300 
System.out.println(yenSummary.getMax()); // JPY 200
System.out.println(yenSummary.getMin()); // JPY 100

為替情報も取得でき、異なる通貨値の変換ができる。wifiを落とすと例外がスローされたので、RIでは最新レート情報をWeb上に取得に行っているようだ。

// 為替レートの取得
ExchangeRateProvider exchangeRateProvider = MonetaryConversions.getExchangeRateProvider("IMF");
ExchangeRate rate = exchangeRateProvider.getExchangeRate("USD", "JPY");
 System.out.println(rate.getFactor());  // => 120.93957... (2015/10/25のドル->円レート)

// 1ドルを日本円に変換
CurrencyConversion dollarConversion = MonetaryConversions.getConversion("JPY");
MonetaryAmount oneDollar = Money.of(1, "USD");
System.out.println(oneDollar.with(dollarConversion));  // => JPY 120.9395779...

いくつかのサンプルコードがgithubjavamoney-examplesで公開されている。
複数の通貨を扱うアプリケーションでは、いままでBigDecimalBigDecimalの数値が表す通貨単位情報を1つのクラスにラップしていたと思うので、このAPIを使うとシンプルにコードが扱えるのでは。日本円だけを計算する場合の有効性はもう少し調べてみる必要がある。

Java Keynote

いろいろな所で紹介されると思うので詳細は省略。
jigsawが何を解決させるかについて、以下の3点を掲げていたのは去年のJavaOneでは説明されていなかったと思う。

  • Is anything missing?
    • NoClassDefFoundErrorが出ても、クラスパスに含まれる大量のjarから、どのjarが漏れてるかわからない
  • Are the any conflicts?
    • maven使っても、commons-binutil-1.7.0と1.8.0の両方が依存性に含まれることがある。別バージョンの競合
  • Is it safe to change internal API?
    • アプリ内の他パッケージに見せるためにpublicにしたのに、意図しないアプリ外から参照される。内部APIでも容易に変更できない。

classpathは依存関係が定義できないのが弱点。moduleは新しいグループの単位で、module->package->class->filed,method の順に位置付けされる。依存性の定義は、module-info.javaに定義される。

module com.greetings {
    // このモジュールが依存するモジュール
    requires test.common;
    // 他のモジュールからも参照されても良いパッケージ
    exports com.greetings.api;
}

jigsawの具体的な使い方は明日以降のセッションで説明があるとのこと。