今日のデータベース・アプリケーション開発者に共通して求められているのは、Web 上でデータにアクセスする関数を公開する能力です。この記事では、Informix のユーザー定義ルーチン (UDR) またはユーザー定義データ型 (UDT) をサービス指向アーキテクチャーの一部である Web サービスとして Web 上に公開する方法を説明します。Informix の UDR または UDT を操作するには JavaBean を、そしてこれを Web サービスとしてデプロイするには RAD (Rational Application Developer) を使用します。
この記事のサンプルのために、Informix サーバーにはすでにカスタマー・テーブルが作成されています。このテーブルにアクセスして、カスタマーの詳細を取得します。それぞれのカスタマー・レコードには、カスタマー ID が固有の識別子として使用されています。カスタマーの詳細を取得するには、Informix サーバーに UDR としてインストールされ、登録されている Java™ メソッドを使用します。UDR または UDT の作成および登録作業は、Informix の udtudrmgr クラスを使用して行います。
このサンプルでは RAD を使用して、JavaBean を用いる Web サービスを作成し、デプロイしています。内部では、UDR を呼び出すメソッドは Web サービス・メソッドとして公開されます。
フロントエンドのアプリケーションは、JSP/HTML で作成されています。索引ページの入力フィールドはカスタマー ID で、送信時にカスタマーの支払明細を取得して表示する結果ページを呼び出します。
このサンプル・アプリケーションの手順に従うと、以下のことを学ぶことができます。
- Java UDR および UDT の作成方法
- RAD での Web サービスの作成方法
- サービス指向アーキテクチャーによって一層優れた Web アプリケーションを作成する方法
- IDS (Informix Dynamic Server) がサービス指向アーキテクチャーの機能を利用する方法
まず始めに、Web サービスを支える基本的な概念について説明しましょう。
サービス指向アーキテクチャー (SOA) は、クライアント・アプリケーション、Web サービス・アプリケーション、そしてサーバーまたは ERP という 3 つの層からなるクライアント・サーバー・アーキテクチャーの最上部に構築され、このアーキテクチャーの欠点に対応するものです。SOA は、一連のサービスとアプリケーションで構成されます。それぞれのサービスはある種の機能を実装し、アプリケーションやその他のサービスがこれらのサービスを使用します。サービス間の通信、そしてサービスとアプリケーション間の通信は、XML データを交換することによって行われます。SOA はこのように、サービス (実際には複数のアプリケーションの要件を満たすソフトウェア・モジュール) という形式でソフトウェアの再利用性を向上させます。
Web サービスとは、基本的にはあるネットワーク全体でマシン間の相互運用性を提供するソフトウェア・システムのことです。Web サービスには、言語とメッセージ転送プロトコルという 2 つの部分があります。言語の部分は、WSDL (Web サービス記述言語) と呼ばれます。使用されるプロトコルは、SOAP (Simple Object Access Protocol) と呼ばれます。WSDL は基本的にサービスを記述するもので、言語として主に用いられるのは、XML です。SOAP はアプリケーションがインターネットで通信できるようにするためのものです。
図 1. サービス指向アーキテクチャー
ユーザー定義ルーチン (UDR) は、SQL ステートメントや別の UDR で呼び出すことができるルーチンです。Java で作成された UDR は、Informix JDBC ドライバーのサーバー側実装を使用して、データベース・サーバーと通信します。
ユーザー定義データ型 (UDT) は、UDR にパラメーターを渡し、結果を取得できるようにするための SQL データ型と Java オブジェクト間のマッピングです。
Java には、以下の 2 つのタイプの UDT があります。
- 特殊データ型: CREATE DISTINCT DATATYPE
- 不透明データ型: CREATE OPAQUE DATATYPE
UDT を作成するには、CREATE TYPE SQL ステートメント、または UDTMANAGER の createUDT メソッドを使用します。
Java で UDR を作成して使用するには、以下を行う必要があります。
- Informix Internet Foundation 2000 のインストール。
- JDK (Java Development Kit) のインストール。さらに、DataBlade Developers Kit バージョン 4.0 以降をインストールすると、Java で簡単に UDR を開発できます。ソース・コードをコンパイルせずに既存の Java UDR のみを実行する場合は、JDK の代わりに JRE をインストールするだけで十分です。
Java で作成された UDR は、Java 仮想プロセッサー (JVP) と呼ばれる特殊化された仮想プロセッサーで実行されます。JVP のコードには、Java 仮想マシンが組み込まれています。INFORMIX ONCONFIG 構成ファイルには、Java に固有のいくつかの構成パラメーターを指定する必要があります。これらのパラメーターは以下のようになります。
リスト 1. UNIX での ONCONFIG ファイルのスナップショット
VPCLASS jvp,num=1 # Number of JVPs to start with
JVPJAVAHOME /usr/informix/ids_10/extend/krakatoa/jre/
JVPHOME /usr/informix/ids_10/extend/krakatoa # Krakatoa installation directory
JVPPROPFILE /usr/informix/ids_10/extend/krakatoa/.jvpprops # JVP property file
JVPLOGFILE /usr/informix/ids_10/jvp.log # JVP log file.
JDKVERSION 1.3 # JDK version supported by this server
JVMTHREAD native # Java VM thread type(green or native)
# The path to the JRE libraries relative to JVPJAVAHOME
JVPJAVALIB /lib/sparc/
# The JRE libraries to use for the Java VM
JVPJAVAVM hpi:server:verify:java:net:zip:jpeg
# use JVPARGS to change Java VM configuration
#To display jni call
#JVPARGS -verbose:jni
# Classpath to use upon Java VM start-up (use _g version for debugging)
JVPCLASSPATH /usr/informix/ids_10/extend/krakatoa/krakatoa.jar:
/usr/informix/ids_10/extend/krakatoa/jdbc. jar
|
以下の手順に従って、UDR を作成し、登録します。
- Java ファイルに、UDR の本文を書き込みます。これは、以下の例のようになります。
リスト 2. Java での UDR のスナップショット: Circle.javapublic class Circle { private static double PI = 3.14159; public static double area(double c) { return PI * c*c } }
- SQL ステートメントで UDR を呼び出す前に、以下の CREATE FUNCTION または CREATE PROCEDURE ステートメントを使用して、UDR を現行データベースに登録します。:
CREATE FUNCTION area (float) RETURNS float EXTERNAL NAME 'circle_jar:Circle.area(double)' LANGUAGE JAVA NOT VARIANT END FUNCTIONYou can also create a Java file and compile it (as in given sample code: Create Cust UDT.java). - あるいは、Java ファイルを作成してコンパイルすることもできます (サンプル・コード CreateCust UDT.java を参照)。
- javac コマンドを使用して、UDR の本文をコンパイルし、クラス・ファイルを作成します。
- jar ファイルをインストールします。
jar ファイルをインストールするには、SQLJ 組み込みプロシージャー install_jar を使用します。
リスト 3
execute procedure sqlj.install_jar('file:/work/circle_jar.jar','circle_jar',1)
UDR は、デプロイメント記述子とマニフェスト・ファイルを使用して登録することもできます。デプロイメント記述子を使用する場合は、以下のファイル (deploy.txt) を作成してください。
リスト 4
SQLACtions[] = {
"BEGIN INSTALL
CREATE FUNCTION area (float) RETURNS float
EXTERNAL NAME 'circle_jar:Circle.area(double)' LANGUAGE
JAVA NOT VARIANT
END FUNCTION
END INSTALL"
}
|
以下のマニフェスト・ファイル manifest.txt を作成します。
名前: deploy.txt
SQLJDeploymentDescriptor : TRUE
以下のように、マニフェストとデプロイメント記述子を使用して jar ファイルを作成します。
Jar cvfm manifest.txt Circle_jar.jar deploy.txt Circle.class
これで、jar をインストールするステップで UDR を登録できます。
UDR を登録すると、例えば以下のように SQL ステートメントで UDR を呼び出すことができるようになります。
select area(3) from area_table;
Rational Application Developer の概要
RAD for Websphere は、開発者が高品質の Web、SOA、Java、J2EE およびポータル・アプリケーションを簡単に設計、開発、分析、テスト、プロファイル作成、そしてデプロイできるようにする統合開発環境です。RAD には、Java クラスを簡単に開発してコンパイルするための Eclipse エディターが組み込まれており、組み込み WAS (WebSphere Application Server) によって、この Java クラスを Web サービスとしてデプロイすることができます。RAD はテスト環境にもなるため、Web 上で公開する前に Web サービスをスタンドアロン・システムでテストすることができます。
サンプル・アプリケーションではこの RAD を使用して Java クラスを開発し、Web サービスを WAS にデプロイしてその機能をテストしました。また、JDBC 接続を利用することによって、Informix サーバーに接続してデータベースからデータを取得するとともに、Informix サーバーに登録された Java UDR を使用することもできました。このように、RAD では他の支援を追加しなくても、一つのプラットフォームでアプリケーションを実行できます。
サンプル・アプリケーションでは、以下の 5 つのプログラムを使用しました。
リスト 5: Customer.java
package customer;
import java.sql.*;
import com.informix.jdbc.IfmxUDTSQLInput;
import com.informix.jdbc.IfmxUDTSQLOutput;
public class Customer implements SQLData
{
private String type = "customer";
public int id=101;
public int tbill;
public int ebill;
public int mbill;
public int monyr;
public String getSQLTypeName() { return type; }
public void readSQL(SQLInput stream, String typeName)
throws SQLException
{
IfmxUDTSQLInput in = (IfmxUDTSQLInput) stream;
id = in.readInt();
tbill= in.readInt();
ebill= in.readInt();
mbill= in.readInt();
monyr= in.readInt();
}
public void writeSQL(SQLOutput stream) throws SQLException
{
IfmxUDTSQLOutput out = (IfmxUDTSQLOutput) stream;
out.writeInt(id);
out.writeInt(tbill);
out.writeInt(ebill);
out.writeInt(mbill);
out.writeInt(monyr);
}
public static Customer getCustomerDetail ( int cust_id) {
Customer cust_obj=new Customer();
try
{
Connection conn = null;
try
{
Class.forName("com.informix.jdbc.IfxDriver");
}
catch (Exception e)
{
System.out.println("Error: failed to load Informix JDBC driver.");
e.printStackTrace();
return null;
}
String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:INFORMIXSERVER=ol_ids;
user=XXXXX;password=XXXXX";
try
{
conn=DriverManager.getConnection(url);
}
catch(SQLException e)
{
System.out.println("ERROR: Failed to connect!");
System.out.println("ERROR:" + e.getMessage());
e.printStackTrace();
return null;
}
PreparedStatement pstmt=conn.prepareStatement("Select * from customer where id=?");
pstmt.setInt(1,cust_id);
ResultSet rs=pstmt.executeQuery();
while(rs.next())
{
cust_obj.id =rs.getInt(1);
cust_obj.tbill =rs.getInt(2);
cust_obj.ebill =rs.getInt(3);
cust_obj.mbill =rs.getInt(4);
cust_obj.monyr =rs.getInt(5);
}
rs.close();
pstmt.close();
}
catch(SQLException e)
{
System.out.println("ERROR:" + e.getMessage());
e.printStackTrace();
}
return cust_obj;
}
}
|
リスト 6: CustSOA.java
package customer;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Iterator;
import java.util.StringTokenizer;
public class CustSOA {
public String getBillDetail(int cust_id)
{
Customer c_out=new Customer();
/*===================Connection Block==========*/
Connection conn = null;
try
{
Class.forName("com.informix.jdbc.IfxDriver");
}
catch (Exception e)
{
System.out.println("Error: failed to load Informix JDBC driver.");
e.printStackTrace();
return null;
} // End Driver Loading Block
System.out.println("Informix JDBC driver loaded successfully.");
// Connect to database
String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:
INFORMIXSERVER=ol_ids;user=XXXXX;password=XXXXX";
//System.out.println("The url is:-"+url);
try
{
conn=DriverManager.getConnection(url);
}
catch(SQLException e)
{
System.out.println("ERROR: Failed to connect!");
System.out.println("ERROR:" + e.getMessage());
e.printStackTrace();
return null;
}
System.out.println("\nConnection established\n");
/*=========End of connection Block=============*/
/*============Call the UDR===================*/
try {
java.util.Map customtypemap = conn.getTypeMap();
System.out.println("getTypeMap...ok");
if (customtypemap == null)
{
System.out.println("***ERROR: map is null!");
return null;
}
customtypemap.put("customer", Class.forName("customer.Customer"));
String s = "select getCustomerDetail("+cust_id+") from customer";
System.out.println(s);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(s);
if (rs.next())
{
c_out=(Customer) rs.getObject(1);
System.out.println(" ID = " + c_out.id);
System.out.println(" ID = " + c_out.tbill);
}
rs.close();
stmt.close();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c_out.id+":"+c_out.tbill+":"+c_out.mbill+":"+c_out.ebill+":"+c_out.monyr;
}
}
|
リスト 7: CreateCust UDT.java
import java.sql.*;
import java.lang.reflect.*;
public class CreateCustUdt
{
String url = null;
Connection conn = null;
public static void main ()
{
new CreateCustUdt();
}
CreateCustUdt() {
String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:
INFORMIXSERVER=ol_ids;user=XXXXX;password=XXXXX";
// --------------
// Loading driver
// --------------
try {
Class.forName("com.informix.jdbc.IfxDriver");
}
catch (java.lang.ClassNotFoundException e) {
System.out.println("\n***ERROR: " + e.getMessage());
e.printStackTrace();
return;
}
try {
conn = DriverManager.getConnection(url);
}
catch (SQLException e) {
System.out.println("URL = '" + url + "'");
System.out.println("\n***ERROR: " + e.getMessage());
e.printStackTrace();
return;
}
Method getCustomerDetailmethod = null;
try {
Class c = Class.forName("Customer");
getCustomerDetailmethod = c.getMethod("getCustomerDetail", new Class[]
{Integer.TYPE });
}
catch (ClassNotFoundException e) {
System.out.println("Cannot get Class: " + e.toString());
return;
}
catch (NoSuchMethodException e) {
System.out.println("Cannot get Method: " + e.toString());
return;
}
UDTMetaData mdata = null;
try {
System.out.print("Setting mdata...");
mdata = new UDTMetaData();
mdata.setSQLName("Customer");
mdata.setLength(24);
mdata.setAlignment(UDTMetaData.EIGHT_BYTE);
mdata.setUDR(getCustomerDetailmethod, "getCustomerDetail");
mdata.setJarFileSQLName("Customer_jar");
System.out.println("ok");
}
catch (SQLException e) {
System.out.println("\n***ERROR: " + e.getMessage());
return;
}
UDTManager udtmgr = null;
try {
udtmgr = new UDTManager(conn);
String jarfilename = udtmgr.createJar(mdata,
new String[] {"Customer.class"}); // jarfilename = Customer.jar
udtmgr.setJarTmpPath("/tmp");
udtmgr.createUDT(mdata,
"C:\\eclipse\\CUST_TEST\\" + jarfilename, "Customer", 0);
System.out.println("UDT/UDR Created");
}
catch (SQLException e)
{
System.out.println("\n***ERROR: " + e.getMessage());
return;
}
System.out.println();
}
private void executeUpdate(String s)
{
try
{
Statement stmt = conn.createStatement();
stmt.executeUpdate(s);
stmt.close();
}
catch (SQLException e)
{
e.printStackTrace();
return;
}
}
}
|
リスト 8: CustSOAIndex.html
<HTML>
<HEAD>
<TITLE>Customer Detail</TITLE>
</HEAD>
<BODY>
<H1>Inputs</H1>
<FORM METHOD="POST" ACTION="CustSOAResult.jsp">
<INPUT TYPE="HIDDEN" NAME="method" VALUE="18">
<TABLE>
<TR>
<TD COLSPAN="1" ALIGN="LEFT">Enter Customer ID:</TD>
<TD ALIGN="left"><INPUT TYPE="TEXT" NAME="cust_id" SIZE=20></TD>
</TR>
</TABLE>
<BR>
<INPUT TYPE="SUBMIT" VALUE="Invoke">
<INPUT TYPE="RESET" VALUE="Clear">
</FORM>
</BODY>
</HTML>
|
リスト 9: CustSOAResult.jsp
<HTML>
<HEAD> <TITLE>Result</TITLE> </HEAD>
<BODY>
<H1>Result</H1>
<jsp:useBean id="sampleCustSOAProxyid" scope="session" class="customer.CustSOAProxy" />
<% String p_id= request.getParameter("cust_id");
int p_idTemp = Integer.parseInt(p_id);
java.lang.String ret_cust = sampleCustSOAProxyid.getBillDetail(p_idTemp);
if(ret_cust == null)
{ %>
<%=ret_cust%>
<%
} else {
String tempResultreturn = webserviceutils.com.ibm.etools.webservice.util.JspUtils.markup
(String.valueOf(ret_cust));
%>
<% StringTokenizer st=new StringTokenizer(tempResultreturn,":");%>
<b> <TABLE>
<tr>
<td> Customer ID </td>
<td> <%= st.nextToken() %> </td>
</tr>
<tr>
<td> Telephone Bill </td>
<td> <%= st.nextToken() %> </td>
</tr>
<tr>
<td> Elect Bill </td>
<td> <%= st.nextToken() %> </td>
</tr>
<tr>
<td> Mobile Phone Bill </td>
<td> <%= st.nextToken() %> </td>
</tr>
<tr>
<td> Year & Month </td>
<td> <%= st.nextToken() %> </td>
</tr>
</TABLE> </b>
<% } %>
</BODY>
</HTML>
|
サンプル・アプリケーションで使用する Web サービスの作成手順
以下の手順に従って、Web サービスを作成し、メソッドを公開します。
- 動的プロジェクトを作成します。.
Launch File > New > Project を選択して新規プロジェクトを作成し、次にDynamic Web project を選択します。
図 2. 動的プロジェクトの作成
- すべてのソース・コードが作成される新規パッケージを作成します。
JavaSource > New > Package を選択します。
図 3. 新規パッケージの作成
- Web サービス・コードを格納する新規 Java クラスを作成します。
図 4. 新規 Java クラスの作成
- デフォルト・オプションを使用して Web サービスを作成します。RAD には、JavaBean を使用して Web サービスを作成する機能があります。
File > New > Web Service を選択します。:
図 5. 新規 Web サービスの作成
- WebService エクスプローラーで、Java Bean Web Service と以下の図に示すその他のオプションを選択します。
図 6. Java Bean Web サービスの選択
- オブジェクト選択ページが表示されたら、Browse Classes... をクリックし、customer.CustSOA と入力して OK をクリックします。
図 7. Java Bean の識別
図 8. Web サービス・エクスプローラー
- WebService クライアントのテスト・ページで、公開するメソッドにチェック・マークを付け、Next > Finish をクリックします。
図 9. Web サービス・エクスプローラー
図 10. Web サービス・エクスプローラー
- メソッドを呼び出します。このページでハイパーリンクをクリックすると、公開されたメソッドをテストできます。
図 11. 公開されたメソッド
図 12. ブラウザーに表示されたメソッド
以下の画面は、動的 Web プロジェクトと生成されたクライアント・プロジェクトのソース構造を示します。
図 13. ディレクトリー構造
以下は、アプリケーションのメイン画面です。
図 14. メイン・ページ
以下は、アプリケーションの結果画面です。
図 15. 結果ページ
Madhusudhan Ramidi 氏の支援、そして私たちの構想をここまで展開させてくれた TWISTER チームのアイデアに感謝します。
学ぶために
-
developerWorks の Informix ゾーンにアクセスしてください。ここには、Informix のスキルを伸ばす記事、チュートリアル、そしてその他の資料へのリンクが記載されています。
- 記事「Java UDRs with embedded SQL」 (developerWorks、2001年1月) では、Java で実装された Informix UDR に SQL を組み込む方法を説明しています。
-
IBM Informix Dynamic Server v10.00 Information Center にアクセスして、Informix の Java UDR を作成する詳細な方法を学んでください。
- 記事「Creating UDRs in Java」(pdf 版、developerWorks、2001年1月) では、Java で実装された Informix UDR に SQL を組み込む方法を説明しています。
製品や技術を入手するために
-
Informix Dynamic Server の無料の試用版をダウンロードしてください。
議論するために


