MDBの実装
前編ではメッセージとしてTextMessageを送受信しました。今回は業務システムでよく使用されるObjectMessageを使います。ObjectMessageにはシリアライズされたオブジェクトを設定、取得します。芋焼酎の銘柄情報を格納するImoshochuCatalogItemクラスを作成し、これをインスタンス化したものをObjectMessageに設定し、MDBで受け取れるようにします。リスト2が実装後のImoshochuMessageDrivenBeanクラスです。
001:package jp.kawakubo; 002: 003:import javax.ejb.ActivationConfigProperty; 004:import javax.ejb.MessageDriven; 005:import javax.jms.JMSException; 006:import javax.jms.Message; 007:import javax.jms.MessageListener; 008:import javax.jms.ObjectMessage; 009: 010:/** 011: * 012: * @author tomoharu 013: */ 014:@MessageDriven(mappedName = "jms/MDBSampleQueue", activationConfig = { 015: @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 016: @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 017: }) 018:public class ImoshochuMessageDrivenBean implements MessageListener { 019: 020: public ImoshochuMessageDrivenBean() { 021: } 022: 023: public void onMessage(Message message) { 024: ObjectMessage objectMessage = null; 025: ImoshochuCatalogItem catalog = null; 026: try { 027: objectMessage = (ObjectMessage)message; 028: // ObjectMessageをImoshochuCatalogItemにキャストしgetterメソッド 029: // で各項目を取り出し、コンソールに表示する 030: catalog = (ImoshochuCatalogItem)objectMessage.getObject(); 031: 032: System.out.println("メッセージ受信開始"); 033: System.out.println("銘柄名 :" + catalog.getName()); 034: System.out.println("読み方 :" + catalog.getNameKana()); 035: System.out.println("度数 :" + catalog.getDosu()); 036: System.out.println("麹 :" + catalog.getKoji()); 037: System.out.println("芋の種類:" + catalog.getSweetPotatoName()); 038: System.out.println("製造元 :" + catalog.getManufacturer()); 039: System.out.println("容量 :" + catalog.getVolume()); 040: System.out.println("単価 :" + catalog.getPrice()); 041: System.out.println("メッセージ受信終了"); 042: 043: } catch (JMSException e) { 044: e.printStackTrace(); 045: throw new RuntimeException(e); 046: } 047: }
リスト2を説明します。
23行目のonMessageメソッドは引数としてMessageインターフェースを持ちます。Messageを継承するインターフェースとして前編で紹介したTextMessageや今回紹介するObjectMessageなどのインターフェースがあります。その他にもMapMessage、BytesMessage、StreamMessageなどが存在し、メッセージの特性に応じ使い分けることが可能になっています。TextMessageは前編の単なる文字列だけでなく、XMLなども送ることが可能です。その他のメッセージについてはJMSのAPIを調べてください。
24行目がMessageインターフェースを継承しているObjectMessageインターフェースの宣言です。25行目がその中に格納するオブジェクトの宣言です。
27行目は受け取ったメッセージがObjectメッセージであるためダウンキャストしています。30行目ではさらにImoshochuCatalogItemクラスにキャストしています。
一般にダウンキャストは危険なコーディングとなりますが、送信側と受信側でお互い授受しあうメッセージタイプが分かっているのであれば何の問題もありません。ただし、お互い相手のことを、メッセージタイプだけでなくオブジェクトの内容も意識しなくてはならないところがWebサービスなどと一線を画するところです。
WebサービスのWSDLを介する通信の便利さと比較すると縛りがないため脆弱な作りになりかねません。この場合、オブジェクトこそがお互いを結びつけるインターフェースだと言ってしまえばそれまでですが、やはり明確なインターフェース定義がないのは変更容易性という視点からは弱いと言わざるをえません。
ただし、薬が時には毒となるように、毒が時には薬となるように、使い方次第だと筆者は考えています。小さな規模のシステムや、大規模であっても同じ組織が管理しているシステム同士であれば、お互いが何者かを知っていることが多く煩雑なWSDLなどの設定ファイルも必要としないことを考えると非常に重宝します。
46行目にfinallyブロックがありません。今までの説明からするとメモリリークの原因になるのではと考えるのも無理ありませんが、ここがコンテナ管理の便利なところで、RuntimeExceptionが発生するとリソースの解放も行ってくれます。