Hiroyuki Wajima
H/W's Blogs about S/W
Profile
Hiroyuki Wajima
Sr. Technical Specialist
Sun Java Consulting
Sun Professional Services
アーカイブ
« 11月 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     
       
今日
XML
Search

リンク
 

Today's Page Hits: 32

All | Java EE | Personal | SOA | Sun
« 前のページ | メイン | 次のページ »
20060726 2006年 7月 26日 水曜日
Java framework in the age of Java EE 5 (1) : Struts and/or/vs Shale (JSF)
Java EE 5の時代のJavaフレームワークはどのように展開していくのでしょうか?その一つのヒントとなるのが,StrutsとShaleに関する最近の動きです。

StrutsとShaleについて簡単に解説すると,Strutsは言わずと知れたJSP/ServletベースのMVCフレームワーク(SunのCraig McClanahanが開発),ShaleはStrutsのサブ・プロジェクトとして発足したJSF(JavaServer Faces)ベースのフレームワーク(Strutsと同じくCraigが開発)です。ちなみにCraigはJSFのSpec Leadも務めています。

Shaleは最近,Strutsのサブ・プロジェクトから離脱して,Apache直下のプロジェクトに移りました。その理由として,
などが挙げられています。
(その際の経緯はこちらのスレッドに詳しいので興味のある方は読んでみてください。)

JSFはUIコンポーネントの利用,可搬性を重視したフレームワークで,開発生産性の向上を念頭において仕様策定されています。普通にコーディングしても良いのですが,Sun Java Studio Creator 2NetBeans等のツールを使えば,ほとんどコーディングすることなく開発できます。今後,Javaをアプリケーション開発プラットフォームとして幅広く展開させていこうと考えている方には,有力な選択肢になると思います。

posted by wajima 7月 26日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060722 2006年 7月 22日 土曜日
Java frameworks' name must start with "S" ?
ふと思ったのですが,Javaフレームワークには"S"で始まる名前のものが多いですね。
Struts, Shale, Seam, Spring, Seasar…これって偶然ですか?

posted by wajima 7月 22日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060715 2006年 7月 15日 土曜日
医療機関のIT化,インテグレーション
最近,子供を連れていろいろな医療機関に行くことが多いのですが,医療機関のITシステムはいわゆる「サイロ」の巣窟のようです。私が遭遇して「IT化されるといいのになぁ…」,「(SOA等を活用して)インテグレーションされるといいのになぁ…」と思ったケースを挙げてみます。
(いわゆる医療業界の常識は全く知らないので,思うままがままに書いてみます。あと,セキュリティ上の問題点もいろいろありそうですが,その辺はちょっと脇においておきます。)
  1. 問診表
    初めての医療機関,薬局に行くと,様々な個人情報(住所,氏名,年齢,連絡先,既往症,アレルギーの有無,今回受診した経緯など)を,問診表に記入させられます。医療機関も薬局もCRMのようなシステムが導入されているようなのですが,たぶんスタンドアローンのシステムなのではないでしょうか。統一データベースみたいなもので一元管理してもらえると無駄が省けます。
  2. 診察券
    医療機関ごとに診察券が発行されます。これも数が増えてくると管理が結構面倒です。統一カードみたいなものを作ってもらいたいです。(住基カードが普及すると,統一カードみたいに使えるようになるのでしょうか…)
  3. 処方箋
    医療機関を受診すると,紙に印刷された処方箋を持って,院外の薬局に行かされます。医療機関と薬局のシステムがオンラインで繋がっていれば,紙をわざわざ持っていかなくても良いですよね。
  4. おくすり手帳
    いまどきの薬局では「おくすり手帳」なるものを配っています。これは何かというと,ある人がいろいろな薬局でもらった薬に関する情報を一元管理するための手帳です。薬が処方されるときに,今回の処方薬一覧を印刷した「おくすり手帳」用のシールをくれます。このシールを「おくすり手帳」に貼ってください,という訳です。何も無かった頃に比べると格段の進歩なのかもしれませんが,煩わしいです。ユーザに責任を転嫁せず,統一データベースみたいなもので管理してほしいですね。
  5. 予約システム
    進んでいる医療機関では,携帯でオンライン予約できたり,待ち人数をリアルタイムで確認できたりします。ただし,そうでないところも多いです。
    先日受診したとある大病院では,最近大々的にシステムの入れ替えがあったようです。例えば,再診予約システムが導入されており,診察が終わったその場で次の受診日時を予約できます。それから,再診の自動受付機も導入されています。診察券を挿し込むと受付番号が発行され,その番号を使って,診察室前の電光掲示板で呼び出しが行われます(個人情報保護への配慮でしょうか)。ただし…いったん治療が終わったり,予約をキャンセルしたりすると,次の予約をするためのユーザインタフェースが電話のみになってしまいます。さらに,電話受付センターの受付時間が14:00 - 17:00の3時間のみ,しかも全く繋がりません。ストレス性胃炎になってしまいそうです。
  6. 紹介状
    症状が重かったり,詳しい検査が必要になったりすると,紙の紹介状を持って他の医療機関に行かされます。紹介状には,これまでの経緯等が記入されているそうです。また,レントゲン写真等がある場合には,それも持たされるようです。紹介状があればまだしも,引越ししたりして新しい医療機関に行かなければならなくなった場合には,口頭でこれまでの経緯を説明しなければなりません。とっても面倒です。カルテが統一データベースで管理されていれば済みますよね。
