IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Sample IT projects  >

J*Air BagTrac: 第1回 JavaとDB2を使用して手荷物をリアルタイムで追跡する固有のバーコードを作成する

荷物はどこにある?

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

サンプルコード

原文はこちら

原文はこちら


レベル: 中級

Michael Abernethy, Software Engineer, FIT Team, IBM China Development Lab 
Kulvir Bhogal (kbhogal@us.ibm.com), Software Engineer, FIT Team, IBM China Development Lab 

2002年 10月 01日

この記事は、航空会社の乗客が自分の手荷物をリアルタイムで追跡できるようにする方法を説明するシリーズの1回目です。著者は、架空の航空会社J*Airと同社の新規システムBagTracを例に、Javaフロントエンドを使用してDB2データベースと通信し、手荷物の情報を追跡および保管します。今回の記事では、システム全体の枠組みおよび荷物の最初のチェックインを紹介します。バーコードをステッカーに印刷する方法、および番号の一意性を確保するためのバックエンド・ロジックについて説明します。

今後の記事では、手荷物係とスキャン、乗客がターミナルのキオスク (システムにアクセスが可能になっている簡易な建物を指す) を使用して荷物の正確な位置を知る方法、および乗客がリアルタイムの手荷物情報をワイアレスで入手するためのダウンロード可能なJ2MEアプリケーションを中心に取り上げます。

概要

私たちが取り上げる架空の航空会社J*Airは、困難な事態に陥っています。景気の減速のため、航空業界全体の業績が下降気味であり、J*Airはテクノロジーの面で業界大手企業に後れをとっているため、特に手痛い打撃を受けました。しかしJ*Airは、最新かつ最大のJavaテクノロジーおよびIBM製品を使用して、同社のシステムを全面的に整備し直すことを決断しました。システムの整備を行うためにIBMコンサルタントが呼ばれました。

刷新の第1段階は手荷物取扱システムです。乗客たちからは、手荷物の紛失について常に苦情が寄せられていますが、航空業界は何よりもサービス産業なのですから、なんとしてでも顧客の満足を得なければ生き残ることができません。J*Airは、乗客たちが本当に求めているもの (手荷物の位置情報をリアルタイムで更新すること) を提供できれば、早急に顧客を勝ち取り、彼らをリピーターにすることができると判断しています。同社は、空港ターミナルにキオスクを設置し、顧客がそのポイントからJ2ME対応の携帯電話またはPDAを使用して、自分の荷物が今どこにあるのかを即座に知ることができるようにしたいと考えています。

J*Airは、このような手荷物取扱システムの大改造を行い、きわめて使いやすく、付加価値の高い「BagTrac (荷物追跡)」キャンペーンを通じて顧客の注意を引き付け、顧客を維持できることを期待しています。




上に戻る


チェックイン

チェックイン時に乗客は、殺人事件の裁判における法廷速記者よりも猛スピードでチケット・エージェントがタイピングを行うのに見とれつつ、航空会社の「用心深い目」に荷物を預けます。チケット・エージェントは、BagTracシステムのステッカー印刷機能BagTrac Sticker Printerとやりとりします。BagTrac Sticker Printerは小型のアプリケーションで、エージェントがこのアプリケーションに名前、便名、荷物の個数を入力すると、固有の番号が印刷されたステッカーが発行されます。これで、荷物が旅路につき、乗客はそれをたどるために必要な情報を得られます。




上に戻る


アプリケーションの設定

BagTracに関連する各クライアント・サイド・アプリケーションは、その情報を共通のBagTracServletに送信します。BagTracServletは、渡された情報を使用して、データを適切なサーバー・サイド・アプリケーションに委任します。 図1 に示すように、サーバー・サイド・アプリケーションはデータベースにデータを送信し、その応答を、最初に呼び出しを行ったクライアント・サイド・アプリケーションに直接渡します。


図1. アプリケーションの一般的なセットアップ

