今回は,前回作成したSOAPメッセージを実際にbiz-Stream Webサービスサーバに送ってみたいと思います.
前回の「Scala 実践編(3) biz-Stream Webサービスサーバを使った例<前編>」は,Webサービスサーバへ送信するためのSOAPメッセージを構築するところまで説明しました.
その際に,指定したファイル名でPDFファイルをWebサービスサーバ上のコンテンツリポジトリへ出力するように指示していましたが,せっかくなので今回はWebサービスサーバのクライアント側にPDFファイルデータを返す例にSOAPメッセージ部分を変更しました.
出力例は次のとおりです.
ソースコードは次のようになります.
- 《 Scalaからbiz-Stream Webサービスサーバへデータを送りPDFを生成するソースコード(完全版) 》
-
package wssclient import dispatch.{:/, Http} import java.io._ object wss_client { val FILE_NAME = "output_test.pdf" val DATASOURCE_NAME = "app-resource" val COL1 = "col1" val COL2 = "col2" val COL3 = "col3" val RESOURCE_NAME = "resource1" def main(args: Array[String]) { val layoutXml = <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:pdf="http://www.brainsellers.com/schema" xmlns:svg="http://www.brainsellers.com/schema" xmlns:bs="http://www.brainsellers.com/schema" xmlns:form="http://www.brainsellers.com/schema"> <bs:datasource-master-set> <bs:application-data-resource-master master-name={DATASOURCE_NAME}/> <bs:application-data-master master-name="app-field"> <bs:application-data-statement master-reference={DATASOURCE_NAME}/> </bs:application-data-master> <bs:datasource-master master-name="app-source" position="inherit"> <bs:application-data-master-reference master-reference="app-field"/> </bs:datasource-master> </bs:datasource-master-set> <fo:layout-master-set> <fo:simple-page-master master-name="A4" page-height="297mm" page-width="210mm"> <fo:region-body> <fo:region-before extent="0"> <fo:region-after extent="0"> <fo:region-start extent="0"> <fo:region-end extent="0"> </fo:region-end> </fo:region-start> </fo:region-after> </fo:region-before> </fo:region-body> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="A4"> <fo:flow flow-name="xsl-region-body"> <bs:block-container> <!-- ページレイアウト定義開始 --> <Layout width="210mm" height="297mm" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:bs="http://www.brainsellers.com/schema" xmlns:svg="http://www.brainsellers.com/schema" xmlns:form="http://www.brainsellers.com/schema" xmlns:pdf="http://www.brainsellers.com/schema"> <flow-area name="flow-area" x="14" y="280" width="180" height="260" master-reference="app-source" no-data-disabled="false"> <flow-table line-height="10" record-type="header" view="page" border-color="0,255,255"> <flow-table-cell cell-width="60" align="horizon" text-align="left" cell-align="bottom" narrow="size"> <Label Width="60" Height="10" Horizon="center" Vertical="center" Vector="horizon" FontSize="12" FontStyle="BOLD" Narrow="horizon">col1</Label> </flow-table-cell> <flow-table-cell cell-width="30" align="horizon" text-align="left" cell-align="bottom" narrow="size"> <Label Width="30" Height="10" Horizon="center" Vertical="center" Vector="horizon" FontSize="12" FontStyle="BOLD" Narrow="horizon">col2</Label> </flow-table-cell> <flow-table-cell cell-width="90" align="horizon" text-align="left" cell-align="bottom" narrow="size"> <Label Width="90" Height="10" Horizon="center" Vertical="center" Vector="horizon" FontSize="12" FontStyle="BOLD" Narrow="horizon">col3</Label> </flow-table-cell> </flow-table> <flow-table record-type="details" view="layout"> <flow-table-cell cell-width="60" border-color="0,255,255" cell-align="top" narrow="size"> <multi-text name={COL1} cell-width="60" font-size="11" margin="start:1;end:1;top:1;bottom:1"/> </flow-table-cell> <flow-table-cell cell-width="30" border-color="0,255,255" cell-align="top" narrow="size"> <multi-text name={COL2} cell-width="30" font-size="11" margin="start:1;end:1;top:1;bottom:1"/> </flow-table-cell> <flow-table-cell cell-width="90" border-color="0,255,255" cell-align="top" narrow="size"> <multi-text name={COL3} cell-width="90" font-size="11" margin="start:1;end:1;top:1;bottom:1"/> </flow-table-cell> </flow-table> </flow-area> </Layout> <!-- ページレイアウト定義完了 --> </bs:block-container> </fo:flow> </fo:page-sequence> </fo:root> val layoutString = layoutXml.toString val records = List( Map(1 -> "data1", 2 -> "data2", 3 -> "data3"), Map(1 -> "data2_1", 2 -> "data2_2", 3 -> "data2_3"), Map(1 -> "data3_1", 2 -> "data3_2", 3 -> "data3_3")) val soapMessage = <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns="http://schemas.brainsellers.com/webservices/bizstream/2006-10" xmlns:ns1="http://schemas.brainsellers.com/webservices/common/2006-10" xmlns:xm="http://www.w3.org/2005/05/xmlmime"> <soap:Header/> <soap:Body> <generateDataRequest xmlns="http://schemas.brainsellers.com/webservices/bizstream/2006-10" xmlns:common="http://schemas.brainsellers.com/webservices/common/2006-10"> <dataType> <pdf/> </dataType> <resource> <resourceData name={RESOURCE_NAME}> <applicationData masterName={DATASOURCE_NAME}> <recordData> <header> <headerColumn value={COL1}/> <headerColumn value={COL2}/> <headerColumn value={COL3}/> </header>{records.map(record => <detail> <detailColumn value={record(1)}/> <detailColumn value={record(2)}/> <detailColumn value={record(3)}/> </detail>)} </recordData> </applicationData> </resourceData> </resource> <layoutData> <layoutDefinition dataReference={RESOURCE_NAME}> {layoutString} </layoutDefinition> </layoutData> </generateDataRequest> </soap:Body> </soap:Envelope> val tempStream = new ByteArrayOutputStream val http = new Http val url = :/("wss_server_host_name", 8080) / "axis2/services/bizstream.BizstreamSOAP12port/" val authed = url as ("bizuser1", "bizuser1") val req = authed <:< Map("content-type" -> """application/soap+xml;charset=utf-8;action="urn:generateData"""") val soapReq = req << soapMessage.toString http(soapReq >>> tempStream) extractPdfFile(tempStream.toByteArray, FILE_NAME) } def extractPdfFile(bytes : Array[Byte], outputFileName : String) = { val outputFile = new FileOutputStream(outputFileName) val START = "%PDF" val END = "%%EOF" var foundStart = false var foundEnd = false var i = 0 for (i <- 0 to bytes.length - 1 if !foundEnd) { if (!foundStart) { var notFound = false for (j <- 0 to START.length - 1 if !notFound) { if (bytes(i+j) != START(j)) notFound = true else if (j == START.length - 1) { foundStart = true outputFile.write(bytes(i)) } } } else { var notFound = false outputFile.write(bytes(i)) for (j <- 0 to END.length - 1 if !notFound) { if (bytes(i+j) != END(j)) notFound = true else if (j == END.length - 1) { foundEnd = true for (k <- 1 to END.length - 1) outputFile.write(bytes(i+k)) } } } } outputFile.close } }
WebサービスサーバへはdispatchというScala用のライブラリを利用して,サーバにSOAPメッセージを送信します.
- 122行: サーバから返ってくるPDFデータはひとまずtempStreamで受け取ります.
- 123行: httpはdispatchでのHTTP通信のためのクラスです.
- 124行: urlにてWebサービスサーバのホスト名,ポート番号,SOAPポートを指定します.
- 125行: また,サーバへのアクセスは認証が必要なので,authedではユーザ名とパスワードを指定しています.
- 126行: さらに,HTTPヘッダのContentTypeにSOAPメッセージであることを表す「application/soap+xml」,文字コードがUTF-8であることを表す「charset=utf-8」,SOAPのアクション(generateData)を表す「action="urn:generateData"」 を設定します.
- 127行: soapReqでは,上記までで設定したHTTPリクエストのためのオブジェクトにSOAPメッセージを設定します.
- 128行: そして,httpにsoapReqを渡し,HTTP送信を行った後,tempStreamにその返信内容を格納します.
- 129行: tempStream内には,PDFファイル自体以外の情報も含まれているので,extractPdfFile()にてPDFデータのみを抽出し,ファイルに出力します.
今回も,依存するライブラリがあるため,sbtにて簡単にビルド,実行するためのファイルを用意しました.
実行方法は,展開後,README.txtをご覧ください.
biz-scala4.zip