この分野,韓国では非常に進んでいるようです。イギリスでも積極的な取り組みがなされています。イギリスNHSのシステムは現在,徐々に出来上がっているようですが,統一データベースSpineをBTが運営しています。そして,このSpineの統合基盤として使われているのが,何を隠そうSun Java CAPS(a.k.a. SeeBeyond, Sun Java Integration Suite)なのです。

調べてみると,日本でも平成13年に厚生労働省に対して「保険医療分野の情報化にむけてのグランドデザイン」という提言がなされていました。上に書いたような内容はおおよそ網羅されています。目標年次が平成18年だったそうですが…早く実現してほしい内容です。

(*)愚痴っぽい内容ばかり書いてしまいましたが,子供が出来て良い面でびっくりしたことを1つ。(自治体によって違いはあるようですが)乳幼児の医療費はほぼタダで済みます。これは地方自治体が乳幼児の医療費助成制度(マル乳)を導入してくれているからです(例えば東京23区では…)。うちの場合,医療機関でも薬局でもほぼ現金不要です。素晴らしい。
最近キーワードになっている「少子化対策」,いろいろ考えるところはありますが,ユーザにメリットがある施策は積極的に実行して欲しいものです。

posted by wajima 7月 15日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060708 2006年 7月 08日 土曜日
Ajax4jsf on Glassfish
前回までのエントリで,以下のような順序でリクエストが処理されるアプリケーションを構築できました。
  1. Webブラウザ
  2. JSF
  3. BPEL on OpenESB (JBI)
  4. Web Service (EJB 3.0)
  5. Stateless SessionBean (EJB 3.0)
  6. Entity Object (EJB 3.0)
  7. Java DB
ついでにといっては何ですが,WebブラウザとJSFの間でAjaxを使ってみたいと思います。

各種のAjaxライブラリ,ツール等が提供されているようですが,今回使うのはAjax4jsfです。
これは,JSFで構築したサーバサイドのプログラムに全く手を入れることなく,プレゼンテーション(JSP)の修正だけでAjaxを用いた非同期更新の仕組みを組み込むことが出来るスグレモノです。

ソースコードを見てもらうと分かり易いと思いますので,前回のエントリで作成したJSPにAjax4jsfを適用したものを見ていただきましょう。

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="a4j" uri="https://ajax4jsf.dev.java.net/ajax"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <f:view>
            <h1><h:outputText value="Java Server Faces" /></h1>
            <h:form>
                <h:inputText value="#{PricingManagedBean.productId}"/>
                <a4j:commandButton reRender="productId,productName,price" value="Submit" action="#{PricingManagedBean.findBooksData}"/>
          </h:form>
            <hr>
            <table border="1">
                <thead>
                    <tr>
                        <th>Product Id</th>
                        <th>Product Name</th>
                        <th>Price</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td><h:outputText id="productId" value="#{PricingManagedBean.productId}"/></td>
                        <td><h:outputText id="productName" value="#{PricingManagedBean.productName}"/></td>
                        <td><h:outputText id="price" value="#{PricingManagedBean.price}"/></td>
                    </tr>
                </tbody>
            </table>

        </f:view>
    </body>
</html>


ソースコードで修正した箇所は,太字の部分だけです。
(*) 他には,web.xmlの修正や,ライブラリの修正が必要です。詳細についてはアーカイブ(本日現在の最新はv1.0rc1)に含まれるreadmeを参照してください。Glassfishで動かす場合には,さらにApache Commonsが必要なようです。私の場合,BeanUtils 1.7.0, Collections 3.2, Digester 1.7, Logging 1.1のjarをライブラリに追加すると動きました。

commandButtonをAjax4jsfが提供するcommandButtonに変更し,更新を反映するコンポーネントのidをreRender属性で指定するだけで,Ajaxアプリになってしまいます。つまり,
というふうに挙動が変わります。

他のAjaxライブラリやツールだと,サーバサイドの仕組みが独自になってしまい,既存のJ2EE/Java EEアプリケーションのアーキテクチャと整合性をとるのが難しくなってしまいそうなのですが,Ajax4jsfの場合は,JSFのモデルを崩すことなく,簡単にAjaxの要素を取り入れることが出来ますし,JavaScriptのコードを記述する必要も一切ありません。現在はまだコンポーネントの種類も少なく,思ったような処理を実現できない場合もあるようですが,今後の展開に期待したいと思います。

posted by wajima 7月 08日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060705 2006年 7月 05日 水曜日
BPEL on JBI by NetBeans and SOA Starter Kit (3)
前回までのエントリでJBIを使ったSOAアプリケーションのメイン部分を開発することができました。