クライアント・サイド

BagTrac Sticker Printerアプリケーションのクライアント・サイド部分は、データベースが必要とする乗客に関する情報を収集し、それをcom.jair.bagtrac.data.BagTracData というBeanにラップします。クライアント・サイドはModel View Controller (MVC) の原理に従ってパターン化されるため、ビューはモデルを収集してそれをコントローラーに渡します。この場合、下の図2 に示すように、コントローラーcom.jair.bagtrac.client.BagTracStickercom.jair.bagtrac.client.BagTracStickerView から情報を取得し、そのデータをサーブレットに中継します。チケット・エージェントは、BagTrac Sticker Printerと対話するときにこのようなビューを使用します。(理想的には、また、実世界のアプリケーションでは、このクライアント・サイド・アプリケーションを既存のチェックイン・システムにそのまま組み込みたいものです。しかし、そのためには航空券予約システムであるSABREシステムを書き直す必要があります。また、そのようにした場合、IBMのWebサイトに無料で掲載してもらえるでしょうか?)


図2. クライアント・サイド・アプリケーション

サーブレット

サーブレット・セットアップは、委譲(delegation) モデルに従って設計されています。すべての要求は同じサーブレットに送られます。サーブレットは、他の作業をどのサーバー・サイドが扱うのかを決定します。私たちのアプリケーションについては、将来必要になる機能を考慮してサーブレットを作成しなければなりません。したがって、サーブレットに対するそれぞれの要求ごとに、データをどのサーバー・サイドに中継するのかをサーブレットに指示するためのAPPコードを1つエンコードすることにします。

String app = req.getParameter(BagTracConstants.APP);
	int appNum = Integer.parseInt(app);
	switch (appNum)
	{
	   case BagTracConstants.STICKER_PRINT:
		...
	}

サーバー・サイド

乗客の荷物に関するすべての情報を保管するためのデータベースが必要です。私たちが使用するデータベースはもちろんDB2ですので、コマンド行で次のように入力します。

db2 => create db bagtrack

その後で、ユーザー名とパスワードを指定してデータベースに接続します。

db2 => connect to bagtrack user db2admin using db2admin

データベースに入るテーブルの1つに、乗客の名前、出発地の都市名、出発時刻、到着地の都市名、到着時刻、便名、および荷物タグの番号が保管されます。このテーブルでは、荷物タグは固有IDでなければなりません。

したがって、SQLでは次のようになります。

db2 => create table bagTable(name varchar(50) not null, departcity 
varchar(3) not null, departtime timestamp not null, arrivcity varchar(3) 
not null, arrivtime timestamp not null, flightnum decimal (4,0) not null, 
bagtag varchar(15) not null, primary key (bagtag))

com.jair.bagtrac.client.BagTracStickerpostToServlet メソッドにおけるURLオブジェクトの構造に注意してください。つまり、必要な情報 (乗客名、便名、およびチェックした荷物の数) を与えて、固有の荷物タグをつけ、また作成したデータベースに保管するように要求します。この情報はBagTracServlet によって処理されます。私たちが指定しているのはSTICKER_PRINTのAPPであるため、 BagTracData オブジェクトがインスタンス化されます。そして、calcBagTag メソッドがこのBagTracData オブジェクトを与えて呼び出されます。

荷物タグの一意性を確保するために、固有タグ番号の一部として現在日時の情報から得られたデータを使用します。この情報は便名と連結されます。そして、データベースにアクセスして、それぞれの荷物ごとに固有の荷物番号を取得します。

テーブル作成ステートメントで定義した基本キーは、 getUniqueBagNumber メソッド内でネストされた以下のSQL照会ロジックとともに、荷物タグの一意性を確保しています。

String strSQL = "select max(bagtag) from bagTable where bagtag in (select 
bagtag from bagTable where bagtag like '" + bagTagSoFar + "%')";

