IntelliJ IDEA BootRun時のコンソール出力の文字化け

  • windows 環境
  • 4:Run windowの出力

build.gradleにこういう記述を追加して状況は改善

def defaultEncoding = 'UTF-8'
tasks.withType(org.springframework.boot.gradle.tasks.run.BootRun) { defaultCharacterEncoding = defaultEncoding }

部分的にまだ文字化け

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: SQLス�?ートメントに�?法エラーがありま�? " 

vmoptionsにfile.encodingを指定すれば解消するかもしれない

IntelliJ IDEA 2020.1 で、vmoptions ファイルに指定すると起動しない問題があり、設定できていない。

IDE起動時に参照されるJava VM Option file(.vmopitons設定ファイル)に「-Dfile.encoding=UTF-8」が指定されている

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 だと動作しない。
バグ?

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 コマンド使うだけで、簡単に違いを発見できた)

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 お試しあれ。

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 になって、アプリケーションの配置・停止がホットデプロイになり、運用が劇的に簡単になった。

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

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 バージョン番号に展開されてチェックされるらしい。