せっかくなので,プレゼンテーションの部分を作って,エンド・ツー・エンドのアプリケーションに仕上げてみたいと思います。BPELのエントリポイントを呼び出せれば何でも良いのですが,Java EE 5から標準で組み込まれることになったJSF (Java Server Faces)を使ってみたいと思います。

(*) NetBeans Enterprise PackにはSun Java Studio Creator 2のようなWYSIWIGのWeb画面編集環境が無いので,エディタでちょろっと作ってみたいと思います。
Sun Java Studio Creator 2には,WebサービスをベースにJSFアプリケーションをWYSIWIGで開発する機能がありますので,興味のある方はチュートリアルを参考にチャレンジしてみていただければと思います。
また,現在NetBeans 5.5にSun Java Studio Creator 2の機能を組み込むためのプラグインCreator Packが開発中とのことですので,そのうちNetBeans Enterprise PackでJSFのWYSIWIG開発環境が使えるようになるでしょう。

1. プロジェクトの作成
[File]-[New Project]から,[Web]-[Web Application]を選択します。
Project Name: "PricingWebApp"を入力して[Next],Frameworksとして"Java Server Faces"をチェックしてプロジェクトを生成します。

2. Webサービスクライアントの生成
プロジェクトPricingWebAppで右クリック,[New]-[File/Folder]から,[Web Service]-[Web Service Client]を選択します。
Local Fileとして,前々回のエントリでローカルファイルとして保存,編集したBooksPricingProcessWebServiceBean.wsdlを指定します。
Package Name: "bpclient"とでもしておきましょう。
そうすると,プロジェクト配下に[Web Service References]-[BooksPricingProcessWebServiceBean]というノードが作成されます。

3. JSF Managed Beanの開発
JSFのManaged Beanというのは,画面の入出力にマッピングされるプロパティを管理したり,画面イベントに対応するアクション処理をアクションメソッドとして実装したりする,JavaBeansの一種だと思っていただければよいと思います。

(1) Managed Beanの生成
プロジェクトPricingWebAppで右クリック,[New]-[JSF Managed Bean]を選択します。
として,Managed Beanの雛形を生成します。
すると,PricingWebAppプロジェクトの[Configuration Files]-[faces-config.xml]に以下のような設定が追加されます。

    <managed-bean>
        <managed-bean-name>PricingManagedBean</managed-bean-name>
        <managed-bean-class>webapp.PricingManagedBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>


これにより,JSFページから,"PricingManagedBean"という名前で,このインスタンスにアクセスできるようになります。

(2) プロパティの追加
Managed Beanのメンバ変数として,以下の3つを追加します。

private String productId = "SUNW-001";
private String productName = null;
private java.math.BigDecimal price = null;


そして,ソースコードエディタ上で右クリック,[Refactor]-[Encapsulate Fields]を選択すると,これらのメンバ変数に対するsetter, getterを自動生成することが出来ます。

(3) アクションメソッドの実装
ソースコードエディタ上で,まず,以下のようなメソッドを実装します。

    public String findBooksData(){
       
        return null;
    }


次に,return文の前の行で右クリック,[Web Service Client Resources]-[Call Web Service Operation]から,BooksPricingProcessWebServiceBeanのfindBookPriceを選択すると,Webサービスのクライアントコードが自動生成されます。これを修正して,以下のような実装にします。

try { // Call Web Service Operation
    bpclient.BooksPricingProcessWebServiceBeanService service =
        new bpclient.BooksPricingProcessWebServiceBeanService();
    bpclient.BooksPricingProcessWebServiceBean port =
        service.getBooksPricingProcessWebServiceBeanPort();
    bpclient.BooksData result = port.findBookPrice(this.productId);
           
    this.setProductName(result.getProductName());
    this.setPrice(result.getPrice());
           
    return "findBooksData_success";
} catch (Exception ex) {
    // TODO handle custom exceptions here
}
       
return null;


4. JSFページの開発
プロジェクトを生成したときにwelcomeJSF.jspというページが出来ていると思いますので,これにコードを追加して,以下のようなJSFページを作ります。

<f:view>
    <h1><h:outputText value="Java Server Faces" /></h1>
    <h:form>
        <h:inputText value="#{PricingManagedBean.productId}"/>
        <h:commandButton value="Submit" action="#{PricingManagedBean.findBooksData}"/>
    </h:form>
    <hr>
    <table border="1">
        <thead>
            <tr>
                <th>Product Id</th>
                <th>Product Name</th>
                <th>Price</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><h:outputText value="#{PricingManagedBean.productId}"/></td>
                <td><h:outputText value="#{PricingManagedBean.productName}"/></td>
                <td><h:outputText value="#{PricingManagedBean.price}"/></td>
            </tr>
        </tbody>
    </table>
</f:view>


内容を簡単に解説します。

5. JSFアプリケーションの実行
プロジェクトPricingWebAppで右クリック,[Run  Project]を選択すると,プロジェクトがディプロイされた上で,ブラウザ上でJSP Pageが開きます。 "Java Server Faces Welcome Page"というリンクをクリックしましょう。

