このチュートリアルの対象は、Hibernate などのパーシスタンス・フレームワークを利用する、データベース駆動の Web サービスを使用するアプリケーションの開発者です。Web サービスを使用することで、アプリケーションの機能やメッセージを世界に公開することができます。Web サービスは XML を使用してデータのコード化およびコード化解除を行い、SOAP を使用して (オープンなプロトコルによって) そのデータを伝送します。Web の世界では、SOAP に代わる単純な選択肢として、REST (REpresentational State Transfer) が広く受け入れられるようになりました。REST はステートレスなクライアント・サーバー・アーキテクチャーを特徴とする重要な設計方式です。REST では、Web サービスはリソースとみなされ、URL によって Web サービスが特定されます。
このチュートリアルでは、Web サービス (JAX-WS Web サービスと REST Web サービス) の作成方法について説明します。Web サービスの実装には、SOAP、XML、JSON、Restful HTTPなど、さまざまなアプリケーション・プロトコルを使用することができ、また Web サービスは HTTP や JMS (Java Message Service) など、さまざまなトランスポート・プロコトルをサポートしています。このチュートリアルでは、Hibernate を使用するデータベース駆動の情報取得 Web サービスを作成し、続いて Hello User という RESTful な Web サービスを作成して Google クラウド (GAE) にデプロイする方法を説明します。最後に、作成した Web サービスをモバイル・クライアント (J2ME と Android) で利用する方法について説明します。
このチュートリアルでは、以下の方法について学びます。
- ORM フレームワークとして Hibernate を使用し、DB2 データベースを操作する JAX-WS Web サービスを作成およびデプロイする方法
- 単純な RESTful Web サービスを作成し、クラウド (GAE) にデプロイする方法
- Android クライアントと J2ME クライアントを使用して上記の 2 つの Web サービスを呼び出す方法
このチュートリアルでは、Eclipse IDE の基本的な概念を理解していること、また Web サービスのアーキテクチャーの基本を理解していることを前提とします。詳しくは「参考文献」を参照してください。
Web サービスは、ネットワークを介してアプリケーションの機能にアクセスするためのインターフェースであり、標準的なインターネット技術を使用して作成されます。Web サービスは、XML ベースのさまざまな言語を使用してリモート・アクセスされるソフトウェア・アプリケーションでもあり、他の Web サイトと同様、通常は URL によって特定されます。Web サービスと通常の Web サイトとでは、クライアントとの間で行われるやりとりが異なります。
Web サービスは非常によく知られたオープンな技術標準であり、以下のようなメリットがあります。
- ベンダー間の競争が促進されるため、製品コストが低くなります。
- ある製品から別の製品へ切り替えるのが容易なため、トレーニング・コストが低くなります。
- パーティー同士の相互運用性が高くなるため、保守費用が安くなります。
- ある 1 つの標準が広く採用され、長く使用されるようになります。膨大な数のベンダーやユーザーに使用されるため、幅広く受け入れられるようになります。
組織が Web サービスに移行する場合、主に以下の 3 つの方法があります。
- 新しい Web サービスをゼロから作成する (コントラクト・ファースト): 開発者は Web サービスの機能を作成し、それらのサービスを記述するドキュメントも用意します。
- Web サービスを利用して既存の機能を公開する (コード・ファースト): この場合はサービスの機能が既に存在しているため、あとはサービスについて記述するのみです。
- 他のベンダーやビジネス・パートナーの Web サービスを統合する (中間的な方法): ゼロから作成するよりも、他の誰かが実装したサービスを使用した方が適切な場合があります。そうした場合、組織は他の誰かの Web サービスや、さらにはビジネス・パートナーの Web サービスでさえ統合する必要があります。
Web サービスの概念の真価が発揮されるのは 2 番目と 3 番目の方法の場合です。この 2 つの方法では、他の Web サービスやアプリケーションを既存のアプリケーションに使用することができます。
SOA と Web サービスは別のものですが、SOA を実現するための標準ベースの望ましい方法が Web サービスになります。SOA (Service Oriented Architecture) は、Web などのネットワーク上で利用可能なサービスを使用するソフトウェア・アプリケーションを作成するためのアーキテクチャー・スタイルです。SOA ではソフトウェア・コンポーネント間の疎結合が促進されるため、ソフトウェア・コンポーネントを再利用できるようになります。SOA のアプリケーションはサービスをベースにして作成されます。サービスは適切に定義されたビジネス機能を実装したものであり、さまざまなアプリケーションやビジネス・プロセスにおけるクライアントで、それらのサービスを利用することができます。
SOA では疎結合が促進されるため、当然、既存の資産を再利用できるようになり、システムの既存の IT インフラストラクチャーから新しいサービスを作成することができるようになります。言い換えると、SOA によって既存のアプリケーションを再利用できるようになるため、企業はこれまでに行った投資を活用できるようになります。また SOA によって、異種混成のアプリケーションや技術の間の相互運用性が約束され、さらにはこれまで不可能であったレベルの柔軟性を実現できるようになります。例えば以下のような柔軟性を実現することができます。
- サービスは、適切に定義されたインターフェースを持ち、実装に依存しないソフトウェア・コンポーネントです。SOA の重要な側面として、サービス・インターフェース (目的) をインターフェースの実装 (手段) から分離することができます。それらのサービスを利用するクライアントは、それらのサービスが彼らのリクエストをどう実行するかによって影響を受けることはありません。
- サービスは自己完結であり (あらかじめ定義されたタスクを実行し)、疎結合です (独立しています)。
- サービスを動的に発見することができます。
- 他のサービスを集約することで複合サービスを作成することができます。
SOA では、「検索 ― バインド ― 実行」というパラダイムを用います。このパラダイムでは、サービス・プロバイダーは公開されているレジストリーにサービスを登録します。コンシューマーはこのレジストリーを使用し、特定の基準を満たすサービスを検索します。該当のサービスがレジストリーに登録されている場合には、レジストリーはコンシューマーに対し、そのサービスに対する契約とエンドポイント・アドレスを提供します。
SOA ベースのアプリケーションは分散型の多層アプリケーションであり、このアプリケーションにはプレゼンテーション層、ビジネス・ロジック層、パーシスタンス層があります。サービスは SOA アプリケーションのビルディング・ブロックで構成されます。どのような機能もサービスとして作成することは可能ですが、適切な抽象化レベルでサービス・インターフェースを定義することは簡単ではありません。サービスが提供する機能は、粒度の大きいものでなければなりません。
Web サービスは、ネットワークを介してマシン同士が相互運用可能な形でやり取りできるように設計されたソフトウェア・システムです。この相互運用性は、WSDL、SOAP、UDDI など、XML ベースの一連のオープンな標準によって実現されます。
Web サービスを使用する主なメリットの 1 つが相互運用性をもたらしてくれることであるため、SOA の最も重要な基本的性質である相互運用性を実現するには Web サービスを使用します。相互運用性が実現されると、さまざまな分散型 Web サービスを多様なソフトウェア・プラットフォームやハードウェア・アーキテクチャー上で実行できるようになります。また Web サービスと SOA の登場によって、統合コストの低減や柔軟性の向上を期待できるようになっています。SOA が持つ重要な特徴の 1 つに、サービス・インターフェース (目的) がそのサービスの実装 (手段) とは切り離されているということがあります。このため、それらのサービスを利用するクライアントは、サービスがクライアントからのリクエストをどう実行するかによって影響を受けることはありません。Web サービスによって、インターネットを介した B2B の関係を自動化するためのインフラストラクチャーとツールが約束されるため、Web サービスは Web の進化における次のステップであると言えます。
Web サービスを作成することが流行だとするなら、Web サービスを作成する方法として、REST は明らかに流行の方法です (現実では、皆さんは石鹸 (SOAP) を使用して手を洗い、疲れた時には休みます (REST))。REST Web サービスの主なメリットは以下のとおりです。
- 軽量であり、余分な大量の XML マークアップはありません。
- 結果を人間が読み取れます。
- 作成が容易であり、ツールキットは必要ありません。
SOAP にも以下のようにメリットがいくつかあります。
- 容易に利用できる場合があります。
- 型チェックは厳密であり、厳密に契約に従います。
- 開発ツールがあります。
Web サービスを利用する場合、REST と SOAP のどちらが容易か、判断しにくい場合があります。例えば、SOAP を使用する Google のアドワーズ Web サービスは、SOAP ヘッダーを使用していることに加え、サービスの利用を難しくしている要素が他にもいくつもあるため、利用するのが実に難しいサービスです。一方、REST を使用する Amazon の REST Web サービスは非常に深くネストされていて構文解析が厄介な場合があり、また検索の対象により、結果のスキーマが大幅に変わる場合があります。
もちろん、SOA を実践しなくてもクラウドを活用することは可能であり、またクラウド・コンピューティングを活用しなくても SOA を活用することは可能ですが、クラウド・コンピューティングの真価は、ファイアウォールの外にある、他の誰かのデータセンターに存在するサービス、データ、プロセスを利用できる点にあります。実際、クラウド・コンピューティングを SOA の拡張機能として考えることができます。つまり、SaaS (Storage as a Service)、DaaS (Data as a Service)、PaaS (Platform as a Service) など、クラウドによって提供されるリソースにまで SOA が拡張されるのです。ポイントは、どのサービス、どの情報、そしてどのプロセスがクラウドに常駐させるのに適しているかを判断し、どのクラウド・サービスを既存の SOA または新たな SOA の中に抽象化する必要があるかを判断することです。SOA は再利用とアジリティーを促進するメカニズムであるだけではなく、何をローカルにとどめる必要があり、何をクラウドに配置する必要があるかを判断するための機能も備えています。適切な SOA を用いることによってクラウド・コンピューティングのための優れた戦略が導かれ、その結果、エンタープライズ・コンピューティングに関してこれまで以上のコストの削減、アジリティーの強化、そしてより一層画期的なことが実現されます。
クラウド・コンピューティングの活用によって SOA にもたらされるもの
サービスの設計: 多くの SOA プロジェクトにおいて、粒度が大きすぎるサービス、粒度が小さすぎるサービス、あるいはまったく適切に設計されていないサービスが作成される傾向があります。実際には、サービスが適切に定義され、適切に設計されていない限り、需要に基づいて提供されたサービスも売上げには結びつきません。クラウドを通じてサービスを提供する主なクラウド・コンピューティング・プロバイダーは、ユーザビリティーや永続性を含め、サービスの設計に多くの時間を費やしています。
サービスの拡張性: クラウド・コンピューティング・サービスは必要に応じて拡張できるように設計されています。またユーザーがクラウド・サービスを利用する理由は、必要なときにオンデマンドでサービスを利用できるからです。
Google App Engineを利用すると、Google のインフラストラクチャー上で Web アプリケーションを実行することができます。Google App Engine には開発コミュニティーとエンタープライズ・コンピューティング・スペースの両方が用意されています。App Engine アプリケーションは作成が容易であり、また保守も容易です。
App Engine を利用することにより、Google が使用しているのと同じインフラストラクチャー上でスケーラブルなエンタープライズ・アプリケーションを作成することができます。
App Engine の構造は通常の Web アプリケーション・サーバーとは異なります。App Engine のコアの部分では、アプリケーションは App Engine の物理インフラストラクチャーにアクセスすることができず、ソケットを開く、バックグラウンド・プロセスを実行する (バックグラウンド・プロセスは実行できませんが、cron を使用することはできます)、そしてその他の一般的なバックエンド・ルーチンを使用するといった、アプリケーション開発者が他の環境ではできて当然と考えることができません。
App Engine を使い始めるために費用はかかりません。すべてのアプリケーションは最大 500 MB のストレージと十分な CPU および帯域幅の能力を使用することができます。そのため、月間約 500 万ページ・ビューに対応できる効率的なアプリケーションを完全に無料でサポートすることができます。アプリケーションへの課金を有効にすると、無料で使用可能な範囲が引き上げられ、ユーザーは無料の範囲を超えて使用したリソースに対してのみ支払うことになります。
例 1: Hibernate を使用する情報取得 Web サービス
Web サービスは、プラットフォームやプログラミング言語に依存せずにアプリケーション同士が通信を行える技術です。Web サービスは一連の操作を記述したソフトウェア・インターフェースであり、標準化された XML メッセージングを利用して、ネットワーク経由でそれらの操作を利用することができます。Web サービスは XML 言語をベースとするプロトコルを使用して実行対象の操作を記述し、あるいは他の Web サービスと交換するデータを記述します。
ここでは、ORM フレームワークとして Hibernate を使用して、基本的にデータベース (この場合は DB2) の操作を行う Web サービスを作成します。先ほど触れたように、Web サービスは本質的に疎結合であるため、ここでは Android クライアントと (JSR-172 をサポートしない) J2ME クライアントを使用して、この Web サービスを呼び出します。
これは Hibernate とコード・ファースト手法を使用して情報を取得する単純なデータベース駆動型 Web サービスであり、ユーザーが従業員 ID を入力すると、その従業員の情報 (つまり、名前、住所、生年月日、契約番号) を取得することができます。このサンプル Web サービスをセットアップして実行するためには、以下の事項に関して理解している必要があります。
Eclipse IDE: 統合開発環境 (IDE) は、コンピューター・プログラムを作成、編集、コンパイル、実行するためのすべてを備えたツールです。そして Eclipse は優れた統合開発環境です。Eclipse の最新リリースは www.eclipse.org から入手することができます。
Eclipse WTP (Web Tools Platform): Eclipse WTP (Web Tools Platform) は、Eclipse プロジェクトによって作成されたソフトウェアと、他のオープンソース・プロジェクトによるサードパーティー・ソフトウェアとの組み合わせによって構成されています。これらのプラグインによって、J2EE ベースのアプリケーション開発を容易に行える環境が設定されます。このプラグインの zip 圧縮版は http://www.eclipse.org/webtools/ からダウンロードすることができます。このプラグインを Eclipse のディレクトリー (Eclipse IDE をダウンロードして解凍したディレクトリー) に解凍し、Eclipse IDE を再起動します。
Websphere Application Server Community Edition 2.1.1 (WASCE): IBM WebSphere Application Server Community Edition (以下、Community Edition とします) は IBM WebSphere Application Server ファミリーの 1 つです。Community Edition は軽量の Java EE (Java Platform Enterprise Edition) アプリケーション・サーバーであり、Apache Software Foundation によるオープンソースのアプリケーション・サーバー・プロジェクト Apache Geronimo の上に構築されています。Community Edition を使用するコミュニティーは、Java EE ソリューションを設計、開発、デプロイ、利用する多種多様な人々や企業で構成されています。Community Edition の最新バージョンは http://www.ibm.com/developerworks/downloads/ws/wasce/ から入手することができます。
WASCE と WEP (Eclipse プラグイン): Eclipse 内で Community Edition を操作するためには、WEP (WebSphere Application Server Community Edition Eclipse Plug-in) をインストールする必要があります。WEP は Community Edition を使用する Web アプリケーションを Eclipse で開発するのを容易にするためのアダプターです。WEP の zip 版は http://download.boulder.ibm.com/ibmdl/pub/software/websphere/wasce/updates/ からダウンロードすることができます。このプラグインを Eclipse のディレクトリー (Eclipse IDE をダウンロードして解凍したディレクトリー) に解凍し、Eclipse を再起動します。
Hibernate: Hibernate は Java 言語のためのオープンソースのオブジェクト (リレーショナル) マッピング・ライブラリーであり、データの処理方法とは無関係に、永続的なクラスとロジックを提供することができます。Hibernate は直接的で永続的なリレーショナル・データベース・アクセスを上位レベルのオブジェクト処理関数で置き換えることにより、オブジェクトとリレーショナルの「インピーダンス不整合」を解決します。Hibernate は http://www.hibernate.org/downloads からダウンロードすることができます。
DB2 Express C: DB2 Express-C データ・サーバー・ソフトウェア (以下、DB2 Express-C とします) は IBM DB2 ファミリーの強力なデータ・サーバー・ソフトウェアの 1 つであり、リレーショナル・データと XML データの両方を管理することができます。DB2 Express-C は DB2 の無料版であり、使用制限がなく、容易に使用することができます。DB2 Express-C の C は Community (コミュニティー) を意味します。DB2 Express-C は www.ibm.com/db2/express/download.html からダウンロードすることができます。
環境を設定する
- JDK 1.5 またはそれ以降をシステムにインストールします。
- 必要な WTP プラグインと WEP プラグインをデプロイした後、Eclipse を起動します。
- WASCE 2.1.1 をインストールします。
- WEP を使用して Eclipse で WASCE にリンクし、WASCE を起動します。
- DB2 Express-C をインストールします。
- 以下のリストに従ってテーブルを作成します。
CREATE TABLE "ADMINISTRATOR"."USER_INFO" ("USER_ID" VARCHAR(10) NOT NULL ,"ADDRESS" VARCHAR(50) NOT NULL ,"DATE_OF_BIRTH" DATE NOT NULL ,"CONTACT_NO" VARCHAR(12) NOT NULL ) ;
ADMINISTRATOR テーブル
情報取得 Web サービスを作成し、WASCE にデプロイする
- UserInfo という動的 Web プロジェクトを新規に作成します (ターゲット・ランタイム環境として WASCE 2.1.1 を選択します)。
- WEB-INF/lib ディレクトリーに以下の jar ファイルを追加します。
antlr-2.7.4.jar
cglib-full-2.0.2.jar
commons-collections-2.1.1.jar
dom4j-1.5.2.jar
ehcache-1.1.jar
hibernate3.jar
jta.jar
log4j-1.2.9.jar
さらに、DB2 データベース・サーバーに接続するために、..\IBM\SQLLIB\java\ ディレクトリーにある以下の jar および zip ファイルを追加します。
db2java.zip
db2jcc4.jar
sqlj4.zip
また、WebContent/WEB-INF ディレクトリーに commons-logging-1.0.4.jar を追加し、プロジェクトのビルド・パスにも commons-logging-1.0.4.jar を追加します。
以下の図は、このプロジェクトの構造を示しています。
UserInfo プロジェクトのディレクトリー構造
- 永続クラスとなる Java Bean クラス UserBean.java を com.ibm.model パッケージの下に作成します (リスト 1 を参照)。
リスト 1. UserBean.java
package com.ibm.model;
import java.util.Date;
public class UserBean {
String ID;
String Address;
Date DOB;
String ContactNo;
public String getID() {
return ID;
}
public void setID(String iD) {
ID = iD;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public Date getDOB() {
return DOB;
}
public void setDOB(Date dOB) {
DOB = dOB;
}
public String getContactNo() {
return ContactNo;
}
public void setContactNo(String contactNo) {
ContactNo = contactNo;
}
}
|
- サービス・エンドポイント・インターフェースとして動作する UserSEI.java というインターフェースを com.ibm.service パッケージの下に作成します (リスト 2 を参照)。
リスト 2. UserSEI.java
package com.ibm.service;
import javax.jws.WebService;
@WebService (name="UserSEI",
targetNamespace="http://service.ibm.com")
public interface UserSEI {
public String getInfo(String user_Id);
}
|
- メインのロジックを含むサービス実装クラス UserServiceImpl.java を作成します。このクラスに @WebService アノテーションを追加し、以下のパラメーターを指定します。
serviceName: サービスの名前 (クライアントに対するスタブを作成する際、この名前を持つクラスが作成されます)。
portName: エンド・ポート (portName を取得するメソッドがスタブ・クラスに作成されます)。
endpointInterface: サービスに対するエンドポイントとして機能するインターフェース・クラス (この場合は UserSEI.java クラス)。
targetNamespace: デプロイ後の Web サービスに対する名前空間。
- UserServiceImpl.java クラスの中で getInfo というメソッドを作成します。このメソッドは従業員情報を含むストリングを返し、ストリング入力 (従業員 ID) を引数に取ります (リスト 3 を参照)。
リスト 3. UserServiceImpl.java
package com.ibm.service;
import java.util.Iterator;
import java.util.List;
import javax.jws.WebService;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.ibm.model.*;
@WebService(serviceName = "HiberService",
portName = "HiberPort",
endpointInterface = "com.ibm.service.UserSEI",
targetNamespace = "http://service.ibm.com")
public class UserImpl implements UserSEI{
public String getInfo(String user_Id){
String s="";
Session session = null;
// Create a new sessionFactory object
SessionFactory sessionFactory = new Configuration().
configure().buildSessionFactory();
session =sessionFactory.openSession();
//Build the prepared query
Query query = session.createQuery("from UserBean use where use.ID =:ID" ).
setString("ID",user_Id);
List result = query.list();
Iterator it = result.iterator();
while(it.hasNext()){
UserBean user = (UserBean)it.next();
s="USER ID :"+user.getID()+ " , ADDRESS :" +user.getAddress()+ " , DATE OF BIRTH
:"+user.getDOB()+ " , CONTACT NO : " +user.getContactNo() ;
}
session.close();
if(!s.equals("")){
return s;
}
else{
return "No Data Found";
}
}
}
|
- src フォルダーを右クリックして「New (新規)」 > 「File (ファイル)」の順に選択し、hibernate.cfg.xml というファイルを作成します。このファイルにはデータベースの構成が含まれています (リスト 4 を参照)。
リスト 4. hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
<property name="hibernate.connection.url">jdbc:db2://localhost:50000/USER</property>
<property name="hibernate.connection.username">ADMINISTRATOR</property>
<property name="hibernate.connection.password">server</property>
<property name="hibernate.connection.pool_size">10</property>
<property name="hibernate.default_schema">ADMINISTRATOR</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="hibernate.hbm2ddl.auto">read</property>
<!-- Mapping files -->
<mapping resource="UserBean.hbm.xml"/>
</session-factory>
</hibernate-configuration>
|
- 再度 src フォルダーを右クリックして「New (新規)」 > 「File (ファイル)」の順に選択し、マッピング情報を提供する UserBean.hbm.xml という別のファイルを作成します。このファイルによって UserBean.java クラスが DB2 データベースの UserInfo テーブルにマッピングされます (リスト 5 を参照)。
リスト 5. hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.ibm.model.UserBean" table="USER_INFO">
<id name="ID" column="USER_ID" >
<generator class="assigned"/>
</id>
<property name="Address" type="string">
<column name="ADDRESS"/>
</property>
<property name="DOB" type="date">
<column name="DATE_OF_BIRTH"/>
</property>
<property name="ContactNo" type="string">
<column name="CONTACT_NO"/>
</property>
</class>
</hibernate-mapping>
|
- リスト 6 のように web.xml ファイルを編集します。
リスト 6. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>UserInfo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>user</servlet-name>
<servlet-class>com.ibm.service.UserImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>user</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
</web-app>
|
- リスト 7 のように geronimo-web.xml ファイルを編集し、WASCE に対するデプロイメント・プランを作成します。
リスト 7. geronimo-web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web:web-app xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0"
xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0"
xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"
xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"
xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2"
xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0"
xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2"
xmlns:pers="http://java.sun.com/xml/ns/persistence"
xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1"
xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0"
xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<dep:environment>
<dep:moduleId>
<dep:groupId>default</dep:groupId>
<dep:artifactId>UserInfo</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
</dep:environment>
<web:context-root>/UserInfo</web:context-root>
</web:web-app>
|
プロジェクトを選択して右クリックし、「Run As (実行)」 > 「Run on Server (WASCE) (サーバーで実行 (WASCE))」の順に選択します。URL (http://localhost:8080/UserInfo/user) を入力し、サービスが適切にサーバーにデプロイされたかどうかをチェックします (下図参照)。
サーバーにデプロイされたサービス
Web サービスの WSDL の場所、http://localhost:8080/UserInfo/user?WSDL をチェックします (下図参照)。
WSDL の場所
情報取得サービスに対する J2ME クライアントを作成する
Web サービスを使用する (JSR-172 標準をサポートしない) J2ME クライアントを作成するためには、以下のソフトウェア・コンポーネントが必要です。
- Sun Java Wireless Toolkit3.0 ― J2ME エミュレーターをダウンロードしてください。
- KSoap2-j2me ライブラリー ― ksoap2-j2me-core-2.1.2-jar をダウンロードしてください。
- J2ME エミュレーターで User という J2ME プロジェクトを作成します。
- プロジェクトの resource フォルダーに ksoap2-j2me-core-2.1.2 jar を追加します。
J2ME プロジェクトの構造
- com.ibm.j2me.client パッケージの下に J2meNonJSR172Client.java という Midlet を作成します (リスト 8 を参照)。
リスト 8. J2meNonJSR172Client.java
package com.ibm.j2me.client;
import javax.microedition.midlet.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import javax.microedition.io.*;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.*;
import org.ksoap2.serialization.PropertyInfo;
public class J2meKsoapClient extends MIDlet implements CommandListener {
private Form firstScreen;
private Display display;
private TextField id = new TextField("Enter User ID :", "1002", 30, TextField.ANY);
StringItem resultItem=new StringItem("","");
// Navigation commands
private static final Command EXIT_COMMAND =new Command("Exit", Command.EXIT, 1);
private static final Command SEND =new Command("SEND", Command.OK, 1);
public J2meKsoapClient() {
initFirstScreen();
}
private void initFirstScreen() {
firstScreen = new Form("Information Retrieval ");
StringItem item = new StringItem(""," ");
firstScreen.append(item);
firstScreen.append(id);
firstScreen.addCommand(SEND);
firstScreen.setCommandListener(this);
}
public void startApp() {
// The initial display is the first form
display=Display.getDisplay(this);
display.setCurrent(firstScreen);
}
public void pauseApp() {
// No implementation required
}
public void destroyApp(boolean unconditional) {
// No implementation required
}
public void commandAction(Command command, Displayable displayable) {
if (command == EXIT_COMMAND) {
// Exit the MIDlet
notifyDestroyed();
}
else if(command == SEND) {
soapCall() ;
}
}
public void soapCall() {
try{
SoapObject rpc = new SoapObject("http://service.ibm.com","getInfo");
PropertyInfo propInfo1=new PropertyInfo();
propInfo1.name="arg0";
propInfo1.type=PropertyInfo.STRING_CLASS;
rpc.addProperty(propInfo1,id.getString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(rpc);
HttpTransport ht = new HttpTransport("http://192.168.1.5:8080/UserInfo/user");
ht.call("http://service.ibm.com/getInfo",envelope);
SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
resultItem.setText(resultsRequestSOAP.toString());
firstScreen.append(resultItem);
}
catch (Exception e){
System.out.println("Exception : "+ e.getMessage());
e.printStackTrace();
}
}
}
|
- 今度はプロジェクトをビルドして実行します。
- 従業員 ID を入力して「Send (送信)」ボタンをクリックすると、求める情報が得られます。下図のような出力が表示されるはずです。
J2ME エミュレーターの出力画面
注: JSR-172 準拠の携帯電話で (スタブを使用して) Web サービスを呼び出す方法については、別のチュートリアルを参照してください。
情報取得サービスに対する Android クライアントを作成する
Web サービスに対する Android クライアントを作成するためには、以下のソフトウェア・コンポーネントが必要です。
- Eclipse IDE
- Android SDK
- Eclipse の ADT プラグイン
- ksoap2-android ライブラリー ― ksoap2-android-assembly-2.4-jar をダウンロードしてください。
- AndroidClient という名前の Android プロジェクトを作成します (下図参照)。
Eclipse で新規の Android プロジェクトを作成する
- プロジェクトのビルド・パスに ksoap2-android-assembly-2.4-jar を追加します (下図参照)。
ksoap2-android-assembly-2.4-jar ディレクトリー
- com.ibm.android.client パッケージの下に AndroidWSClient というクラスを作成します (リスト 9 を参照)。
リスト 9. AndroidWSClient.java
package com.ibm.android.client;
// ksoap-android library imports
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.ksoap2.serialization.PropertyInfo;
// Android imports
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
public class AndroidWSClient extends Activity {
// Declaring web service WSDL,Namespace,Method
private static final String NAMESPACE = "http://service.ibm.com";
private static String URL = "http://192.168.1.5:8080/UserInfo/user";
private static final String METHOD_NAME = "getInfo";
private static final String SOAP_ACTION = "http://service.ibm.com/getInfo";
private TextView lblResult;
private EditText text;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (EditText) findViewById(R.id.editText);
lblResult = (TextView) findViewById(R.id.result);
final Button button = (Button) findViewById(R.id.buttons);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
PropertyInfo propInfo=new PropertyInfo();
propInfo.name="arg0";
propInfo.type=PropertyInfo.STRING_CLASS;
request.addProperty(propInfo, text.getText().toString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
lblResult.setText(resultsRequestSOAP.toString());
} catch (Exception e) {
System.out.println();
}
}
});
}
}
|
- res/layout フォルダーの下にある main.xml ファイルを編集します (リスト 10 を参照)。
リスト 10. main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
/>
<EditText android:layout_height="wrap_content" android:text="Enter Employee ID"
android:id="@+id/editText" android:layout_width="wrap_content"></EditText>
<Button android:text="SEND" android:id="@+id/buttons" android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
</LinearLayout>
|
- AndroidManifest.xml ファイルに以下の uses-permission を追加します (リスト 11 を参照)。
リスト 11. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ibm.android.client"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidWSClient"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
</manifest>
|
- Android アプリケーションとして実行します (下図参照)。
Android プロジェクトを実行する
Android エミュレーターとアクティビティーが起動されると、コンソールには以下のような出力が表示されるはずです (下図参照)。
Android コンソールへの出力
- 情報と詳細の取得対象である従業員の従業員 ID を入力します。
Android を呼び出した場合のプレビュー
このチュートリアルでは一例として、データベースの中にある従業員 ID 「1002」を入力します。そして「SEND (送信)」ボタンをクリックすると、先ほど作成した Web サービスからのレスポンスとして、その従業員の情報を取得することができます (下図参照)。
Android でサービスを呼び出した場合のレスポンスのプレビュー
例 2: RESTful な Web サービス「Hello User」を作成し、Google App Engine にデプロイする
RESTful なサービスを作成する上で、プロトタイピングと公開を短時間で行えると非常に便利です。またサービスの作成中に、コンシューマーがそのサービスにアクセスして試せることは不可欠です。GAE (Google App Engine) プラットフォームは入門レベルでは無料であり、パブリック URI を持つ RESTful なアプリケーションをデプロイする上では十分な機能を備えています。
ここでは、非常に単純にパラメーター化した「Hello User」という RESTful な Web サービスを Jersey を使用して作成し、そのサービスを Google クラウドにデプロイします。この Web サービスでは、ユーザーが名前を入力すると、それを歓迎するメッセージが表示されます。このサンプル Web サービスをセットアップして実行するためには、以下の事項を理解している必要があります。
環境設定
- https://appengine.google.com から無料の GAE アカウントを取得します (下図参照)。
Google App Engine のプレビュー
- App Engine のページの「My Applications (マイ アプリケーション)」ビューで新しいアプリケーション ID を作成します (下図参照)。
Google App Engine の「My Applications (マイ アプリケーション)」のプレビュー
- Google App 用の Eclipse プラグインをインストールします。
- JAXB 2.1 をダウンロードし (GAE は現在 JAXB 2.2 をサポートしていないことに注意してください)、そのファイルを解凍し、UNIX
ベースのシステムの場合には下記コマンドを実行します。
java -jar JAXB2_20081030.jar - JAX-RS リファレンス実装 (jersey) をダウンロードして解凍します。
RESTful なアプリケーションを Google クラウド (GAE) で開発し、デプロイする
- Eclipse で「RestCloudComputing」という新規の Web アプリケーション・プロジェクトを作成します (「File (ファイル)」 > 「New (新規)」 > 「Project (プロジェクト)」の順に選択し、表示される画面で「Google」 > 「Web Application Project (Web アプリケーション・プロジェクト)」の順に選択し、「Next (次へ)」をクリックします)。「New Web Application Project (新規 Web アプリケーション・プロジェクト)」画面で「Use Google Web Toolkit (Google Web ツールキットを使用)」のチェックは外します (下図参照)。
Google App Engine の新規プロジェクト
- JAXB と JAX-RS の jar をこの Eclipse プロジェクト内の /war/WEB-INF/lib の下に配置します (下図参照)。
GAE プロジェクトの jar
- また、このプロジェクトの「Java Build Path (Java ビルド・パス)」にそれらの jar を追加します (下図参照)。
ビルド・パスに追加する
- com.ibm.rest パッケージの下に TestRestService.java という RESTful なクラスを作成します (リスト 12 を参照)。
リスト 12. TestRestService.java
package com.ibm.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@Path("/testuser/{Username}")
public class TestRestService {
@GET
@Produces("text/plain")
public String getWelcome(@PathParam("Username")String user) {
return "Welcome "+ user +" to DeveloperWorks!";
}
}
|
- リスト 13 のように web.xml を更新します。
リスト 13. web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet><servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.ibm</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
|
- GAE プラグインによってインストールされたツールバーで、「Deploy App Engine Project (App Engine プロジェクトのデプロイ)」アイコンをクリックし、Eclipse から App Engine をデプロイします (ツールバーを使わずにメニューから選択する方法は下図を参照)。
アプリケーションをクラウドにデプロイする
- アプリケーションを Google クラウド (GAE) にデプロイするために、GAE にサインアップする際に作成した Google アカウント (E メール・アドレスとパスワード) を使用して Google クラウド (GAE) にログインします (下図参照)。
GAE にログインする
- 「App Engine project settings (App Engine プロジェクトの設定)」リンクをクリックし、先ほど作成した「Application ID (アプリケーション ID)」を入力します (下図参照)。
アプリケーション ID とバージョン番号を設定する
- デプロイメントが成功すると、コンソールには下図のような出力が表示されるはずです。
GAE の出力コンソール
これが終わると、URL http://restingae.appspot.com にアクセスしてアプリケーションをチェックすることができます。
Web クライアント (つまりブラウザー) から、RESTful な Web サービスをテストする (つまり呼び出す) ことができます。そのためには下図のように単純に http://restingae.appspot.com/rest/testuser/Kuntal というリンクにアクセスします (ここでは私の名前の Kuntal を使用していますが、実際には皆さんの名前を使用します)。
ブラウザーの URL 欄を使用して REST サービスをテストする
Restful な Web サービス「Hello User」に対する Android クライアントを作成する
- AndroidRSClient という Android プロジェクトを作成します。
- com.ibm.android.rest.client パッケージの下に AndroidRestClient というクラスを作成します (リスト 14 を参照)。
リスト 14. AndroidRestClient.java
package com.ibm.android.rest.client;
// java net import
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
// Android imports
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
public class AndroidRestClient extends Activity {
// Declaring web service WSDL,Namespace,Method
private TextView textView;
private EditText text;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (EditText) findViewById(R.id.editText);
textView = (TextView) findViewById(R.id.result);
final Button button = (Button) findViewById(R.id.buttons);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try
{
String s=text.getText().toString();
URL url = new URL("http://restingae.appspot.com/rest/testuser/"+s );
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
// Get the HTTP response code
if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK)
{
InputStream inputStream = httpConnection.getInputStream();
if(inputStream != null)
{
StringBuilder stringBuilder = new StringBuilder();
String line;
try
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream, "UTF-8"));
while ((line = reader.readLine()) != null)
{
stringBuilder.append(line).append("\n");
}
}
finally
{
inputStream.close();
}
textView.setText(stringBuilder.toString());
}
}
if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND)
{
textView.setText("404 (not found)");
}
}
catch (MalformedURLException urlEx)
{
textView.setText(urlEx.getMessage());
}
catch (IOException ioEx)
{
textView.setText(ioEx.getMessage());
}
catch (Exception ex)
{
textView.setText(ex.getMessage());
}
}
});
}
}
|
- res|layout フォルダーの下にある main.xml ファイルを編集します (リスト 15 を参照)。
リスト 15. main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/result"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
/>
<EditText android:layout_height="wrap_content" android:text="Partha"
android:id="@+id/editText" android:layout_width="wrap_content"></EditText>
<Button android:text="SEND" android:id="@+id/buttons"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
|
- インターネットにアクセスできるように、以下の uses-permission を AndroidManifest.xml ファイルに追加します。
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission> |
- Android アプリケーションとして実行し、皆さんの名前を入力し (ここでは Partha と入力しています)、「SEND (送信)」をクリックすると、RESTful な Web サービスから歓迎のメッセージが表示されます (下図参照)。
Android でサービスを呼び出す
このチュートリアルでは、JAX-WS Web サービスと JAX-RS Web サービスの作成方法を非常に短時間で学びました。また SOA とクラウド・コンピューティングの概要、そして両者の連携についても学びました。SOA とクラウド・コンピューティングとを組み合わせることで、大規模なエンタープライズ・アプリケーションのための非常にスケーラブルなプラットフォームが提供されるため、コストを削減することができ、ROI を高めることができます。
- 「Eclipse
WTP Tutorials」 ― Apache Axis2 を使用してボトムアップ方式で Web サービスを作成する方法を解説した Eclipse WTP
のチュートリアルです。
- 「Developing
a web service and consuming it with J2ME Client」(developerWorks、2011年3月) では、Java 2
プラットフォームを使用して Web サービスを作成し、WebSphere Application Server Community Edition (WASCE) と Tomcat サーバーにデプロイする方法について、例として 2 つの単純なサービス (Hello World と Logging) を作成し、それらを J2ME クライアントを使用して呼び出す方法を解説しています。
- 「SOA
development with Axis2」(developerWorks、2006年8月) は次世代の SOAP 処理フレームワークについて解説しています。
- Sun Developer Network の記事、「Service-Oriented
Architecture and Web Services: Concepts, Technologies, and Tools」は、Web サービスと SOA に関するツールと技術について解説しています。
- チュートリアル「Deliver
Web services to mobile apps」(developerWorks、2003年1月) を読み、J2ME (Java 2 Platform, Micro Edition) 対応のモバイル機器を使用して Web サービスにアクセスする方法を学んでください。
- 「Developing
web services」(developerWorks、2011年6月) は、Axis2 を使用してコード・ファースト、コントラクト・ファーストの手法で Web サービスを作成する方法を解説しています。

Partha Goswami は J2EE、Web サービス (JAX-WS)、J2ME、Android アプリケーションの開発に 13 ヶ月を超える経験を持つ B.Tech (Bachelor of Technology: 科学技術学士) です。現在はカルカッタの Protech Infosystems のジュニア・コンサルタントです。彼は広範なオープンソース・ツールや商用ツール (WASCE、Eclipse、Oracle SOA Suite11g、EZlegacy、BIRT、DB2 Express C) の使用に関する専門知識を持っています。最新技術への情熱の他に、彼はクリケットやタブラ (2個1組の手太鼓) などにも関心を持っています。

Kuntal Ganguly は J2EE、Web サービス (JAX-WS)、J2ME、Android アプリケーションの開発に 13 ヶ月を超える経験を持つ B.Tech (Bachelor of Technology: 科学技術学士) です。現在はカルカッタの Protech Infosystems のジュニア・コンサルタントです。彼は広範なオープンソース・ツールや商用ツール (WASCE、Eclipse、Oracle SOA Suite11g、EZlegacy、Active MQ、BIRT、DB2 Express C)、そして技術 (GWT や Android) の使用に関する専門知識を持っています。最新技術への情熱の他に、彼はクリケット、ヨガ、ボディビルなどにも関心を持っています。