Hatena::ブログ(Diary)

開発日記

2016-05-07

Direct Field Access とメソッドレベルのバリデーション

(備忘録)

Spring Boot 1.3 の @Restcontroller で、GET 時のバリデーション

DataBinder で、initDirectFieldAccess() を設定


ハンドラー

@RequestMapping(method = RequestMethod.GET)
public Response search( @ModelAttribute @Validated Criteria criteria) {
        List<Item> items= planService.search();
        return new Response(items);
 }

検索条件のバリデーション

public class Criteria {

    @AssertTrue
    private boolean isValid() {
        return false;
    }
}

メソッドの型が、 プリミティブ boolean だと動作するが、ラッパークラスの Boolean だと動作しない。

バグ

2014-04-19

AWS Amazon Linux インスタンスの Open JDK 1.6.0_30 でメモリーリーク

Amazon EC2Amazon Linux インスタンスで、 Mule ESB 3.4.0 を動かしていたら、でくわしたメモリリーク

原因は、OpenJDK 1.6.0_30。

ソケットの finalizer まわりにバグがあるみたい。

http://stackoverflow.com/questions/21717814/memory-leak-with-sockssocketimpl-finalize-method

1.7.0_55 に変えたら、あっさり解消した。

障害の発生

Mule ESB が突然、再起動

JVM の応答を監視しているラッパーが 30秒タイムアウトを検知して、強制的に Mule ESB を再起動した。

GCログ

手がかりが少なく、困っていた。

知人から、メモリリークの疑いと、GCログの取得するようにアドバイスがあった。

Mule ESB では、conf ファイルに以下を設定。

#

wrapper.java.additional.4=-verbose:gc

wrapper.java.additional.5=-XX:+PrintGCTimeStamps

wrapper.java.additional.6=-XX:+PrintGCDetails

※番号に注意。連番であること。

これで、メモリーリークが起きていること、3日間くらい稼働すると、Full GC が始まり、かつ、Tenured (old) 領域が、上限に張り付いたまま、メモリが解放されない現象を確認。

再現できなかった

しかし、テスト環境ではどうやっても再現しない。

できるだけ本番環境に近づけようと、いろいろテスト環境をいじってみた。

ここに相当時間を取られた。

再現した

データベースを、テスト環境では、Mule ESB と同じサーバーインストールしていた。

これを本番環境と同じ RDS ( PostgreSQL 9.3.3 ) に変更した。

みごとに再現した。

アプリケーションオブジェクトの生成や後始末をいろいろやってみる

問題が起きる時間に走るアプリケーションオブジェクトの生成や後始末をいろいろ変えてみたがメモリリークは解消しない。

Amazon EC2 の Amazon Linux インスタンスでは、デフォルトJDK が、 1.6.0_30 で、そのままだったことに、ここで気が付く。

JDKバージョンアップ

yum と alternatives コマンドは、ほんと楽ちん。

yum で 1.7 をインストールし、alternatives で、1.6 と 1.7 を切り替えながら、再現テスト。

見事に、 1.6 ではメモリリーク。1.7 では、リークなし。

一件、落着。

PostgreSQL のローカル接続がひとつの落とし穴だった

ローカルに接続する場合は、Unixドメインソケット(ローカルなプロセス間通信)、別サーバー上のDBに接続する場合は、TCP/IPソケット(ネットワークソケット)。

OpenJDK 1.6.0_30 で発生したメモリーリークは、この、TCP/IPソケットのファイナライズに問題があるらしい。

教訓

テスト環境でも、RDS にするなど、もっと本番環境に近づけておくべきだった

メモリの状態をもっと確認すべきだった( 本番環境とテスト環境で、top コマンド使うだけで、簡単に違いを発見できた)

2011-11-09

Clojure = ( + Lisp JVM )

「7つの言語 7つの世界」の6つ目の言語、 Clojure にチャレンジ。

Java 版の Lisp 言語です。

すべてはシーケンス ( list ) です。

以上。