入力フィールドには,Managed Beanで実装したproductIdの初期値"SUNW-001"が入っています。
出力フィールドにも,Managed Beanで実装した初期値が表示されます。productName, priceとしてnullを指定したので空欄になっています。



Submitボタンを押すと,BPELで定義されたプロセスをWebサービスで呼び出した結果が,出力フィールドに表示されます。



posted by wajima 7月 05日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060701 2006年 7月 01日 土曜日
BPEL on JBI by NetBeans and SOA Starter Kit (2)

今回は,前回のエントリで作成したBPELから,前々回のエントリで作成したサービスをWebサービスで呼び出すことにします。


こんなイメージです。


【1. サービスのWebサービス化】

前々回に作成したサービス(BooksDataFacade,FooPriceListFacade,BarPriceListFacade)をWebサービス化します。手順は,前々回にBooksPricingProcessBeanをWebサービス化したときと同様です。Deployして,Webサービスのテスト機能で簡単に動作確認しておくと良いでしょう。


(*) 複数のWebサービスを同じパッケージで作成する場合,異なるクラスであってもWebメソッド名が重複すると上手く動作しないようです。findBooksData, findFooPriceList, findBarPriceListなど,Webメソッドの名前を変えるようにしましょう。


【2. WSDL,XMLスキーマの準備】

前回のBooksPricingProcessWebServiceBeanと同様の手順で,BooksDataWebServiceBean, FooPriceListWebServiceBean, BarPriceListWebServiceBeanのWSDL,XMLスキーマをローカルに保存,編集します。


【3. BPELの編集】

(1) WSDLのインポート,パートナーリンクの設定

編集した3つのWSDLファイルをBPELにインポートします。そして,それぞれのサービスに対応するパートナーリンクを設定します。


(2) アクティビティの配置

アクティビティを配置して,全体のプロセスが見えるようにしましょう。


(3) Assign1の設定

BPELエディタ上でAssign1を選択して,Mapperでコピー方法を設定します。
左側のFindBookPriceIn1から,右側のFindBooksDataIn1, FindFooPriceListIn1, FindBarPriceListIn1に線を引っ張ります。


BPELではこうなります。


        <assign name="Assign1">
            <copy>
            <from variable="FindBookPriceIn1" part="parameters"/>
            <to variable="FindBarPriceListIn1" part="parameters"/>
            </copy>
            <copy>
            <from variable="FindBookPriceIn1" part="parameters"/>
            <to variable="FindFooPriceListIn1" part="parameters"/>
            </copy>
            <copy>
            <from variable="FindBookPriceIn1" part="parameters"/>
            <to variable="FindBooksDataIn1" part="parameters"/>
            </copy>
        </assign>



(4) Invokeの設定

NavigatorのBPEL Logical Viewで,それぞれのInvokeを右クリック,[Edit]を選択して,3つのサービスを呼び出すように設定します。Input Variable,Output VariableをCreateするのを忘れないようにしましょう。変数名はデフォルト値で構いません。


(5) Assign2の設定

BPELエディタ上でAssign2を選択して,Mapperでコピー方法を設定します。
左側のFindBooksDataOut1から,右側のFindBookPriceOut1に線を引っ張ります。


BPELではこんな感じ。

        <assign name="Assign2">

            <copy>
            <from variable="FindBooksDataOut1" part="parameters"/>
            <to variable="FindBookPriceOut1" part="parameters"/>
            </copy>
        </assign>




(6) If1の設定

If1のMapperで,FindFooPriceListOut1のpriceをnumberとして評価した値が,FindBookPriceOut1のpriceをnumberとして評価した値より小さいことを条件として設定します。


(7) Assign3の設定

Assign3のMapperで,FindFooPriceListOut1のpriceをFindBookPriceOut1のpriceにコピーするように設定します。


If1とAssign3のBPEL該当箇所はこうなっているはずです。


        <if name="If1">
            <condition> ( number($FindFooPriceListOut1.parameters/return/price) &lt; number($FindBookPriceOut1.parameters/return/price) ) </condition>
            <then>
                <assign name="Assign3">
                    <copy>
                    <from>$FindFooPriceListOut1.parameters/return/price</from>
                    <to>$FindBookPriceOut1.parameters/return/price</to>
                    </copy>
                </assign>
            </then>
        </if>



(8) If2, Assign4の設定

FindBarPriceListOut1のpriceをnumberとして評価した値がFindBookPriceOut1のpriceをnumberとして評価した値より小さければ,FindBarPricListOut1のpriceをFindBookPriceOut1のpriceにコピーするように設定します。


【4. 実行】

BPELを実行してみましょう。BooksDataから取得したデータに加えて,FooPriceListとBarPriceListで安い方の価格が設定されたデータが戻ってくることを確かめます。


【5. BPELでのプロセス並行処理】

BPELではプロセスの並行処理が簡単に実行できます。これはJavaでプロセスを実行する場合に比較してアドバンテージになります。


Assign1の後に,並行処理のためのアクティビティであるFlowをDrag&Dropして,Invoke1, Invoke2, Invoke3を並行処理するようにアイコンを移動させます。これで並行処理が実行されるようになります。

 