実際に複数の荷物タグがチェックインされる場合には、 calcBagTag メソッドが、複数の荷物タグ番号が戻されることを予期することに注意してください。したがって、これらのそれぞれの荷物タグは # 記号で区切られます。

荷物タグを印刷した後、荷物タグに関する情報をデータベースに保管する必要があります。その前に、出発地の都市、出発時刻、到着地の都市、到着時刻などの、フライト情報をflighttableと呼ばれるテーブルから入手しておく必要があります。flighttableは次のように定義されています。

db2 => create table flighttable (flightnum decimal (4,0) not null, 
departcity varchar(3) not null, departtime timestamp not null, arrivcity 
varchar(3) not null, arrivetime timestamp not null, primary key (flightnum))

フライトで運ばれる手荷物に関する荷物タグを作成するためには、該当のフライトが存在しなければなりません。次のサンプルinsertステートメントでは、便名1234が作成されます。

db2 => insert into flighttable values(1234,'DFW',
  '2002-09-06-07.35.00.000000','SJO','2002-09-06-09.40.00.000000')

flighttable情報は、 storebagtag メソッド内でbagtableに正しい挿入を行うために獲得されます。




上に戻る


バーコードとステッカー

ステッカー番号が得られましたので、次のステップではそれを印刷して、読み取り可能なバーコードを作成します。このアプリケーションでは、Code128バーコード規格を選択しました。市場で一般に使用されているバーコード規格は、15種類ほどあり、それぞれに長所と短所、および適した市場があります。Code128規格を選択したのは、コーディングが比較的簡単であり、0-9の数値とA-zの英字をエンコードできるためです。つまり、単純で強力な、理想のソリューションなのです。

物理的な印刷について掘り下げる前に、バーコード生成の舞台裏を覗いて見ることにしましょう。このシステムの設計者は、拡張性を確保しようと考えました。別のバーコード規格が業界標準になった場合に備え、最小限のコード変更によってバーコード規格を変更できるような枠組みを用意しておく必要があります。彼らがどのような設定を行ったのかを見てみましょう。

BarCode

BarCode クラスは、すべてのバーコード規格のスーパークラスとして機能する抽象クラスです。このクラスで、私たちは、どのようなバーコード規格を選択した場合にも共通して使用される、それぞれの変数と関数を定義します。

  • バーの高さ
  • バーの単位幅
  • 現行のxおよびy位置
  • エンコードされる数字をペイント (paint) するかどうか

このクラスには、サブクラスがそれ自体を描く方法を定義できるようにするabstract paint(Graphics g) 関数も含まれます。

Code128

Code128 クラスはBarCodeクラスのサブクラスであり、StringをCode128バーコード表示に変換するために必要なすべての情報を含んでいます。Code128構造 (および一般に使用されているその他の多くのバーコード形式) の詳細が記載されたサイトについては、 参考文献を参照してください。Code128の基本構造は、各文字が1、2、3、または4からなる6桁のコードで表されるようになっています。これらの数値は、バーの相対幅を表します。1番目、3番目、および5番目の数値は黒のバーに対応し、2番目、4番目、および6番目の数値は白のバーに対応します。バーコード・スキャナーに対して、Code128バーコードの読取開始を示す開始コード、およびコードが終了したことを示す終了コードが付与されています。Code128では、0-9の数字とA-zの文字 (およびその他のいくつかの文字) を使用して、128文字を表現することができます (Code128という名称は、このことに由来しています)。この形式はコーディングとアップグレードが容易なため、BagTrac用のバーコードとして妥当な選択でした。

BarCodePanel