Lisp 言語は、広く受け入れられた言語ではないが、いろいろなプログラミングパラダイムを知るための必修科目の一つ。他のプログラミング言語では、わからない世界がそこにある。

私自身は、大昔に、Lispアプリケーションを書いていたことがあるので、Clojure はなつかしかったし、また、Lisp 系言語が、ここまで発展しているのに、正直びっくりした。

Lisp 系言語の経験がない技術者には、いちど、 Lisp 系の世界を、Clojure で経験して、ぜひ、この独特のパラダイムを知ってほしいと思う。

実務で使うことはないかもしれないけど、見方や発想が広がり、設計能力のアップに、絶対、役に立つと思うんだけどなあ。

Clojure は、 Java資産が全部使えちゃうし、並行処理も、非常に面白い( Lisp 系らしい ) 取組をしている。ただ、これは、 Lisp 系言語の中での比較には意味があるけど、別のパラダイムの言語との比較では、やはり、「シーケンス」の感じをぜひ体験しておきたいところ。

万物はリスト ( シーケンス )である

文字列、リスト、マップ、ファイルシステム、並列処理、....

全部、「シーケンス」モデルで同じに扱う。

文字列は、String, コレクションフレームワークに、 配列に、 Arrays クラスと、ごった煮の Java 世界ではなく、「万物はシーケンスである」という Clojure の世界観は、ぜひいちどご賞味ください。

万物は、 first と rest である

これは、上記の「万物はシーケンスである」の別の言い方。

リストは、たくさんの要素の集合ではなく、「最初の要素」+「残りの要素」の2つ組み合わせという発想。

もちろん「残りの要素」が、またシーケンスつまり「最初」と「残り」という入れ子の構造になっている。

この感覚が、Clojure (というか、Lisp 系全般)の、もっとも「らしい」ところ。

関数(命令)もデータである

別の言い方をすると、Clojure の世界は「データだけ」です。

データのシーケンスを作って、実行する。これの繰り返し。

Lisp 系のわかりにくさ(なじみにくさ)の理由のひとつの独特(?)の「記法

( * 2 3 )

が、他の多くの言語では、 ( 2 * 3 ) になる。

この違いを会得できれば、Clojure の世界が、ちゃんと理解できたことになる。

なぜ、こういう記法をしているかが、

Clojrueの

  • 万物はシーケンスである
  • 万物は first と rest である(その入子である)
  • 万物は データの並びである(プログラムもデータの並びである)

の世界観を会得するということ。

この世界を一度体験すると、データの塊やプログラムコードの塊の扱い方のセンスが変わること請け合いです。

ぜひ、一度、Clojure お試しあれ。

2011-10-26

Erlang で世界の見え方がかわっちゃった

「7つの言語 7つの世界」を参考に、Erlang を体験。

いやー、ほんと、別世界。

最初の印象:

・ルールとパターンマッチングは、ご先祖様の、Prolog ゆずりだなあ。

・メッセージ・パッシングは、Smalltalk というか、オブジェクト指向の原点の雰囲気。

・ループ構造が末尾再帰っぽいのは、関数型言語

まあ、こんなもんかな、という感じ。

ところが、

プロセス間通信

プロセスの監視、自動再起動

を試したら、これがびっくり。

Erlangプロセスは、Unixプロセススレッドとも、 Javaスレッドとも違うタイプの独自の「軽量プロセス」らしい)

プロセスをぼんぼん起動して、プロセス間で、ばんばんメッセージパッシングが、いとも簡単にできちゃうのがすごい。

もっと驚いたのは、同一サーバーや、ネットワーク上のサーバーに、ノード(Erlang ランタイム)をいくつでも、立ち上げて、簡単に通信ができちゃうところ。

erl -name 'node-name@hostname'

で、ほんと、いくらでも、立ち上がる。

そして、ノードをまたがったプロセス間通信の仕組みが、Erlang ランタイムにもともと組み込まれている。

ネットワーク上に分散したプロセス間通信と、その間のメッセージングがいとも簡単にできちゃう。