posted by wajima 7月 01日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060628 2006年 6月 28日 水曜日
BPEL on JBI by NetBeans and SOA Starter Kit (1)

前回のエントリで,SOAのレイヤ構成を想定したJava EE 5開発を試してみました。これにSOAを適用するとどのようなイメージになるのでしょうか?実際に,前回のアプリケーションをベースにSOAを試してみましょう。具体的には,リソースレイヤとサービスレイヤをそのまま使って,プロセスレイヤをBPELで実現します。


ただし,一気にそこまで行くのは大変なので,今回は,ひとまず簡単なプロセスを動かすところまでにしたいと思います。


【0. 前提条件】

必要なのは,前回と同じくNetBeans Enterprise Pack 5.5 EA版だけです。これには,SOA Starter Kitが含まれています。プラットフォームはJBIのオープンソース実装であるOpen ESBです。


【1. プロジェクトの作成,準備】

(1) プロジェクトの作成

[File]-[New Project]を選択すると,[New Project]ダイアログが起動します。
[Service Oriented Architecture]-[BPEL Module]を選択します。

としてプロジェクトを生成します。


PricingProcess_1.bpel, PricingProcess_1.wsdlが生成されます。


(2) WSDL,XMLスキーマの準備

このプロセスのエントリポイントをWebサービスとして定義するためのWSDL,XMLスキーマを準備します。前回のアプリケーションのBooksPricingProxessWebServiceBeanと同じWSDLとXMLスキーマを流用することにしましょう。


前回の最後の手順で使ったWebサービスのテスト画面にWSDLというリンクがあります。これをクリックしてWSDLを表示させてローカルに保存しましょう。(拡張子をwsdlにしましょう。)


こんな感じのWSDLになっているはずです。


<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://ws/" name="BooksPricingProcessWebServiceBeanService">
  <types>
    <xsd:schema>
      <xsd:import namespace="http://ws/" schemaLocation="http://xxx.xxx.xxx.xxx:8080/BooksPricingProcessWebServiceBeanService/BooksPricingProcessWebServiceBean/__container$publishing$subctx/META-INF/wsdl/BooksPricingProcessWebServiceBeanService_schema1.xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
    </xsd:schema>
  </types>
  <message name="findBookPrice">
    <part name="parameters" element="tns:findBookPrice"/>
  </message>
  <message name="findBookPriceResponse">
    <part name="parameters" element="tns:findBookPriceResponse"/>
  </message>
  <portType name="BooksPricingProcessWebServiceBean">
    <operation name="findBookPrice">
      <input message="tns:findBookPrice"/>
      <output message="tns:findBookPriceResponse"/>
    </operation>
  </portType>
  <binding name="BooksPricingProcessWebServiceBeanPortBinding" type="tns:BooksPricingProcessWebServiceBean">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="findBookPrice">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="BooksPricingProcessWebServiceBeanService">
    <port name="BooksPricingProcessWebServiceBeanPort" binding="tns:BooksPricingProcessWebServiceBeanPortBinding">
      <soap:address location="http://xxx.xxx.xxx.xxx:8080/BooksPricingProcessWebServiceBeanService/BooksPricingProcessWebServiceBean" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
    </port>
  </service>
</definitions>



それから,WSDLの最初の方でXMLスキーマをインポートしています。このURLをブラウザのアドレスバーにコピーして,XMLスキーマを表示させ,これもローカルに保存します。(拡張子をxsdにしましょう)


そして,WSDLを今回の環境に合わせて編集します。

  1. インポートしているXMLスキーマのURLを(ローカルファイルを示す)相対パスに変更します。
  2. SOAPアドレスのロケーション属性を,PricingProcess_1.wsdlに記述されているロケーション属性の値に変更します。
    location="http://localhost:18181/PricingProcess/PricingProcess_1"
    となっているはずです。
  3. パートナーリンクを追加します。
    まずパートナーリンクの名前空間を定義します。
    xmlns:plink="http://schemas.xmlsoap.org/ws/2004/03/partner-link/"
    そして,パートナーリンクを追加します。
        <plink:partnerLinkType name="BooksPricingProcessPartnerLinkType">
            <plink:role name="provider" portType="tns:BooksPricingProcessWebServiceBean"/>
        </plink:partnerLinkType>


編集後のWSDLはこんな感じになります。(変更箇所をBold体で示しています。)


<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://ws/" name="BooksPricingProcessWebServiceBeanService"  xmlns:plink="http://schemas.xmlsoap.org/ws/2004/03/partner-link/">
  <types>
    <xsd:schema>
      <xsd:import namespace="http://ws/" schemaLocation="BooksPricingProcessWebServiceBeanService_schema1.xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
    </xsd:schema>
  </types>

  <!-- 中略 -->

  <service name="BooksPricingProcessWebServiceBeanService">
    <port name="BooksPricingProcessWebServiceBeanPort" binding="tns:BooksPricingProcessWebServiceBeanPortBinding">
      <soap:address
