PL / SQL Webサービスソリューション

OracleデータベースからSOAPメッセージを送受信するという要件に直面しました。
また、このソリューションは普遍的であり、他のモジュールと簡単に統合できる必要があります。
インターネットではこのようなものは見つかりませんでした。 UTL_HTTPパケットを使用してSOAPメッセージを送信する方法に関する記事がありますが、それ以上のものはありません。

構成と統合が簡単なOracleデータベースからSOAPメッセージを送信するための汎用PL / SQL製品を作成することにしました。

それでは始めましょう。

このソリューションでは、次のデータベースオブジェクトを使用します。


読者は、SOAP、XML、またはOracle Databaseオブジェクトが何であるかを説明する必要がないと想定されています。

設置


このソリューションをインストールするには、次のオブジェクトをインストールする必要があります


ソースコード

説明書


テーブルの構造を考慮する

画像

それぞれについて詳しく見ていきましょう。

テーブルWS_SERVER

SOAP / XMLメッセージが送信されるサーバーのリストを保存します。

列SERVER_ID-サーバーの論理識別子。 主キーです
URL列-サービスパス
STATUS-ステータス。 1-動作します。 0-オフ。 デフォルト1

テーブルWS_TEMPLATE

SOAP / XMLメッセージテンプレートと構成情報を格納します。

TEMPLATE_ID-テンプレートの論理識別子。 主キーです
TEMPLATE_XML-テンプレート(形式については後で説明します)
SERVER_ID-サーバーの論理識別子。 テーブルWS_SERVERを参照する外部キーです
REQUEST_PARAMS-要求パラメーター(形式については後で説明します)
RESPONSE_PARAMS-応答パラメーター(形式については後で説明します)
XMLNS-名前空間
PATH-XMLパス(以下の例を使用して詳細に説明します)
STATUS-ステータス。 1-動作します。 0-オフ。 デフォルト1

テーブルWS_LOG

操作に関するログを保持します。

EVENT_TIME-操作時間
XML_REQUEST-XML / SOAPリクエスト
XML_RESPONSE-XML / SOAPレスポンス
REQUEST_PARAMS-要求パラメーター
RESPONSE_PARAMS-応答パラメーター
RETVAL-完了したリクエストのステータスに関する情報。 成功した場合> 0
RETMSG-完了したリクエストに関する情報。 リクエストが失敗した場合のエラーコード
EXECUTE_TIME-リクエストの実行に費やされた時間(秒およびミリ秒)

TEMPLATE_XMLテンプレートを作成する方法

XMLファイル自体がここに収まり、次の形式の入力に必要なパラメーターを置き換えます%PARAMETER_NAME%

例:
 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPrice> <m:StockName>%NAME%</m:StockName> </m:GetStockPrice> </soap:Body> </soap:Envelope> 


この場合、このリクエストを送信するには、この形式の値をこの列に書き込む必要があります。 プログラム自体は、さらにこれを対応するパラメーターに置き換えます(パラメーターについては以下で説明します)。

 <m:StockName>%NAME%</m:StockName> 


したがって、干渉しない値がいくつかある場合は、すぐに示す必要があります。

 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPrice> <m:StockName>%NAME%</m:StockName> <m:StockCount>%COUNT%</m:StockCount> </m:GetStockPrice> </soap:Body> </soap:Envelope> 


ご覧のとおり、2つの変数NAMECOUNTが示されています。

 <m:StockName>%NAME%</m:StockName> <m:StockCount>%COUNT%</m:StockCount> 


パラメーター入力規則(REQUEST_PARAMSおよびRESPONSE_PARAMS列)

この列は次の形式で入力されます。
PARAMETER_NAME_1={VALUE_1}|PARAMETER_NAME_2={VALUE_2}|…PARAMETER_NAME_N={VALUE_N}

クエリパラメータ(REQUEST_PARAMS列)

リクエストに関係なく定数変数がある場合、この列は埋められます。 基本的に、空白のままにすることができます。 この値は、メインプロシージャの開始時に設定されます。 これについてもう少し。

