デ
デ
ー
ー
タ
タ
ベ
ベ
ー
ー
ス
ス
上
上
で
で
の
の
W
W
e
e
b
b
サ
サ
ー
ー
ビ
ビ
ス
ス
Olivier Le Diouris, Oracle Corporation
サービス・プロバイダとしてのデータベース
この項では、データベース・パッケージを Web サービスとして公開する方法について詳しく説明します。パッケージという理由
Webサービスは、可能なかぎり呼び出すことができる有効なメソッドを持ち、異なる機能を提供するオブジェクト(一 意の名前によって識別される)に非常に似ています。この記述は、まるでパッケージの記述のようです。PL/SQL パッケー ジには、パッケージ仕様で公開されている呼出し可能なメソッドがあります。Web サービスとして公開するプロシージャ や関数が PL/SQL パッケージで実装されていない場合、これらをパッケージ化するのは簡単で、パッケージ化すればすぐ 適切なオブジェクトに呼び出しを転送できます。方法
SOAP仕様は、このような目的を達成するために必要なものすべてを提供します。SOAP は、サービスおよびサービス・ プロバイダのコンセプトを説明しています。サービス・プロバイダは Web サービスによってオブジェクトを実行するコ ンポーネントのようなものです。サービス・プロバイダは、サービスを展開する過程で SOAP サーバーが与えられた Web サービスに対してどのプロバイダを起動するかを識別するようにされます。 たとえば、サービスが Java クラスとして実装される場合、サービス・プロバイダは Java 仮想マシンであり、サービスが 要求されるや SOAP サーバーによってインスタンス化されます。 サービスが Perl スクリプトとして実装された場合は、サービス・プロバイダは Perl インタプリタとなります。 同じ様に、PL/SQL サービス・プロバイダの実装も、新しいプロバイダを作成するために拡張するクラスおよび実装する インタフェースが多くの SOAP 実装に含まれているため、容易に行えます。 PL/SQLサービス・プロバイダには次の情報が必要です。 1. データベース URL 2. 接続のためのスキーマ Webサービスから参照されるパッケージ名がサービス名となり、メソッド名が実行する関数またはプロシージャの名前 となります。このため、リクエストされたものを実行するためにはどちらも必要です。 問題は、仕様によって SOAP がステートレスであるという点です。そのため、このような Web サービスが呼び出された 場合にサーバーが次のことを行う必要があります。 1. 接続する。 2. 適切な関数またはプロシージャを実行する。 3. 切断する。 接続や切断にかかるコストを考えると、このモデルは拡張性が高いとは言えません。JSR 109
の価値
Webサービスを J2EE コンテナで開発しデプロイする方法を指定した JSR 109 に準拠して作業を行う場合があります。 我々の Web サービスは J2EE コンテナのフレームワーク内で実行されるため、J2EE の機能を活用できます。そして、こ のような場合の目標は、データソースと接続プーリングです。PL/SQL Web サービスにアクセスするたびに再接続するか わりに、接続プールからの接続を取得し、完了したらそれを返します。
実際の操作方法
Javaクラスを Web サービスとして公開する方法についてはすでにわかっています。
ここ 2、3 年の間に使用されるようになったツールである JPublisher を使用して、PL/SQL オブジェクトを呼び出すための Javaラッパーを生成します。JPublisher は、Thin Java クラスを生成し、その後ユーザーが Java からデータベースを呼び出 すことを許可します。 次のステップは、この Java ラッパーを Web サービスとして公開することです。すべての要素はここにあり、あとはそれ らをつなげるのみです。
仕様に 100%準拠した真の Web サービス
証拠として、VBScript から呼び出します。 次の PL/SQL パッケージを見てみます。create or replace package greetings as
function sayHello(name in varchar2) return varchar2; function sayGoodbye(name in varchar2) return varchar2; function gettime return varchar2;
end greetings; /
show errors
create or replace package body greetings as
function sayHello(name in varchar2) return varchar2 is val varchar2(48);
begin
val := 'Hello ' || name || '!'; return val;
end sayHello;
function sayGoodbye(name in varchar2) return varchar2 is val varchar2(48);
begin
val := 'Bye-bye ' || name || '!'; return val;
end sayGoodbye;
function gettime return varchar2 is begin
end greetings; /
show errors
Oracle JDeveloperを使用して、このパッケージの 3 つの機能を Web サービスで公開します。
次の VB スクリプトを見てみます。
Dim x, h
rem Set the values in the following three lines
endPoint = "http://localhost.us.oracle.com:8988/WebServices-PLSQL-contextroot/ PLSQLGreetings" WSName = "PLSQLGreetings" methodName = "sayhello" rem Set x = CreateObject("MSXML2.DOMDocument") s = "<s:Envelope xmlns:s=" + chr(34) + "http://schemas.xmlsoap.org/soap/envelope/" + chr(34) s = s + " xmlns:xsi=" + chr(34) + "http://www.w3.org/2001/XMLSchemainstance" + chr(34) s = s + " xmlns:xsd=" + chr(34) + "http://www.w3.org/2001/XMLSchema" + chr(34) + "> " s = s + " <s:Body> " s = s + " <ns1:" + methodName + " xmlns:ns1=" + chr(34) + WSName + chr(34) s = s + " s:encodingStyle=" + chr(34) + "http://schemas.xmlsoap.org/soap/encoding/" + chr(34) + ">" rem Make sure type and value are set correctly here
s = s + " <name xsi:type=" + chr(34) + "xsd:string" + chr(34) + ">Oracle Database</name>"
s = s + " </ns1:" + methodName + ">" s = s + " </s:Body>"
s = s + "</s:Envelope>" x.loadXML s
msgbox x.xml, , "Input SOAP Message" Set h = CreateObject("Microsoft.XMLHTTP") h.open "POST", endPoint
h.send(x)
msgbox "In progress...",,"Click OK to go on" while h.readyState <> 4
wend
msgbox h.responseText,,"Output SOAP Message"
また、次のメッセージが返されます。
この場合、バルク XML 入出力を生成したことがわかります。結果は、必要な値のみが表示されるよう適切に解析されま す。
サービス・コンシューマとしてのデータベース
この項では、データベース内のオブジェクトから既存の Web サービスを呼び出す方法について説明します。 これらはすべて Oracle9i Database Release 2 (9.2.0)上で問題なくテストが終了して正常に実行されています。
操作方法
さいわい、データベースから Web サービスを呼び出すために使用しようとしているテクノロジはすべて、ここ数年間に 使用可能となっています。
データベースに Java クラスを保存して PL/SQL から呼び出すことができるため、指定 Web サービスに対して Java クライ アントを生成し、それを適切な PL/SQL ラッパーとともにデータベースに格納します。その結果、それを PL/SQL および 他の SQL 文から呼び出すことが可能になります。Java クライアントの生成は、最も注意を要する部分ですが、Oracle JDeveloperでは数回のマウス・クリックでこれを行うことができます。
1. 呼び出す Web サービスを選択する。
2. その Web サービスに対する Java クライアントを生成する。
3. このクライアント Java クラスに対する Stored Procedure Deployment Profile を作成する。
4. このデータベースに SOAP Client スタックがインストールされていることを確認する(インストールされていな い場合はインストールする)。 5. データベースでクライアントをデプロイする。 6. 適切な権限を付与する。 7. データベースから Web サービスを呼び出す。
クライアントの生成
例として、www.xmethod.netから取得した Web サービスを呼び出します。具体的に、このサービスに関連付けられた WSDL が必要となります。 クライアント・スタブ(またはプロキシ)を JDeveloper から生成し、クラスから呼び出します。 package wsclient;public class TemperatureWS {
public static String getTemp(String zip, String proxyHost, String proxyPort) {
String ret = "Don't know"; try
{
if (proxyHost != null && proxyHost.length() > 0) { System.setProperty("http.useProxy", "true"); System.setProperty("http.proxyHost", proxyHost); System.setProperty("http.proxyPort", proxyPort); } else System.setProperty("http.useProxy", "false");
TemperatureServiceStub stub = new TemperatureServiceStub(); // Add your own code here.
ret = stub.getTemp(zip).toString(); } catch(Exception ex) { ret = ex.toString(); } return ret; } }
データベースへのクライアント・スタックのインストール
この操作は、生成したクライアントに必要なクラスをデータベース内にインストールするために 1 度実行されます。 次の DOS スクリプトを見てみます。 @echo off setlocal @echo ========================================= @echo Installing the SOAP Stack in the database @echo ========================================= remrem If required, modify the 4 next lines: set JDEV_LOCATION=D:\JDev903.1035 set WIRELESS_LOCATION=D:\iaswv20 set SYS_PASSWD=manager set SID=ORCL rem set SOAP_JAR=%JDEV_LOCATION%\soap\lib\soap.jar set DMS_JAR=%WIRELESS_LOCATION%\lib\dms.jar set JAVAX_SSL=%JDEV_LOCATION%\jlib\javax-ssl-1_1.jar set SERVLET_JAR=%JDEV_LOCATION%\j2ee\home\lib\servlet.jar set MAIL_JAR=%WIRELESS_LOCATION%\jdk\jre\lib\ext\mail.jar ::
@echo Executing loadjava
call loadjava -thin -user sys/%SYS_PASSWD%@localhost:1521:%SID% -resolve -synonym - verbose -grant public %SOAP_JAR% %DMS_JAR% %JAVAX_SSL% %SERVLET_JAR% %MAIL_JAR% ::
:sqlplus
sqlplus "sys/%SYS_PASSWD% as sysdba" @grant.sql pause :finish endlocal loadjavaの呼び出す行を見ると、5 つの jar ファイルをデータベースにインストールしていることがわかります。 SYSアカウントを使用し、これらのオブジェクトへのアクセスを PUBLIC に許可しています。 SQL*Plusから grant.sql と呼ばれるスクリプトを実行していることに注意してください。このスクリプトの使用に関する 詳細を次に示します。このスクリプトは、データベースがローカル・ホスト上に位置し、変更が可能であることを前提と しています。 データベース Web サービスを使用する利点の 1 つは、データベースのセキュリティ機能をすぐに活かせることです。 セキュリティ上の理由から、ユーザーに対してデータベースの固有のリソースにアクセスするために固有の権限を与える 必要があります。この権限は、次のようにして許可する必要があります。
execute dbms_java.grant_permission( 'SCOTT',
'SYS:java.net.SocketPermission',
ここで、SCOTT はユーザーで、localhost:80 はリソースおよび TCP ポートを識別しています。さらに、PropertyPermission も許可の必要があります。次のスクリプトを提案します。
accept machine prompt 'host:port to grant > ' accept user2grant prompt 'for user > ' prompt Granting access on &machine to &user2grant ... execute dbms_java.grant_permission(upper('&user2grant'),
'SYS:java.net.SocketPermission', '&machine', 'connect,resolve'); execute dbms_java.grant_permission(upper('&user2grant'),
'SYS:java.util.PropertyPermission', '*', 'read,write'); execute dbms_java.grant_permission(upper('&user2grant'),
'SYS:java.lang.RuntimePermission', 'getClassLoader', '' ); prompt [Hit return]
pause quit
このスクリプトは、SYS として接続した SQL*Plus を使用して実行するためのものです。username および machine:port を 入力するプロンプトが表示されます。
ストアド・プロシージャとしてのクライアントのデプロイ
SCOTTユーザーを使用してデータベースで 2 つのクラスをロードし、次のように公開します。
CREATE OR REPLACE FUNCTION getTemp (zip IN VARCHAR2, host IN VARCHAR2, port IN VARCHAR2) RETURN VARCHAR2 AUTHID CURRENT_USER
AS LANGUAGE JAVA NAME 'wsclient.TemperatureWS.getTemp (java.lang.String,
java.lang.String, java.lang.String) return java.lang.String'; すでに詳しく説明したいくつかの権限を許可する必要があります。
データベースからの呼出しと使用
set serveroutput on declare zip varchar2(5) := '94065'; begin dbms_output.put_line('Temp at ' || zip || ' is ' || getTemp(zip, 'www-proxy.us.oracle.com', '80') || ' F.'); end; / Temp at 94065 is 61.0 F.PL/SQL procedure successfully completed.
また、select 文からも同じことができます。
select getTemp('94065','www-proxy.us.oracle.com','80') WSTemp from dual;
WSTEMP
--- 61.0
REF-CURSORなどの他の PL/SQL オブジェクト、一時表なども完全に適合します。