location="http://localhost:18181/PricingProcess/PricingProcess_1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
    </port>
  </service>
    <plink:partnerLinkType name="BooksPricingProcessPartnerLinkType">
        <plink:role name="provider" portType="tns:BooksPricingProcessWebServiceBean"/>
    </plink:partnerLinkType>
</definitions>



【2. BPELの編集】

(1) WSDLのインポート

PricingProcess_1.bpelのNavigator画面で,[Imports]を右クリック,[Add Import]を選択して,編集したWSDLをインポートします。


(2) パートナーリンクの追加

右のパレットから,Partner LinkをDrag&Dropします。

としてPartnerLinkを追加します。


(3) Receive, Replyの設定
最初のアクティビティとしてReceive, 最後のアクティビティとしてReplyをDrag&Dropします。


BPEL Navigator画面で,Receive1を右クリック,[Edit]を選択すると,ReceiveのProperty Editorが起動します。

とします。


Receive1に関しては,ソースビューで属性としてcreateInstance="yes"を追加します。


<receive name="Receive1" partnerLink="PartnerLink1" operation="findBookPrice" portType="ns1:BooksPricingProcessWebServiceBean" variable="FindBookPriceIn1" createInstance="yes"/>



同様に,Reply1に関しても

と設定します。


(4) Assignの設定
Receive1とReply1の間にAssignをDrag&Dropします。最初から存在する空のアクティビティは削除します。


Assignは,変数に値をコピーするためのアクティビティです。NetBeans Enterprise PackにはMapperという機能があり,GUIでコピー内容を指定できます。メニュー[Window]-[Mapper]を選択すると,Mapperが起動されます。BPELエディタ上でAssign1を選択して,Assignの内容を設定しましょう。


例えば,FindBookPriceIn1のproductIdをFindBookPriceOut1のproductIdにコピーする場合には,Mapperの左から右へ線を引っ張るだけでO.K.です。


固定値を設定する場合には,Mapperのメニューから[string literal]あるいは[number literal]を選択して値を入力,右の該当箇所へ線を引っ張ります。


BPELエディタをソースビューに切り替えると,Assignの内容が確認できます。


        <assign name="Assign1">
            <copy>
            <from>$FindBookPriceIn1.parameters/productId</from>
            <to>$FindBookPriceOut1.parameters/return/productId</to>
            </copy>
            <copy>
            <from>39.99</from>
            <to>$FindBookPriceOut1.parameters/return/price</to>
            </copy>
            <copy>
            <from>'Java EE and .NET Interoperability'</from>
            <to>$FindBookPriceOut1.parameters/return/productName</to>
            </copy>
        </assign>



BPELやXPathの細かい文法を知らなくても編集できるのでとても便利です。


【3. 実行】

(1) Composite Applicationの作成
[File]-[New Project]を選択,[Service Oriented Architecture]-[Composite Application]を選択します。

として作成します。


次に,プロジェクト"PricingApp"を右クリック,[Add JBI Module]でプロジェクト"PricingProcess"を追加します。


(2) テストの作成
プロジェクト"PricingApp"の[Test]を右クリック,[Add Testcase]を選択します。Input.xmlのproductIdとして"SUNW-001"など適当な値を指定します。


(3) 実行
プロジェクト"PricingApp"をDeployして,テストを実行します。



どうですか?WSDLの準備がちょっと面倒ですが,後はとても簡単です。プラットフォームがJBIであることを意識する必要も無く,BPELを直接編集する必要もありません。


posted by wajima 6月 28日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060624 2006年 6月 24日 土曜日
Java EE 5 looking ahead to the future SOA

以前のエントリで,SOAにはレイヤ構成が重要だと書きました。例えば,現在は一般的なエンタープライズJavaの開発を行っていたとしても,将来的にSOAを実施する可能性があるようであれば,SOAのレイヤ構成を想定した開発を行っておけば,スムーズに移行できるようになります。


今回は,最近リリースされたNetBeans Enterprise Pack 5.5を使って,SOAのレイヤ構成に従ったJava EE 5開発を試して見ましょう。(チュートリアル風に手順を追っていきますので,Java EE 5やNetBeansを使われたことのない方も是非試してみてください。とても簡単です。)


以下のような雰囲気のアプリケーションを作りたいと思います。


【0. 前提条件】

NetBeans Enterprise Pack 5.5 EA版をダウンロードしてインストールしてください。それだけでO.K.です。


【1. Java DBの準備】

NetBeansにはデータベースとして,Java DBであるDerbyがバンドルされています。今回はこれを使います。


(1) Java DB起動

NetBeansのメニューで,[Tools]-[Java DB]-[Java DB Database]-[Start Java DB Server]を選択します。コンソール"Java DB Database Process"が開始され,以下のようなメッセージが表示されます。


サーバーは、ポート 1527 で接続を受け入れる準備ができました。
接続番号: 1。



(2) 接続の設定

左側のペインで[Runtime]タブを選択,[Databases]-[Drivers]-[Java DB(Net)]を右クリックして,[Connect Using ...]を選択すると,"New Database Connection"ダイアログが開きます。ここで,