列パス

サーバーからの応答の処理を構成するには、必要な回答がXML内(タグ間)で同期されるパスを示すPATH列に入力する必要があります。

SOAP / XMLメッセージを送信するとき、サーバーから送信される可能性のある応答は事前にわかっています。
たとえば、答えは次のSOAP / XMLである可能性があります

 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPriceResponse> <m:Price>34.5</m:Price> </m:GetStockPriceResponse> </soap:Body> </soap:Envelope> 


この場合、PATH列は次のように記述する必要があります。
/soap:Envelope/soap:Body/m:GetStockPriceResponse

回答からわかるように、このようにして必要な値が見つかります
 <m:Price>34.5</m:Price> 


応答パラメーター(RESPONSE_PARAMS列)

この列は必須です。 フォーマットは同じままです(上記)。

応答形式を事前に知っているため、この列にパラメーターを書き込む必要があります。

 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPriceResponse> <m:Price>34.5</m:Price> </m:GetStockPriceResponse> </soap:Body> </soap:Envelope> 


PATH列に必要なパスを既に示しているので、必要な値を次の形式で入力します。
RESULT_PRICE={m:Price}

これは、RESULT_PRICEをSOAP / XML応答から受け取ったm:Price値に割り当てることを意味します。 さらに例を挙げて、より詳細に検討します。

XMLNSカラム

この名前空間列。 SOAP / XMLリクエストから同じ方法で入力されます。

 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPrice> <m:StockName>%NAME%</m:StockName> <m:StockCount>%COUNT%</m:StockCount> </m:GetStockPrice> </soap:Body> </soap:Envelope> 


この列に入力する必要があり、そこにこのリクエストのすべてのxmlnsを入力します。 この例から、次の値を入力する必要があります。
xmlns:soap="http://www.w3.org/2001/12/soap-envelope" xmlns:m="http://www.example.org/stock"

手順開始

次に、パッケージの構造と実行のルールを検討します。
パッケージ仕様は次のとおりです。

 create or replace package WS is PROCEDURE add_param(pi_params in out varchar2, pi_parameter_name varchar2, pi_parameter_value varchar2); FUNCTION get_param(pi_params varchar2, pi_parameter_name varchar2) return varchar2; PROCEDURE call(pi_template_id VARCHAR2, pi_params VARCHAR2, po_params OUT VARCHAR2, po_data_response OUT VARCHAR2); end WS; 


各機能をさらに詳しく考えてみましょう。
それぞれを例として使用する方法については、統合セクションで説明します。

ADD_PARAMプロシージャ

パラメータを追加/形成するために使用されます。

パラメータ
pi_params-パラメーター文字列変数
pi_parameter_name-追加されたパラメーターの名前
pi_parameter_value-追加されたパラメーターの値

Get_param関数

パラメータ文字列からパラメータを取得するために使用されます。

パラメータ
pi_params-パラメーター文字列変数
pi_parameter_name-取得するパラメーターの名前

呼び出し手順

これがメインであり、プロセス自体を開始します。

パラメータ
pi_template_id-テーブルWS_TEMPLATEのテンプレートID
pi_params-送信に必要なパラメーター文字列変数
po_params-サーバーからの応答で受信したパラメーター文字列変数
po_data_response-サーバーからのXML応答(この変数は使用できません)

次のセクションでは、例としてパッケージ手順を使用します。

統合


このセクションでは、架空のプロジェクトの例を使用して、このソリューションの統合を検討します。

問題があるとします:

次の操作を実行できるエンドユーザー用のサーバーとの対話用のインターフェイスを構築する


実装スキームは次のとおりです。


エンドユーザーとデータベースの間のインターフェイスは任意です。 エンドユーザーは、SQLを介してプロシージャを直接開始することも、サードパーティアプリケーション(Java SE、Java EEなど)から呼び出すこともできます。

以下の情報が提供されます。

