Webサービスの最近のブログ記事

JavaBeans仕様における、プロパティ命名規約では、

というgetter/setterメソッドがあれば、fooというプロパティが定義されていると解釈します。ここからは、メソッドの中では、先頭が大文字ですが、プロパティ名としては、先頭を小文字に変換するという規則になっていることが暗黙的に読み取れますが、これは、Javaを使ってプログラミングしている人にとっては、常識的な話ですね。

この暗黙的な変換は、JavaBeans APIの、java.beans.Introspector#decapitalize()メソッドにて実装されています。そこでは、以下のように仕様が説明されています。

文字列を引数に取り、通常の Java 変数名の大文字使用法に従って変換するユーティリティメソッドです。通常は最初の文字を大文字から小文字に変換しますが、この変換を行わない特殊なケースもあります (複数の文字が存在し、先頭の文字と 2 番目の文字がどちらも大文字である場合など)。

たとえば、「FooBah」は「fooBah」、「X」は「x」に変換されますが、「URL」は変換されません。

では、実際に、いくつかの例で試して見ましょう。

結果は以下の通りとなります。
(1) FooBah --> fooBah
(2) X --> x
(3) URL --> URL
(4) UR_L --> UR_L
(5) U_RL --> u_RL
(6) U2_RL --> u2_RL
(7) _FooBah --> _FooBah

Introspector#decapitalize()メソッドのソースを見ると、先頭の2文字が両方とも英大文字(Character#isUpperCase())の場合以外は、先頭1文字を、Character#toLowerCase()しているようです。

結果を分類すると、

  • (1)(2): 「通常の Java 変数名の大文字使用法」に適合している。
  • (3)(4): 「特殊なケース」に該当するので、変換されなかった。
  • (5)(6): 何となく違和感のある変換が行われた。
  • (7) : 先頭がアルファベットではないため、変換されなかった。
ということになるかと思います。

(1)~(4)については、仕様にて明記されている挙動なので、問題ないでしょう。(7)は、特に実害はないように思います。(5)と(6)については、「特殊なケース」の方に分類されると期待されるところが、そうではなかったという感じです。

実際のシステムでは、プロジェクトの事情から、(5)と(6)のようなプロパティ名を付与せざるを得ない場合もあります。例えば、Webサービスで非Javaのシステムとの接続をする場合に、相手側主導でインタフェース設計が行われると、A3_CUSTOMER_IDのような(6)に該当する名称のプロパティが定義されることがあります。ここで、WebLogicのservicegenのようなツールを使って、WSDLを自動生成すると、complexTypea3_CUSTOMER_IDというエレメントが生成されます。これは、JAX-RPC仕様では、WSDLのcomplexTypeは、JavaBeansクラスにマッピングすることが決められており、エレメント名にはBeanのプロパティ名が設定されることによります。しかしながら、アプリケーションレベルのインタフェース設計に対しては不適合な状態になってしまいます。

最も理想的な解決策は、(1)(2)以外の場合は、すべて「特殊なケース」になるように、Introspectorを変更することですが、JavaBeans仕様なのでそれは現実的ではありません。
従って、このような制約を、当初から意識した上で、問題を回避するための命名規約を作成しておくことが適切な対応だと思います。具体的には、以下のいずれかになります。

  • 「通常の Java 変数名の大文字使用法」に適合しない名称を許可しない。
  • 先頭の2文字は、英大文字のみを許可する。

SOAという考え方が広まるにつれ、Javaアプリケーションが、非Javaシステムと接続する機会が多くなってきていると思いますが、そのときに、この話がお役に立てば幸いです。

ITの世界には、多くの標準仕様が作成され、それらをベースとする、さまざまな製品がリリースされています。標準仕様のおかげで、われわれは、ベンダーに縛られることなく、「相互接続性」や「ポータビリティ」などのメリットを享受しています。ところが、標準仕様を別の角度から見てみると、適用領域によっては、オーバスペックで複雑すぎるのではと感じてしまうものも多く見られます。
特に、最近は、XMLとWebサービスの世界で、そういった傾向が強くなってきているようです。

一般的な企業システムで使用されるデータは、そのほとんどがRDBに永続化されています。そこでは、2次元の表である「テーブル」を、キーによって関連付け(リレーションシップ)することで、多次元的なデータ構造が実現されています。
Javaアプリケーションでは、JDBC APIでRDBにアクセスし、それらのデータを何らかのオブジェクトのプロパティにマッピングして使用します。その結果、メモリ上では、RDBのデータモデルを投影したオブジェクトとして表現されることになります。
ここまでは、「そんなの常識」という内容ですが、これらのデータをWebサービスで扱う場合には、ちょっと話が違ってきます。
Webサービスでは、送受信メッセージをXML形式で扱います。XMLは、RDBやJavaオブジェクトとくらべると、「豊かな表現力」を持っていますが、その裏返しとして、複雑でかつオーバスペックなデータモデルを生みやすいという副作用があると思います。

ここでは、複雑さの落とし穴にはまらないよう、RDBのデータをXML化するときに、シンプルなモデルを作成する方法について考えてみたいと思います。
実際には、JavaオブジェクトとRDB間のマッピングについても、いろいろと考えるべきことはあるのですが、ここでは、すでに最適化されたJavaオブジェクトが定義されていると仮定して、話を進めていきます。