BarCodePanel はJPanelのサブクラスであり、アプリケーションはこのサブクラスでバーコードを「ペイント」します。 BarCodePanel はユーザーに対して表示されることはありませんが、プリンターがピクセル情報を把握するためのキャンバスとして機能します。BarCodePanelは、そのpaintメソッドの中で、それぞれのCode128バーコードをどこに描くかを定義します。

   public void paint(Graphics g)
   {
     // clear the panel
     g.setColor(Color.white);
     g.fillRect(0, 0, getWidth(), getHeight());
	 // set the variables for the barcode to be printed
     barCode.setBarHeight((int)
       (PrintConstants.ONE_INCH * PrintConstants.BIG_BAR_HEIGHT_IN_INCHES));
     barCode.setBarUnitWidth(PrintConstants.BIG_BAR_WIDTH_IN_UNITS);
     barCode.setPaintNumber(false);
     barCode.paint(g, strBarcode, startX, startY);
   }

StickerPrint

printSticker() メソッドを調べると、これらのすべてのクラスが協力し合っていることが分かります。 printSticker() 関数はBarCodePanel を作成し、エンコードされるステッカー番号をそれに渡し、また、作成する必要のあるバーコードのタイプをBarCodePanel に渡します。

  BarCodePanel p = new BarCodePanel("01234567890123", new Code128());

上記の4つのクラスをセットアップすると、必要に応じて、印刷されるバーコード・ステッカーを簡単に切り替えることができます。例えば、J*Airが別のバーコード規格 (PostNetなど) に切り替えることを決定した場合、PostNetと呼ばれるBarCode の新規サブクラスを作成し、 StickerPrint.printSticker() 内のコードの行を次のように変更する必要があります。

  BarCodePanel p = new BarCodePanel("01234567890123", new PostNet());

また、設計者がバーコードを印刷する向きを変えた場合、 BarCodePanel クラスのpaintメソッドを変更して、希望するレイアウトでバーコードを表示するようにするだけでよいです。




上に戻る


印刷

バーコードが出来上がりましたので、今度はそれを用紙に物理的に印刷する必要があります。幸い、Java 1.2の印刷用APIは、完全ではないものの、BagTracシステムには十分です。BagTracの設計者、J*Airのマーケティング部門、および手荷物係たちの組合代表者による会合で、ステッカーの設定について以下のように合意されました。


ステッカーのレイアウト

手荷物にこの非常に大きなステッカーを付けて、手荷物係がスキャンすることにします。組合の代表者たちが、そのほうが見付けやすいと主張したためです。乗客に渡される小冊子には、それよりも小さなステッカーを添付します。これには、バーコードとステッカー番号の両方が表示されるため、乗客は、後で入力する際にバーコードあるいはステッカー番号のいずれかを使用することができます。

大きなステッカーは、左および上から1インチ (約2.5センチ) の位置にあり、縦と横がともに3インチ (約7.6センチ) になっています。バーの長さは3インチです。大きなステッカーと小さなステッカーの間には、3/4インチ (約1.9センチ) の余白があります。小さなステッカーは、縦が1インチで横が3インチです。J*Airは、製紙会社に、ステッカーを印刷するための用紙として、8 1/2インチ (約21.6センチ) x5インチ (約12.7センチ) のサイズのものを、入札により特注することで合意しました。それぞれのステッカーは、独自の用紙に印刷されます。

BarCodePanel.paint() 関数とPrintingConstants クラスを調べると、これらのすべての数値がどのように指定されているのかが分かります。Javaでは1インチ当たり72ピクセルで印刷されますので、BarCodePanelはこれを基に、上に示した寸法でバーコードを印刷します。

仕様が決まりましたので (もちろんこれは、わずか30分ほどのミーティングで決まりました)、次に行う必要があるのは、それを実際に印刷することです。 Printer クラスは、必要なすべての機能を備えています。

Printerクラス

Javaプログラム言語で印刷を行うためには複数のインターフェースと関数が必要ですが、そのすべてがPrinter クラスに統合されているため、印刷は簡単に行えるようになっています。Printerコンストラクターは印刷を行なうための引数としてComponentを受け入れます。このアプリケーションでは、印刷されるComponentとしてBarCodePanelを使用することにします。呼び出し元がprint() を呼び出し、その結果として得られたステッカーが印刷されます。

   BarCodePanel p = new BarCodePanel("01234567890123", new Code128());
   Printer printer = new Printer(p);
   printer.print();