しかも、ノードをまたがった、プロセスの監視や再起動などが、組込みのモジュールで、最初から全部そろっている感じ。

とにかく「ネットワークプログラミング」だとか「プロセス間通信」だとか「並行プロセス管理」だとか、小難しいことをいっさい考えずに、たくさんのノードの分散したアプリケーションを書けちゃう感じ。

関数をまたがって、状態を持てない言語のそもそものアーキテクチャが効果絶大なんだろうなあ。

試してはいないけど、Erlangランタイムや、プロセス管理、プロセス間通信は、めちゃくちゃ信頼性が高いらしい。

状態管理が不要になれば、並行分散処理の信頼性は格段に向上する。

C/C++ とか、 Java で、スレッドセーフにするのがたいへんなのは、状態管理がたいへんだから。

最初から状態を持たなければ、どんどん、分散並行処理しても、安全なわけだ。


Twitter のメッセージングサーバーErlang で書かれていたとか、RappidMQ が Erlang で実装という話を聞いたような気がするが、なるほどなあ、という感じ。


ルールベースで宣言型、かつ、非同期メッセージングの分散並行処理という、この Erlang という言語の世界は、ほんと、別世界。そしてすばらしい。

Erlang で仕事をするとか、Erlang がメジャーになるということはないとは思う。

でも、 

宣言スタイル:事実とルールを宣言、パターンマッチングで処理

分散協調:非同期メッセージングで、ネットワーク上で、分散並行した多数のプロセス間で、協調処理

ほんと、すてきなアーキテクチャだと思う。

しかも、その世界を、さくっと、試せてしまうのが、Erlang

クラウドコンピューティングに対応したソフトウェアアーキテクチャプラットフォームの雰囲気を、すでに Erlang で、疑似体験できている気がする。

「7つの言語 7つの世界」の意図の通り、「異なるプログラミングパラダイムを知ることが設計能力を劇的に向上する」ということを、また実感できた。

実プロジェクトで、Mule ESB でのメッセージングアプリケーションの設計・実装の真っ最中なんだけど、そっちの設計のアイデアやスタイルに、だいぶ、影響がでそうな予感。

Smalltalk だと、メッセージパッシングが、ひとつのプログラム空間に閉じている。

Erlang では、メッセージパッシングは、多数のプロセス、多数のノード上で、さくっと実現できちゃう。

ほんと、すごい世界になったもんだと思う。

Mule ESB 3.2 JMX を HTTP (ブラウザ)で利用する

最近は、すっかり、メッセージングスタイルのアプリケーション開発にのめりこんでいる。

使っている道具は Mule ESB。メッセージング処理用のアプリケーションサーバー

Tomcat は、 Web用のアプリケーションサーバー )

Mule ESB は、 3.x になって、アプリケーションの配置・停止がホットデプロイになり、運用が劇的に簡単になった。

<flow> の概念が導入され、サービスの記述が、直観的になったのは大きい。

EIP:Enterprise Integration Patterns のパターンを意識した実装/機能/説明が豊富になったので、EIP の実践手段としては、だいぶ進化した感じ。(現在も発展中なので、おおいに期待したい)

3.1.2 から、ログファイルが、アプリケーション単位に扱えるようになったのはありがたい。(ようやくですが)

3.2.0 で、schemaLocation ファイルで、バージョン番号のかわりに "current" が使えるようになった。これ、地味だけど、とてもありがたい改良点。

あと、前々から、実現できたいたらしいけど、私がようやく自分で設定できるようになった、Mule ESB の運用・監視ネタ。

JMX の機能を、HTTP ベースでブラウザから、利用する方法。

JVM のメモリ、スレッドの状態の把握から、Mule の各コンポーネントの動作状況の監視、起動や停止など、もりだくさんの機能が手軽にアクセス可能人になる。

以下の、単純なアプリケーションを、ホットデプロイすれば LAN 上 mule-hostname:9999 で、ベーシック認証付で、利用できるようになる。

興味がある人は、ぜひ、ためしてみてください。