みなさんは、WSDLを作成するとき、どんな方法を使いますか?
JAX-RPCによる、Webサービス開発スタイル」の中で、ボトムアップ型とトップダウン型という2つのスタイルの概要を説明しました。この2つのスタイルを、出来上がるWSDLの複雑さという観点で見ると、トップダウン型の方が、複雑なXMLスキーマができる確率が高い傾向があります。その理由としては、やはり、XMLが持つ「豊かな表現力」によるところが大きいのではと思われます。XMLスキーマを設計していると、発想も豊か(?)になってしまい、「将来の拡張のため」などの名の下に、不要な項目を追加したり、モデリングに凝りすぎて、不要な型を作ってしまう傾向が強いようです。
一方、ボトムアップ型では、いくつかの制約はあるものの、圧倒的にシンプルなXMLスキーマになります。もちろん、ベースとなるオブジェクトモデルがシンプルな構造であることが前提です。オブジェクトモデルに関しても、変に凝りすぎず、RDBのデータモデルを素直にマッピングしていれば、それほど複雑にはならないでしょう。
ボトムアップ型の制約が問題となる場合は、トップダウン型を採用しますが、その場合でもスタートポイントしては、ボトムアップ型のツールで生成されたWSDLを使用することで、複雑さを回避できると思います。

さらに、誤解を恐れずに言うと。。。
当たり前の話ですが、RDBのデータをJavaオブジェクトに直線的にマッピングした場合、1行分のデータは、カラム名をキーとするMapで表現することができます。複数行のデータやto manyリレーションシップはListに対応付けることができます。このような、MapとListからなるオブジェクトを、Mapのキーを要素名とするXMLにマッピングしてできあがるモデルは、かなりシンプルなものになります。
XMLスキーマという観点では、制約があるモデルかもしれませんが、世の中のかなりのビジネスデータは、これで十分にカバーできるのではと思います。

例えば、以下のようなMapとListから構成されるオブジェクトがあります(HashMapとArrayListをtoString()したイメージです)。


        {
          productPrice=[
            {
              productCode=C0001,
              productName=ブルーマウンテン豆(100g),
              price=1200
            },
            {
              productCode=C0003,
              productName=グァテマラ豆(100g),
              price=1300
            }
          ]
        }
 

これを、XMLにマッピングしたものが、以下のようなイメージです。


         <productPriceList>
            <productPrice>
              <productCode>C0001</productCode>
              <productName>ブルーマウンテン豆(100g)</productName>
              <price>1200</price>
            </productPrice>
            <productPrice">
              <productCode>C0003</productCode>
              <productName>グァテマラ豆(100g)</productName>
              <price>1300</price>
            </productPrice>
        </productPriceList>

特に目新しい考え方というわけではないですが、Javaでも、こういったシンプルなマッピングの標準仕様というのが、あってもいいのではないかと思います。
WSDLには、ちょっと合わないけれど、RESTfulなWebサービスには、フィットするのではないでしょうか。
PHPのSimpleXML関数は、かなり近いイメージかもしれませんね。

これもSOA....?

| コメント(0) | トラックバック(0)

ロボット業界のことはよくわからないのですが。。。

解説! ロボット開発環境Robotics Studio(1)にて、Microsoft Robotics Studio(MSRS)という、アプリケーション開発プラットフォームが紹介されています。
MSRSがターゲットしているのは、ビジネスアプリケーションではなく、ロボットを動かすためのアプリケーションなのですが、その実行環境は、RESTfulなSOAをベースとするアーキテクチャとなっています。
ロボットを制御する「サービス」をC#やVisual Basicで作成し、Visual Programming Languageというグラフィカルなツールにて、各サービスの「流れ」を定義していきます。
(まるでBPMのような感じですね)

LEGO MINDSTORMSには、昔からちょっと興味があったのですが、MSRSで対応しているようなので、時間があれば、試してみたいところです。
ロボット工学の実習用教材として、使われている例もあるようですが、システム開発の実習教材として使っても、楽しみながら学習できていいかもしれませんね。

Java EE 6

| コメント(0) | トラックバック(1)

JSR 316: Java Platform, Enterprise Edition 6 (Java EE 6) Specificationの検討が、JCPで始められているようです。
J2EE1.xまでは、時代をリードしようという空気があったと思いますが、最近は、まわりにあるものを拾い集めているような傾向があるように思います。例えば、以下のものに関しては、時代の流れと合わなくなったことにより、中身だけでなく、呼び名が変わります。

  • EJB CMP --> Java Persistence
  • JAX-RPC --> JAX-WS

また、新しいものもいくつか追加されるようですが、その中でもある意味注目したいのは、JSR 311: JAX-RS: The Java API for RESTful Web Servicesです。これまで、Simple & Lightなアーキテクチャとして、プラットフォームを選ばず、草の根的に広まってきたものを、今になってJava EEの中で仕様化するわけですから。。。(すでにApache Axis2の中でも、RESTの実装がサポートされていたりします)
仕様のドラフトをざっくりと見たところでは、URIやMIME Typeなどの外部パラメタを設定するためのアノテーションに関する規約が中心であり、EJBやJAX-WSなどと無理に統合しようということはないようなので、少し安心しました。
Jerseyというリファレンス実装もあるみたいなので、機会があれば、試してみたいと思います。
ただ、リリース予定がQ4 2008というのは、ちょっと遅いかなと。。。