Webサービス自体
http://10.10.1.100:8080/GoodsManagementWS/Goods

SOAP / XMLメッセージをサーバーに送信する前に、後者をACLに追加する必要があることに注意してください。 これを行うには、データベース管理者に連絡してください。 インターネットにもこれに関する情報があります。 この記事ではこれを考慮すべきではないと思います。

リクエスト例

製品情報

リクエスト:
 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:GetInfo> <m:ID>1</m:ID> </m: GetInfo > </soap:Body> </soap:Envelope> 


答えは:
 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:Response> <m:Name>Printer</m:Name> <m:Vendor>HP</m:Vendor> <m:Price>Printer</m:Price> <m:Count>Printer</m:Count> </m:Response> </soap:Body> </soap:Envelope> 


製品を追加する

リクエスト:
 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:Add> <m:Name>Printer</m:Name> <m:Vendor>HP</m:Vendor> <m:Price>Printer</m:Price> <m:Count>Printer</m:Count> </m: Add > </soap:Body> </soap:Envelope> 


答えは:
 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:Response> <m:id>1</m:id> </m:Response> </soap:Body> </soap:Envelope> 


お客様から必要なデータを受け取りました。 セットアップと統合の開始。

まず、サーバーに関する情報を記録する必要があります。

 INSERT INTO WS_SERVER (SERVER_ID, URL, STATUS) VALUES ('Store', 'http://10.10.1.100:8080/GoodsManagementWS/Goods', 1); 


次に、クエリパターンに関する情報をテーブルWS_TEMPLATEに書き込む必要があります

製品情報

 INSERT INTO WS_TEMPLATE (TEMPLATE_ID, TEMPLATE_XML, SERVER_ID, REQUEST_PARAMS, RESPONSE_PARAMS, XMLNS, PATH, STATUS) VALUES ('GetInfo', --TEMPLATE_ID '<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:GetInfo> <m:ID>%ID%</m:ID> </m: GetInfo > </soap:Body> </soap:Envelope> ', --TEMPLATE_XML 'Store', --SERVER_ID NULL, --REQUEST_PARAMS 'NAME={m:Name}|VENDOR={m:Vendor}|PRICE={m:Price}|COUNT={m:Count}', --RESPONSE_PARAMS 'xmlns:soap="http://www.w3.org/2001/12/soap-envelope" xmlns:m="http://www.example.org/goods"', --XMLNS '/soap:Envelope/soap:Body/m:Response', --PATH 1) ;--STATUS 


製品を追加する

 INSERT INTO WS_TEMPLATE (TEMPLATE_ID, TEMPLATE_XML, SERVER_ID, REQUEST_PARAMS, RESPONSE_PARAMS, XMLNS, PATH, STATUS) VALUES ('AddInfo', --TEMPLATE_ID '<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:Add> <m:Name>%NAME%</m:Name> <m:Vendor>%VENDOR%</m:Vendor> <m:Price>%PRICE%</m:Price> <m:Count>%COUNT%</m:Count> </m: Add > </soap:Body> </soap:Envelope> ', --TEMPLATE_XML 'Store', --SERVER_ID NULL, --REQUEST_PARAMS 'ID={m:id}', --RESPONSE_PARAMS 'xmlns:soap="http://www.w3.org/2001/12/soap-envelope" xmlns:m="http://www.example.org/goods"', --XMLNS '/soap:Envelope/soap:Body/m:Response', --PATH 1); --STATUS 


そして今、必要な情報をすべて追加して、手順を開始できます。 ただし、このためには、このプロジェクトの手順を記述する必要があります。このプロジェクトでは、WSパッケージの手順を使用します。

製品情報の取得