PrintableインターフェースおよびPageableインターフェースはPrinter クラスに実装されています。印刷したいページ数が分かっていて、ページ形式がprint() メソッドで定義されているため、あとは、このクラスで両方のインターフェースを実装するだけで済みます。print() メソッドは次のように非常に単純なものになります。

   PrinterJob printerJob = PrinterJob.getPrinterJob();
   printerJob.setPrintable(this);
   printerJob.setCopies(1);
   printerJob.setPageable(this);
   try
   {
     printerJob.print();
   }
   catch (PrinterException e)
   {
     System.out.println("Printer error: " + e);
   }

これとは別に、コンポーネントのペイント方法をプリンターに指示するために、 print(Graphics, PageFormat, int) メソッドがPrintableインターフェースによって使用されます。このメソッドは、印刷のために使用されるGraphicsオブジェクトとGraphics2Dというオブジェクトを変換し、またBarCodePanel に、それ自体をプリンターにペイントさせます。簡単にいうと、プリンターはBarCodePanel に対して、そのペイント方法を問い合わせます。

Printer クラスにより、2つの完全なバーコードが印刷された用紙がページ上に正しく配置されます。




上に戻る


まとめ

J*Airは、BagTracシステムが、航空業界にテクノロジー面で革命をもたらす道のりの、最初のステップとなることを期待しています。(今私が使用している携帯電話のコンピューター集積回路が、巨大なジャンボ・ジェットを運行させている集積回路より高速でもよいじゃありませんか!)

この記事では、BagTracシステムが何を行おうとしているのか、また、全体的な設計の中で各パーツがどのような役割を果たすのかを理解していただくために、BagTracのアイデアと目標を紹介させていただきました。サーブレットの設計およびデータベースの設定を概説し、将来登場するパーツをどのように適合させられるのかを示しました。最後に、BagTracの最初のステップとして、バーコードを2つのステッカーに印刷しました。ステッカーのうちの一方は手荷物に添付され、もう一方は乗客に手渡されて、乗客が旅行中に自分の荷物を追跡できるようになります。




上に戻る


今後の予定

次回の記事では、荷物とともに旅行して、手荷物係とやりとりするのにお付き合いいただきましょう。手荷物係は、中央の装置に情報を送るワイヤレス・バーコード・スキャナーを使用してそれぞれの荷物をスキャンします。この装置は、スキャンされた情報をサーブレットに中継します。この記事では、DB2を実行するWebSphere Application Serverとクライアント/サーバーを介して通信し、スキャンするごとにレコードを更新する、クライアント・サイドのバーコード・スキャナー・マネージャーに焦点を当てます。この記事ではまた、バーコード・スキャナーを処理するためのJavaアーキテクチャーを紹介します。

別の記事で、乗客に焦点を当てます。ターミナルには、キオスクが設置され、そこにはキーボードとスキャナーが用意されています。キオスクで実行されるアプリケーションは、いずれかの入力装置を介してサーブレットおよびDB2と連絡し、荷物の現在位置を入手します。

さらに別の記事で、乗客が使用可能なJ2MEアプリケーションをダウンロードできるようにします。このアプリケーションを使用すると、Java対応の携帯電話のユーザーは、自分のコードを入力してリアルタイムの手荷物情報をワイアレスで検索することができます。





上に戻る


ダウンロード

ファイル名サイズダウンロード形式
i-jair1.jar13.2KBHTTP
ダウンロード形式について


参考文献



著者について

Michael Abernethyは、テキサス州オースティンで、IBMのJavaコンサルタントとして勤務しています。


Kulvir Singh Bhogal

Kulvir Singh Bhogalは、IBMのコンサルタントとして勤務し、世界各地のカスタマー・サイトでJava中心のソリューションを考案し、実装しています。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