
Adobe
Adobe LiveCycle ESの最も便利な機能の1つ。それは、さまざまな方法でアプリケーションからプロセスを呼び出せることです。例えば、RMI/IIOP対応のJavaアプリケーションの場合はEJB、Flex/AIRアプリケーションの場合はRemoting、.NETの場合はSOAPがそれぞれ利用できます。また、インターフェイスとしてEJBが利用できないJavaアプリケーションであれば、代わりにSOAPを利用できます。本記事では、JavaアプリケーションからSOAPを利用して、LiveCycle ESプロセスを呼び出す以下の3つの方法を解説します。
この記事を効率良くフォローするには、次のソフトウェアやファイルが必要です。
本記事の内容を理解するにはJava/J2EE環境に対する実務知識と、LiveCycle ES環境についての基礎知識が必要です。
本記事では、SOAPを利用してJavaアプリケーションから簡単なLiveCycle ESプロセスを呼び出す、3つの呼び出しを作成します。作業を始める前に、まず、LiveCycle ES Admin UIを利用して、ご利用中のLiveCycle ES環境に本記事付属のLiveCycle Archive(LCA)ファイルを読み込む必要があります。読み込み処理が完了すると、LiveCycle ESはアクティブなLCAファイルを利用して、Javaコードから呼び出すSOAPエンドポイントを自動的に作成します。
また、あらかじめリポジトリにFormsフォルダを作成し、このフォルダに付属のXDP(XML Data Package)ファイルを追加する必要があります。このプロセスは、LiveCycle Forms ESを用いてXMLデータとXDPテンプレートを結合し、PDFファイルを返します。
ここで紹介する3つの方法は、いずれもユーザがJSPページにアクセスし、そこでアップロード対象のXMLファイルを選択するという、同じ処理を行います。ユーザが「アップロード」ボタンをクリックすることで、所定のサーブレットが呼び出されます。そして、このサーブレットがリクエストからXMLファイルを抽出し、SOAPインターフェイスを介してLiveCycle ESを呼び出します。
ご利用中のJavaアプリケーションがEJBを使用できなくても、JDK 1.5のサブバージョンを使用していれば、LiveCycle ES SDKを利用できることがあります。SDKを使用すれば、より高次元なオブジェクト(com.adobe.idp.Documentオブジェクトなど)へのアクセスが可能になります。また、この場合、プロキシクラスやアタッチメントを扱う必要はありません。
まず必要なのは接続プロパティの設定です(詳しくは、Adobe LiveCycle ES LiveDocsの接続プロパティの設定*の節を参照のこと)。ここではLiveCycle ESがJBossサーバ(localhost)上で稼働するケースを例に解説します。接続プロパティでは、接続先のサーバ、ポート、および転送プロトコルを指定します。使用するプロセスがセキュアな場合は、あわせてユーザ名とパスワードも指定します。
Properties ConnectionProps = new Properties(); ServiceClientFactory m_scf = null; ServiceClient myServiceClient = null; ConnectionProps.setProperty("DSC_DEFAULT_SOAP_ENDPOINT", "http://localhost:8080"); ConnectionProps.setProperty("DSC_TRANSPORT_PROTOCOL", "SOAP"); ConnectionProps.setProperty("DSC_SERVER_TYPE", "JBoss"); //login information ConnectionProps.setProperty("DSC_CREDENTIAL_USERNAME", "administrator"); ConnectionProps.setProperty("DSC_CREDENTIAL_PASSWORD", "password");
接続プロパティの指定が完了したら、LiveCycleの呼び出しに用いられるサービスクライアントをインスタンス化します。
m_scf = ServiceClientFactory.createInstance(ConnectionProps); myServiceClient =m_scf.getServiceClient();
次に、LiveCycle ESプロセスが必要とするすべてのパラメータを格納するためのHashMap変数に値を代入する必要があります。HashMapキーは、必ずLiveCycle ESプロセスの入力変数名と一致するようにします。例では、xmlDataという名前のパラメータを1つだけ用意し、これにアップロードされたファイルのコンテンツが配置されるようにしています。getUploadedDataメソッドは、アップロードされたXMLファイルからcom.adobe.idp.Documentオブジェクトを取得します。
//create a Map object to hold the input parameters Map generatePDFparams = new HashMap(); Document myDoc = getUploadedData(request); generatePDFparams.put("xmlData",myDoc );
すべての入力パラメータの指定が完了したら、次にLiveCycle ESへの呼び出しを作成します。まず、サービス名、メソッドおよびパラメータを用い、リクエストを作成します。そして、このリクエストを実行します。このリクエストは短期間のみ存在するプロセスに向けた同期型リクエストであることから、レスポンスが即座に返されるはずです。
//Create the request InvocationRequest Irequest = m_scf.createInvocationRequest( "FormAndData", //Specify the short-lived process name "invoke", //Specify the operation name generatePDFparams, //Specify input values true); //Create a synchronous request //execute the request InvocationResponse Iresponse = myServiceClient.invoke(Irequest);
最後に、呼び出しに対するレスポンスが返されます。サンプルコードには、com.adobe.idp.DocumentオブジェクトであるpdfDocumentが唯一返されるパラメータとして指定されています。
//get the PDF
Document resultDoc = (Document) Iresponse.getOutputParameter("pdfDocument");
この後、Documentオブジェクトは必要に応じて自由に利用できます。(筆者の場合、ブラウザへと書き出しています。)
Adobe LiveCycle ES SDKが使用できない場合(アプリケーションサーバがJDK 1.4.2のみをサポートする場合など)は、WSDLを基にオリジナルのプロキシクラス群を生成することができます。 プロキシクラスの生成には、WSDL2JavaやEclipse WTPプラグインといった、いくつかのツールが利用できます。これらの大半のツールでは、WSDLファイルを指定することで、アプリケーションに読み込めるJavaクラス群を生成できます。
アクティブなプロセス用のWSDLは、LiveCycle ESによって自動生成され、次の場所に配置されます。 http://サーバ名:ポート番号/soap/services/serviceName?WSDL
仮に、筆者のサーバ名がtranquility、ポート番号が8080(JBoss)、サービス名がFormsAndDataであったとします。この場合WSDLは、次の場所に配置されます。 http://tranquility:8080/soap/services/FormAndData?WSDL
生成されたプロキシクラスには、通常、com.adobe.idp.servicesのようなパッケージ名が付与されます。通常、BLOBオブジェクトが作成され、これがバイナリデータおよびDocumentデータを保持します。また、通常はアプリケーションで用いられるProxy、Service、Service Locator、Stubの各クラスの存在を確認することができます。
プロキシクラス群はBase64、DIME/MIMEアタッチメントのどちらでも使用することができます。
Base64エンコーディングではデータが文字列に変換され、SOAPメッセージ内で送信されます。LiveCycle ESはこの文字列が他の処理に回される前に、デコード処理を行います。そして、返されるパラメータはLiveCycle ESによってBase64でエンコードされ、SOAPメッセージの一部として転送されます。幸いにも、メッセージのエンコーディングとデコーディングはプロキシクラスによって大半が処理されるので、これらの詳細を心配する必要はほとんどありません。
まず、生成済みのプロキシクラス群を利用して、LiveCycle ESサーバとの接続を設定します。 LiveCycle ESサービスのURLはプリロードされるかもしれませんが、ここではバイナリデータがどの形式で送信されるかを指定する必要があります。 ここではBase64エンコーディングを使用するので、URLの末尾に「?blob=base64」を追加します。
//create a service locator FormAndDataServiceLocator locate = new FormAndDataServiceLocator(); //specify the service target URL and object type URL serviceURL = new URL("http://tranquility:8080/soap/services/FormAndData?blob=base64"); //Use the binding stub with the locator FormAndDataSoapBindingStub formAndDataClient = new FormAndDataSoapBindingStub(serviceURL, locate); formAndDataClient.setUsername("administrator"); formAndDataClient.setPassword("password");
次に、入力変数を指定する必要があります。ここでは、入力としてオブジェクトのcom.adobe.idp.Documentのみがあります。残念ながら、SOAPの定義にはDocumentオブジェクトが存在しないため、代わりに、より汎用的なBLOBオブジェクトを使用します。BLOBのバイナリデータには、setBinaryDataメソッドを利用してバイト配列を代入することができます。
//populate the input variable BLOB xmlAttachment = new BLOB(); byte[] xmlData = getUploadedData(request); xmlAttachment.setBinaryData(xmlData);
Base64へのエンコーディング処理は、setBinaryDataメソッドによって行われます。
これでLiveCycle ESサービスを呼び出す準備が整いました。結果は別のBLOBオブジェクトとして返され、このオブジェクトからは、getBinaryDataメソッドを利用してバイナリデータを抽出できます。
//call the process
BLOB resultDoc = formAndDataClient.invoke(xmlAttachment);
byte[] resultData = resultDoc.getBinaryData();
Base64エンコーディング処理のコードはさほど難しいものではありませんが、サーバ、クライアント両側でのエンコーディング処理には、相応のパフォーマンスハンデが伴います。これは特にデータファイルの容量が多い場面で顕著になります。幸いにも、LiveCycle ESは、Direct Internet Message Encapsulation(DIME)とMultipurpose Internet Mail Extensions(MIME)の両方をサポートしています。SOAPアタッチメントは、Base64エンコーディングを使用するよりはるかに効率に優れています。
サービス接続の設定は、BLOBタイプがdimeまたはmimeに設定されることを除き、Base64エンコーディングと同じです。
//create a service locator FormAndDataServiceLocator locate = new FormAndDataServiceLocator(); //specify the service target URL and object type URL serviceURL = new URL("http://tranquility:8080/soap/services/FormAndData?blob=dime"); //Use the binding stub with the locator FormAndDataSoapBindingStub formAndDataClient = new FormAndDataSoapBindingStub(serviceURL, locate); formAndDataClient.setUsername("administrator"); formAndDataClient.setPassword("password");
次に、アタッチメントを追加する必要があります。これを行うには、DataHandlerオブジェクトを作成してバイナリデータを格納し、SOAPメッセージへと添付します。この際、アタッチメントIDが発行されます。アタッチメントIDをBLOBオブジェクトに渡すことで、どのアタッチメントがどのパラメータに対応するかをLiveCycle ESへと伝達します。
//Do the DIME attachment byte[] uploadedFile = getUploadedData(request); DataHandler buildFile = new DataHandler(uploadedFile, "application/xml"); AttachmentPart part = new AttachmentPart(buildFile); //get the attachment ID String attachmentID = part.getContentId(); //add the attachment formAndDataClient.addAttachment(part); //Tell LC ES where the attachment is stored by providing the attachment id BLOB xmlAttachment = new BLOB(); xmlAttachment.setAttachmentID(attachmentID);
アタッチメントが完成したら、LiveCycle ESを呼び出すことができます。
//call the process BLOB resultDoc = formAndDataClient.invoke(xmlAttachment);
結果としては、別のBLOBオブジェクトが返されます。BLOBにはバイナリデータそのものではなく、アタッチメントへの参照が含まれます。返されたアタッチメントIDを使用することで、メッセージ内の適切なアタッチメントが特定できます。そして結果のバイナリオブジェクトは、後の処理用にバイト配列に読み込んでおくことができます。
//go through the retuned attachments and get the PDF byte[] resultByte = null; attachmentID = resultDoc.getAttachmentID(); //now find the proper attachment Object[] parts = formAndDataClient.getAttachments(); for (int i=0;i<parts.length;i++){ AttachmentPart attPart = (AttachmentPart) parts[i]; //get the content of the attachment that matches the BLOB's attachment id if (attPart.getContentId().equals(attachmentID)) { buildFile = attPart.getDataHandler(); InputStream stream = buildFile.getInputStream(); resultByte = newbyte[stream.available()]; stream.read(resultByte); } }
本記事で取り上げた項目について詳しくは、アドビ公式ドキュメンテーション*を参照してください。

この記事は、Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported Licenseのもと提供しています。
Michael Hodgsonはアドビエンタープライズテクノロジチームに所属するeシステムスペシャリストです。アドビには過去5年間在籍し、顧客に提示するための試作デモの開発を専門に手がけています。Mikeはカナダ国オタワに在住し、同地にて勤務しています。