このタスクの最終手順は次のようになります

 CREATE OR REPLACE PROCEDURE GET_INFO(PI_ID VARCHAR2, PO_NAME OUT VARCHAR2, PO_VENDOR OUT VARCHAR2, PO_PRICE OUT NUMBER, PO_COUNT OUT NUMBER) IS v_template_id VARCHAR2(100) := 'GetInfo'; v_data_response VARCHAR2(4000); v_request_params VARCHAR2(4000); v_response_params VARCHAR2(4000); BEGIN --       -- ws.add_param(v_request_params, 'ID', PI_ID); --    -- ws.call(v_template_id, v_request_params, v_response_params, v_data_response); --        -- PO_NAME := ws.get_param(v_response_params, 'NAME'); PO_VENDOR := ws.get_param(v_response_params, 'VENDOR'); PO_PRICE := ws.get_param(v_response_params, 'PRICE'); PO_COUNT := ws.get_param(v_response_params, 'COUNT'); END; 


パッケージは、結果を送信、送信、受信するためにSOAPメッセージを準備します。その結果、最終プロシージャの結果の応答は、get_paramプロシージャが受信した値になります。 パラメーターリストRESPONSE_PARAMSから任意のパラメーターを取得し、結果として返すことができます。

製品を追加する

このタスクの最終手順は次のようになります

 PROCEDURE ADD_INFO(PI_NAME VARCHAR2, PI_VENDOR VARCHAR2, PI_PRICE NUMBER, PI_COUNT NUMBER, PO_ID OUT VARCHAR2) IS v_template_id VARCHAR2(100) := 'AddInfo'; v_data_response VARCHAR2(4000); v_request_params VARCHAR2(4000); v_response_params VARCHAR2(4000); BEGIN --       -- ws.add_param(v_request_params, 'NAME', PI_NAME); ws.add_param(v_request_params, 'VENDOR', PI_VENDOR); ws.add_param(v_request_params, 'PRICE', PI_PRICE); ws.add_param(v_request_params, 'COUNT', PI_COUNT); --    -- ws.call(v_template_id, v_request_params, v_response_params, v_data_response); --        -- PO_ID := ws.get_param(v_response_params, 'ID'); END; 


この手順にはいくつかの入力パラメーターがあり、結果の変数は1です。

そのため、最終的に、タスクを実行する2つのプロシージャを取得しました。 クエリ結果はテーブルWS_LOG記録されます

追加の質問



応答に必要なデータがさまざまな方法である場合はどうなりますか?

 <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/goods"> <m:Response1> <m:id>1</m:id> </m:Response1> <m:Response2> <m:id>1</m:id> </m:Response2> <m:Response3> <m:id>1</m:id> </m:Response3> </soap:Body> </soap:Envelope> 


この場合、PATHは /soap:Envelope/soap:Bodyて書き込みます。 必要な答えは<soap:Body> </soap:Body>タグの間にあるためです。 そして、RESPONSE_PARAMSをもう少し詳しく記述する必要があります。

ID1={m:Response1/m:id}|ID2={m:Response2/m:id}|ID3={m:Response3/m:id}

SOAP / XML要求と応答が最も単純な場合はどうなりますか?

リクエスト
 <Request> <Data>Test</Data> </Request> 


答え
 <Response> <Result>DONE</Result> <Response> 


この場合、すべてが同様の方法で構成されます。
したがって、XMLNSは空、PATHはResponse RESPONSE_PARAMSはRES={Result}です。 変数名は任意に指定されますが、get_param get_paramリクエストに使用されることに注意してください

プロシージャの開始中にREQUEST_PARAMS行を入力した場合、WS_TEMPLATEテーブルにREQUEST_PARAMS列が必要なのはなぜですか?

この列は、SOAP / XML要求に変更されていない値がある場合に必要です。 プロシージャの開始時にこの列で指定すると、これらのパラメータはすでにデフォルトで追加されているため、追加する必要はありません(add_paramプロシージャ)。

それだけです

十分な情報をレイアウトしようとしました。
私は、発生する質問を聞いて答えてうれしいです。 批判だけでなく、提案やヒントも。
この決定は最近書かれました。 だからあなたが洗練できることがあります。

ありがとう この記事がお役に立てば幸いです。

Source: https://habr.com/ru/post/J223405/


All Articles