を入力すると,あらかじめ構築済みのサンプルDBに接続できるようになります。


(3) テーブル,データの作成

接続先DBの[Tables]-[Execute Command]を選択すると,SQLコマンドを実行するコンソールが立ち上がります。ここで,3つのテーブルを作成します。


create table books_data(
product_id varchar(8) CONSTRAINT book_data_pk PRIMARY KEY,
product_name varchar(64),
price numeric(6,2)
);
insert into books_data values('SUNW-001', 'Java EE and .NET Interoperability',49.99);
insert into books_data values('SUNW-002', 'Core Security Patterns',           59.99);
insert into books_data values('SUNW-003', 'NetBeans IDE Field Guide',         44.99);
insert into books_data values('SUNW-004', 'Core JavaServer Faces',            54.99);
insert into books_data values('SUNW-005', 'Java? Studio Creator Field Guide', 39.99);


create table foo_price_list(
product_id varchar(8) CONSTRAINT foo_price_pk PRIMARY KEY,
price numeric(6,2)
);
insert into foo_price_list values('SUNW-001', 44.99);
insert into foo_price_list values('SUNW-002', 49.99);
insert into foo_price_list values('SUNW-003', 39.99);
insert into foo_price_list values('SUNW-004', 44.99);
insert into foo_price_list values('SUNW-005', 34.99);


create table bar_price_list(
product_id varchar(8) CONSTRAINT bar_price_pk PRIMARY KEY,
price numeric(6,2)
);
insert into bar_price_list values('SUNW-001', 39.99);
insert into bar_price_list values('SUNW-002', 54.99);
insert into bar_price_list values('SUNW-003', 34.99);
insert into bar_price_list values('SUNW-004', 49.99);
insert into bar_price_list values('SUNW-005', 29.99);


作成されたテーブルのアイコンを右クリックして[View Data]を選択して,データの一覧を確認してください。


【2. エンティティ,サービスの開発】

(1) プロジェクトの作成

[File]-[New Project]を選択すると,"New Project"ダイアログが起動します。カテゴリ"Enterprise"から"EJB Module"を選択して,プロジェクト"PricingService"を作成してください。


(2) エンティティの作成

プロジェクト"PricingService"を右クリック,[New]-[Entity Classes from Database]を選択します。
Data Sourceとして"jdbc/sample"を選択します。(もし存在しないようなら,[New Data Source]から作成しましょう。)
"Available Tables"から"BOOKS_DATA"をADDして[Next],Package: persistを入力します。
[Create Persistence Unit]を押して,Persistence Unitを作成します。今回は,テーブルをcreateする必要は無いので,Table Generation Strategy: Noneを選択して[OK]を押します。
[Finish]でエンティティクラスが作成されます。


以下のように,Java EE 5のアノテーションを使ったEntity Objectが生成されます。


@Entity
@Table(name = "BOOKS_DATA")
@NamedQueries(
{@NamedQuery(name = "BooksData.findByProductId", query = "SELECT b FROM BooksData b WHERE b.productId = :productId"), @NamedQuery(name = "BooksData.findByProductName", query = "SELECT b FROM BooksData b WHERE b.productName = :productName"), @NamedQuery(name = "BooksData.findByPrice", query = "SELECT b FROM BooksData b WHERE b.price = :price")})
public class BooksData implements Serializable {

    @Id
    @Column(name = "PRODUCT_ID", nullable = false)
    private String productId;

    @Column(name = "PRODUCT_NAME")
    private String productName;

    @Column(name = "PRICE")
    private BigDecimal price;
   
    /** Creates a new instance of BooksData */
    public BooksData() {
    }

    public BooksData(String productId) {
        this.productId = productId;
    }