この機能は、セキュリティ上、がちがち保護すべき機能なので、くれぐれも自己責任で。

( 本番環境であれば、firewall 設定で、 ip や、port の縛りが必須です )

JMX監視アプリケーションの config ファイル:

mule-jmx.xml

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:management="http://www.mulesoft.org/schema/mule/management"
      xsi:schemaLocation="
          http://www.mulesoft.org/schema/mule/core
          http://www.mulesoft.org/schema/mule/core/current/mule.xsd
          http://www.mulesoft.org/schema/mule/management
          http://www.mulesoft.org/schema/mule/management/current/mule-management.xsd
      ">

<!-- for JMX Console -->
<management:jmx-default-config />

<!-- for Browser Access -->
<management:jmx-mx4j-adaptor jmxAdaptorUrl="http://0.0.0.0:9999" login="masuda" password="toru" />

</mule>

schemaLocation の、/current/ が、3.2 からの新機能。

以前のバージョンまでは、ここに、 3.1 とか、実バージョン番号を入れていたので、Mule サーバーバージョンアップの度に、書き換えが必要だった。

3.2 以降は、/current/ と記述しておくと、実行時に、実際の Mule ESB バージョン番号に展開されてチェックされるらしい。

2011-09-12

続々 プログラミング言語 Io : 多重継承

Io は、多重継承ができる。

プロタイプベース

前にも書いたように、Io は、クラスベースではなく、プロトタイプベースのオブジェクト指向言語

Vehicle := Object clone

Car := Vehicle clone

Civic := Car clone

と宣言していけば、

Vehicle <- Car <- Civic

というオブジェクトの階層ができる。

これとは別のオブジェクト階層として、

Maker := Object clone

Honda := Maker clone

と宣言して、

Maker <- Honda

というオブジェクトの階層を作る。

継承関係の表示

Io での継承関係は、protos メッセージ( プロトタイプを指す proto の 複数形 ) で確認できる。

スロット名の通り protos は、 list() 、つまり、複数のオブジェクトを保持できる。

Civic protos

は、今のところ

type = Car

だけ。

多重継承

Civic appendProto( Honda )

とメッセージを送ると、Civic のprotos 、つまり元になったオブジェクトの一覧に、 Honda を追加できる。

今度は、

Civic protos だと、

type = Car,

type = Honda

となって、めだたく(?)、Civic は、Car オブジェクトの特性と、Honda オブジェクトの特性を組み合わせて継承したオブジェクトになる。

Civic の生成時に多重継承を宣言しているのではなく、後から、他のオブジェクトの特性を注入(?)している。

Car にも、Honda に、それぞれ、次のようなスロットを追加する。

Car wheels := 4 (車輪は四つ)

Honda ism := "hondaism" (主張は、ホンダイズム)

この結果、

Civic wheels ==> 4

Civic ism ==> hondaism

というように、 Civic は、Car の特性と、Honda の特性を、多重に継承したオブジェクトになる。

触ってみて、はじめてわかる感触

Io は、単純さにこだわった言語なので、多重継承の仕組み、会話的に、ちょっと試してみるのは、とても便利。

第一印象は、継承というより、コンポジションに近い。

動的に継承関係を、append , remove できたり、継承関係を設定した後に、継承元にスロットを増やせば、それがそのまま反映されたりできるのが、そういう印象になっているのかもしれない。

個人的には、(単一継承パラダイムでも)継承より、コンポジション派なので、多重継承も、正直いうと、懐疑的。

今まで、多重継承で、実際コードで、いろいろ試したことはなかったので、良い機会なので、ちょっと、多重継承ごっこ(?)をやってみようかと思っている。

たぶん、継承よりコンポジション、という自分のスタンスは変わらないだろうけど、多重継承というパラダイムを実際に触ってみることで、自分の設計感覚に新しい財産を追加できそうな期待感はある。

「多重継承」という言葉だけではぴんとこないけど、 Civic appendProto( Honda ) というコードを実際に書いてみると、全然違うものが見えてくるのが実感できる。