    public String getProductId() {
        return this.productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return this.productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public BigDecimal getPrice() {
        return this.price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public int hashCode() {
        int hash = 0;
        hash += (this.productId != null ? this.productId.hashCode() : 0);
        return hash;
    }

    public boolean equals(Object object) {
        if (object == null || !this.getClass().equals(object.getClass())) {
            return false;
        }
        BooksData other = (BooksData)object;
        if (this.productId != other.productId && (this.productId == null || !this.productId.equals(other.productId))) return false;
        return true;
    }

    public String toString() {
        //TODO change toString() implementation to return a better display name
        return "" + this.productId;
    }
   
}



(3) サービスの生成

プロジェクト"PricingService"を右クリック,[New]-[Session Facade]を選択します。
"Available Entity Classes"から"BooksData"をADDして[NEXT],Package: serviceを入力します。
[Finish]でセッションファサードが生成されます。


こちらも,Java EE 5のアノテーションを使ったStateless SessionBeanです。


@Stateless
public class BooksDataFacade implements BooksDataFacadeLocal {

    @PersistenceContext
    private EntityManager em;
   
    /** Creates a new instance of BooksDataFacade */
    public BooksDataFacade() {
    }

    public void create(BooksData booksData) {
        em.persist(booksData);
    }

    public void edit(BooksData booksData) {
        em.merge(booksData);
    }

    public void destroy(BooksData booksData) {
        em.merge(booksData);
        em.remove(booksData);
    }

    public BooksData find(Object pk) {
        return (BooksData) em.find(BooksData.class, pk);
    }

    public List findAll() {
        return em.createQuery("select object(o) from persist.BooksData as o").getResultList();
    }
   
}



(4) 他のテーブルに対するサービスの作成

上記(1)-(3)の手順を,FOO_PRICE_LISTテーブル,BAR_PRICE_LISTテーブルに対しても同様に実施します。


(*)ここまで,ソースコードは一行も編集していません。


【3. プロセスの開発】

(1) ビジネスプロセスを実行するSession Beanの生成

プロジェクト"PricingService"を右クリックして,[New]-[Session Bean]を選択,以下のような値を入力します。


(2) Dependency Injectionの設定

クラスが生成されたら,ソースコードエディタ上で右クリック,[Enterprise Resources]-[Call Enterprise Bean]を選択します。BooksDataFacade, FooPriceListFacade, BarPriceFacadeをそれぞれ選択すると,Injectionされるメンバー変数が生成されますので,以下のようにアノテーションを追記します。


従来のDDに記述していたejb-refと,ソースコードに記述していたInitialContext#lookupをまとめて記述しているとイメージしてください。このように記述するだけで,メンバー変数にEJB参照が自動的に設定された状態でメソッドからアクセスできるようになります。


@EJB(name="ejb/BooksDataFacade", beanInterface=BooksDataFacadeLocal.class)
private BooksDataFacadeLocal booksDataFacade;

@EJB(name="ejb/FooPriceListFacade", beanInterface=FooPriceListFacadeLocal.class)
private FooPriceListFacadeLocal fooPriceListFacade;

@EJB(name="ejb/BarPriceListFacade", beanInterface=BarPriceListFacadeLocal.class)
private BarPriceListFacadeLocal barPriceListFacade;



(3) ビジネスメソッドの追加

ソースコードエディタ上で右クリック,[EJB Methods]-[Add Business Method]を選択します。

としてメソッドを生成します。


生成したメソッド内で実装を行います。ようやくJavaプログラミングの出番ですが,以前のJ2EEに比べると,とても素っ気無いプログラムです。


public BooksData findBookPrice(String productId) {
        
  // 3つのサービスにアクセスします。
  BooksData booksData = booksDataFacade.find(productId);
  FooPriceList fooPriceList = fooPriceListFacade.find(productId);
  BarPriceList barPriceList = barPriceListFacade.find(productId);

  // 戻り値用のインスタンスにBooksDataをコピー
  BooksData to_return = new BooksData();
  to_return.setProductId(booksData.getProductId());
  to_return.setProductName(booksData.getProductName());
  to_return.setPrice(booksData.getPrice());

  // Foo, Barのうち,安い方の価格を設定します。
  if(to_return.getPrice().doubleValue() > fooPriceList.getPrice().doubleValue())
    to_return.setPrice(fooPriceList.getPrice());
       
  if(to_return.getPrice().doubleValue() > barPriceList.getPrice().doubleValue())
    to_return.setPrice(barPriceList.getPrice());
        
  return to_return;
}



(4) Webサービス化

それでは,このプロセスをWebサービスとして呼び出せるようにしましょう。


プロジェクト"PricingService"を右クリック,[New]-[Web Service]を選択します。

を入力,選択,[Finish]でWebサービスが生成されます。


ただし,ただし,このWebサービスにはpublicメソッドが一切定義されていません。
"BooksPricingProcessWebServiceBean.java"のソースコードエディタ上で右クリック,
[Web Service]-[Add Operation]を選択します。

としてメソッドを生成します。そして,3(2)と同様の手順で,Dependency Injectionの設定した上で,BooksPricingProcessBean#findBookPriceに処理を委譲するように実装します。


(5) Webサービスによる呼び出しテスト

[PricingService]-[Web Services]-[BooksPricingProcessWebServiceBean]を右クリック,[Test Web Service]を選択すると,テスト用のWebページが開きます。


プロダクトID(例えば,SUNW-001)を入力,送信すると結果が表示されます。

 


posted by wajima 6月 24日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060606 2006年 6月 06日 火曜日
Interop Tokyo 2006

SunはInterop Tokyo 2006出展します。
以下の4つのテーマを柱に,デモ,プレゼンテーションが行われます。

Java, Softwareに関しては,Identity Management, SOA(Sun Java CAPS), 開発ツール(NetBeans 5.5, Sun Java Studio Creator 2)などが予定されています。私もSOAのプレゼンテーションを行いますので,興味のある方は是非お立ち寄りください。


posted by wajima 6月 06日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]

20060520 2006年 5月 20日 土曜日
The Aquarium Japanese Edition

The Aquarium日本語版Java EE 5アプリケーションサーバのOpen Source開発プロジェクトGlassfishに関するブログ)が登場しています。本家と併せてどうぞ。


posted by wajima 5月 20日 2006年, 12:00:00 午前 JST Permalink 投稿されたコメント [0]