So-net無料ブログ作成
お知らせ

 当ブログは、ブログに割当てられたディスク容量が満杯になったため、2017年1月8日に、続ブログへ移転しました。

 【移転先】
  続・Emi Clockは、どうなったの?
  http://yuna-k.blog.so-net.ne.jp/


  RSSフィード
  http://yuna-k.blog.so-net.ne.jp/index.xml
アーキテクトぽい ブログトップ
前の5件 | -

MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ [アーキテクトぽい]

2016年11月18日(金)
※2015.11.19 即時学習項目変更の記述を追加

きょうの横浜は、[晴れ]晴れて、日中は暖かかったです。

※ ITの難しい話(チャットボット)が延々と続きますので、興味がない方は、スルーして、ポチっとしてください。

― ― ― ― ― ― ― ― ― ―
[飲み会調整botのリスト並べ替えパーソナライズ]
11月12日のブログ記事で、パーソナルエクスペリエンス(個人の経験)によって、ステートフルな(つながりの状態を保った)会話を動的に変更する機能を、ご紹介しました。
   ↓
2016.11.12 MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

チャットBotに限らず、Webのショッピングサイトなどで、よく参照する商品が先頭に出てくる、なんていうことは、パーソナライズの基本中の基本です。
これができていないサイトには、行かなくなる! ぐらい、古典的だけれども重要な機能です。
この発展形が「あなたへのおススメ商品は、xxxです」といった、レコメンデーションです。

飲み会調整botで使っている チャットBotエンジンでも、ちゃんとできますよ。
実例を示す前に、リストの並び変えが分かりやすくなるように、リストの選択肢を、箇条書きにフォーマッティングしました。(最初から、こうすればよかったんですけどね)
ついでに、店名選択リストには、「ぐるなび」サイトへのURL(リンク)を追記して、お店を選びやすくしています。

まずは、渋谷で女子会の設定例です。
MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ
リストを箇条書きにしたことで、グンと見やすくなりました。
(なお、Skypeのように、単純な改行コードでフォーマッティングできないクライアントもありますのでご注意)

そのまま続けて、渋谷でオフ会の設定例です。
MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ
前回、女子会を設定しているので、今回は、リストの最上位にきて、並びが変わっています。
Webショッピングサイトでよくみる光景ですね。
お店も、前回選んだ光屋‐HIKARIYA‐ 夜景居酒屋が最上位に上がっています。
よく使うお店ほど、上位に並ぶようになります。
グルメサイトで、よくみる光景ですね。

オフ会の設定が終わると、次のイベントの設定メニューは、オフ会、女子会、・・・の順に並びが変わっています。
MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ
「あたりまえの機能だね。」
まぁ、チャットBotで、リスト選択が、このようなパーソナライゼーションができるのは、あたりまえの機能です。
だからこそ、こうなってないものは、古めかしい(旧式)なチャットBotです。

ただし、リストなら、なんでもかんでも、よく使う順に並び変えればいいってものでもないのです。
日付は昇順、開始時刻も昇順、会費も昇順になっていないと、かえって選びにくくなります。
いったい何のデータを扱っているのか、順序性が固定であるべきか、使用頻度で並び変えるべきか、プログラムコードの変更なしに、「データの意味」によって、振る舞いが変わるべきです。

ー ー ー ー ー 
※2015.11.19 即時学習項目変更の記述を追加
11月12日のブログ記事で書いた、パーソナルエクスペリエンスによって、ステートフルな会話を動的に変更する機能を、ご紹介しましたが、学習をリセットするには、①いったんイベントを企画し、②最後に学習項目をリセットし、③最初から、イベントを企画しなおし、といった不便な手順でした。
「めんどくさいね。」
そこれで、企画したイベントの確認後、変更したい項目だけを個別に即時変更できるようにしました。
同時に、パーソナルエクスペリエンスも、そのことを学習します。
MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ
「開始時刻を 30分遅らせたい」とか、「この店だと会費が 1000円高くせねば」ということがありますよね。
なお、「開催場所」を変更すると、「ぐるなび」と連動で、その場所にある「お店」も聞き直します。

ー ー ー ー ー 
Windows系PCの方、Android系スマホの方は、以下の URLでデモを動かすことができます。
   ↓
2016.11.20 MS Bot Framework 3.0で 飲み会調整botの日本語自然文入力
※Apple系(OS X、iOS)の Safariなどは、Microsoftのバグのため、正しく動作しません。
とりあえず、上記のWebチャット画面を表示して、「hi」と打ち込んでください。
あとは、分かります。

※Web Chatコネクターを使っていますので、HTTPSセッションごとにパーソナルエクスペリエンスをデフォルト学習状態にしています。
※Skype、Lync、Facebook Messenger等では、ユーザごとにパーソナルエクスペリエンスを永続化できます。

このURLのドメインは、LINEチャットBot用に取得したものですが、期間限定で、MS Bot Framework 用に使っています。
自分が管理している VPSサーバなので、インバウンドは、SSL/TLS接続のみです。

[MS チャットBot 実証実験 関連ブログ]
2016.10.30 Microsot Bot Framework 3.0で 飲み会調整botデモサイト改二
2016.11.04 Microsot Bot Framework 3.0で ニュースbotデモサイト改二
2016.11.05 Microsot Bot Framework 3.0で 飲み会調整botデモサイト改二 再始動
2016.11.12 MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション
2016.11.18 MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ [かわいい]

― ― ― ― ― ― ― ― ― ―
[追伸]
きょうのビールは、グランドキリン DIP HOP WEIZEN BOCK(瓶)です。
グランドキリン DIP HOP WEIZEN BOCK(瓶)


ヴェーダが、こう判断している。

オリジナルの太陽炉=GNドライブを持たざる者は、イノベイターにはなれない。

nice!(93) 
共通テーマ:趣味・カルチャー

MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション [アーキテクトぽい]

2016年11月12日(土)
※2016.11.13 「ぐるなび」サイトのURLを表示するよう改善

きょうの横浜は、[晴れ]晴れて、日中は暑かったです。

【ご注意】難しい ITの話題が長く続きますので、興味ない方は、ポチっと押し逃げでお願いします。

― ― ― ― ― ― ― ― ― ―
[飲み会調整botのパーソナライゼーション]
前回のブログ記事で、飲み会調整bot 改二について書きました。
   ↓
2016.11.05 Microsot Bot Framework 3.0で 飲み会調整botデモサイト改二 再始動

もう忘れたかと思いますが、見た目に、 5段階の会話プロセスでイベントの調整の会話が成り立っているように見えます。

MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

復習のために、女子会の調整の会話プロセスをやってみますね。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

でも、「横浜」とか、「19:00~21:00」とか、「5,000円」とか、決め打ちのように見える箇所が、3か所あります。
実は、「横浜」とか、「19:00~21:00」とか、「5,000円」とかの値は、決め打ち(ハードコード)されたものではなく、元々は 8段階の会話プロセスで成り立っていたものを、「パーソナルエクスペリエンス」という機能が自動応答し、会話プロセスを動的に変更して、会話をスキップしていたものなのです。

MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

「パーソナルエクスペリエンス」は、そのユーザが、「いつも繰り返し同じ応答」をすることで、「いつもの値」として学習し、次回は、その値を聞かないように、動的に会話プロセスを変更するためのしかけです。
たとえば、Webショッピングサイト(Amazonなど)で、毎回、住所、氏名、クレジットカード番号などを聞かれずに、カートに商品を入れるだけでワンクリックで購入できますが、あれと似たようなものです。
チャットBotの場合は、「その人のやり方=俺流」があると思うのですが、それを実現するしかけが、「パーソナルエクスペリエンス」です。

「今回は、いつもの横浜ではなく、代官山でやりたいわ。」という場合は、会話の最後のイベント詳細確認で、「いいえ」と答えると、学習した値を忘れさせることができます。
では、開催場所を忘れさせましょう。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション
はい、これで、開催場所=横浜、という、「いつもの値」の学習を忘れました。

試しに、いつものように、女子会の調整を始めると、こんどは、「パーソナルエクスペリエンス」が介入しませんので、場所を聞いてくるようになります。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

開催地を、「代官山」と応答すると、開催地と、お店のリストが代官山の内容に変わります。
※ちなみに、お店のデータは「ぐるなび」から取得しています
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション
会話プロセスが、5段階から 6段階になり、開催場所を代官山に変更できました。
で、こんどは、「代官山」を、よく使うと、開催地=代官山と学習し、聞いてこなくなります。

例えば、誕生会を調整しようとすると、開催場所=代官山と学習していれば、「パーソナルエクスペリエンス」が介入して、開催場所=代官山を自動応答し、聞いてこなくなります。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

時刻や、会費についても、同様のことができます。
何度か繰り返し、オレは、いつも、こうやってるんだよね」という値を、「いつもの値」として適宜学習し、会話で聞いてこなくなります。
開始時刻や会費も「オレ流」に学習させて、自動応答させた例が、以下です。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション

以上、長くなりましたが、雑談チャットBotのようなナレッジベースのステートレスなAI(人工知能)と違って、ステートフルな会話プロセスで構成される業務=タスクのようなものは、できるだけ、各々のユーザの「いつものやり方を学習して、個別に、ルーティン・プロセスを短くする」ことが大事なんです。
ルーティン・プロセスは、少しでも簡素にしたいものです。

 ー ー ー ー ー ー
※2016.11.13 「ぐるなび」サイトのURLを表示するよう改善
イベント詳細の表示の際に、お店の元データになっている「ぐるなび」サイトへのURLを表示するよう改善しました。
URLをクリックすると、Webブラウザ上に、お店の「ぐるなび」サイトが表示されます。
MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション
こういう、地道な使い勝手の改善は、プロトを作らないと分からないんだよねー
机の上で、アタマで考えてるだけじゃ、ダメでしょ。
 ー ー ー ー ー ー

Windows系PCの方、Android系スマホの方は、以下の URLでデモを動かすことができます。
   ↓
2016.11.18 MS Bot Framework 3.0で 飲み会調整botのリスト並べ替えパーソナライズ
※Apple系(OS X、iOS)の Safariなどは、Microsoftのバグのため、正しく動作しません。
とりあえず、上記のWebチャット画面を表示して、「hi」と打ち込んでください。
あとは、分かります。

※Web Chatコネクターを使っていますので、HTTPSセッションごとにパーソナルエクスペリエンスをデフォルト学習状態にしています。
※Skype、Lync、Facebook Messenger等では、ユーザごとにパーソナルエクスペリエンスを永続化できます。

このURLのドメインは、LINEチャットBot用に取得したものですが、期間限定で、MS Bot Framework 用に使っています。
自分が管理している VPSサーバなので、インバウンドは、SSL/TLS接続のみです。

[MS チャットBot 実証実験 関連ブログ]
2016.10.30 Microsot Bot Framework 3.0で 飲み会調整botデモサイト改二
2016.11.04 Microsot Bot Framework 3.0で ニュースbotデモサイト改二
2016.11.05 Microsot Bot Framework 3.0で 飲み会調整botデモサイト改二 再始動
2016.11.12 MS Bot Framework 3.0で 飲み会調整botのパーソナライゼーション [かわいい]


ヴェーダが、こう判断している。

オリジナルの太陽炉=GNドライブを持たざる者は、イノベイターにはなれない。
nice!(100) 
共通テーマ:趣味・カルチャー

ハロウィン パンプキン プリン ラテ + Spring BOOTだぜ! [アーキテクトぽい]

書いた記事を、アップ寸前に消してしまった・・・

かなしみー


気を取り直して、書き直し。



― ― ― ― ― ― ― ― ― ―
2016年10月27日(木曜)
※2016.10.28 05:30 Spring Boot Console アプリを追加
※2016.10.28 07:40 Spring Boot Web アプリを追加

きょうの横浜は、[晴れ]晴れましたが、冷え込んで、寒かったです。

― ― ― ― ― ― ― ― ― ―
[パンプキン プリン ラテ]
食欲がなかったので、夕食は、駅構内のベックスで、パンプキン プリン ラテ + サラダドックでした。
ハロウィン パンプキン プリン ラテ + サラダドック
今だけ。

― ― ― ― ― ― ― ― ― ―
[Suica定期券]
iPhone 7 Plusに、Suica定期券をダウンロードして、駅の自動改札をタッチ&ゴーできるようになりました。
Suica定期券
めっちゃ便利ですっ!

iPhone 7から、通信でチャージもできますし、グリーン券も買えます。
Androidスマホだとできたんですが、iPhone 6s まではできなくて、不利になってました。

「そんな機能、俺には要らない」は、遠吠えにしか聞こえませんなー

― ― ― ― ― ― ― ― ― ―
[追伸]
ポケモン GOで、ゴースト系ポケモンが大量に出ていますよね。
ゴースト系ポケモンメダル
50匹ゲットでシルバーメダル、200匹ゲットでゴールドメダルになりますので、ゴールドメダルをコンプしたい方は、せっせと、ゴースを200匹ゲットしてください。
将来、ゴールドメダルの数が条件になる激レアポケモンが出ると予想しています。

相棒のアメが 3倍もらえて、嬉しさも 3倍です。

― ― ― ― ― ― ― ― ― ―
[チャット Bot]
某チャットbot SDKが、Spring Boot(STS) + Gradleビルドなので、Eclipseにプラグインを追加して、使えるようにしました。
コンソールアプリ用の HelloWorldコードを記述します。

※2016.10.28 05:30 Spring Boot Console アプリ(コード)を追加

まずは、コンソールアプリを作ってテスト。
Spring Boot(STS) + Gradle

※2016.10.28 07:40 Spring Boot Web アプリを追加
これをちょこっと、コードを手直しするだけで、RESTful APIになるんですよ~

build.gradle の dependences を書き換えます。
  compile('org.springframework.boot:spring-boot-starter')
      ↓
  compile('org.springframework.boot:spring-boot-starter-web')

Eclipseのエクスプローラーでプロジェクトを右クリック
「Gradle(STS) 」「依存関係を使用可能にする」「依存関係のリフレッシュ」

メインクラスは、こんなふうに修正します。


新規に、WebControllerクラスを作ります。


デバッグで、Spring Bootアプリケーションを起動しますと、GradleでTomcat 8が起動します。
Spring Boot(STS) + Gradle
IE 11とかの Webブラウザで、以下のURLを実行します。
Spring Boot(STS) + Gradle
これは、RESTfulアプリなので、HTTP/GETだけでなく、PUTなども、アノテーションだけで作れます。

まぁ、Strutsとか、昔の Spring時代に、AntやMavenでビルドしてた人(=オヤジ世代)には、便利さがわからないかもしれませんが、天国です。

土日は、某チャットbot SDKを Spring Bootでビルドして、加速しますよ~

C# だの、.NETだのは、捨て捨て~

[チャット Bot さくら 関連ブログ]
2016.10.20 きょうから LINE Bot に転向っ! さくら!
http://emiclock.blog.so-net.ne.jp/2016-10-20
2016.10.25 LINE チャット Bot さくら プロジェクト スタート
http://emiclock.blog.so-net.ne.jp/2016-10-25

※今日のブログは、チャットBotとは直接関係はありません

nice!(106)  コメント(17) 
共通テーマ:趣味・カルチャー

ひみつのPDFフォーム(その7) [アーキテクトぽい]

[exclamation]このブログの内容は、アドビ社から公開されている情報に基づき、個人の趣味で記述しています。

PDFフォームに入力したデータを、Web画面表示を更新せずにWebサーバへ送信するには、Webサービスを使えば簡単にできます。

※OS: Windows 7 Ultimete SP1
※Java SE: Java SE SDK 6 Update 32
※Java IDE: Eclipse 3.7.2 Indigo SR2
※ + Pleiades All in One e3.7
※Webサーバ/APサーバ: JBoss AS 7.1.1.Final "Brontes"
※Webブラウザ: IE 9.0.5
※PDF表示: Adobe Reader X 10.1.3
※PDF作成: Adobe Acrobat X Pro 10.1.3
※PDFフォーム作成: Adobe LiveCycle Designer ES2 9.0.0

LiveCycle ES2 Designerの送信ボタンを使うことにより、PDFフォーム上のフィールドの値をWebサーバへ送信できますが、HTTPプロトコルはリクエストに対してレスポンスが返る同期通信プロトコルであるため、HTTP POSTで送信してしてしまうと、PDFフォーム画面が書き換わってしまいます。
サーバ側で、同じPDFフォームを生成して返す方法もありますが、PDFフォームの生成処理時間が、少なからずかかってしまいます。

入力途中のPDFフォームを、画面を書き換えずに一時保存するには、Acrobat SDKのマニュアルに記載されているWebサービスを活用すればよいのです。
Acrobat SDKで同期型のWebサービスを、SOAP over HTTPで用いるには、Net.SOAPオブジェクトを用います。

【コラム】
ただし、Acrobat SDKのNet.SOAP(以前のバージョンでは、SOAP)オブジェクトは、JAX-RPC(Java API for XML Based RPC) 1.1が基本でしたが、現在のバージョンでは、JAX-WS(Java API for XML-Based Web Services) 2.0 → JAX-RPCのサポートになっており、JAXB(Java Architecture for XML Binding)を用いてしてデータ バインディングを管理するようになっており、XMLBeanを用いてのバインディングが deplicatedです。 したがって、Axis 1.xではJAX-RPCをサポートしているのですが、使わないでください。WS-I Basic Profile 2.0および1.2は、JAX-WSにのみ適用されることに注意してください。


では、LiveCycle ES2 Designerを用いて、今まで作ってきたPDFフォームに『一時保存』ボタン(tempSaveBtn)を追加します。
『一時保存ボタン』を追加

Scriptエディタを開き、『一時保存ボタン』ボタンのclickイベント処理の JavaScriptを書きます。
ポイントは、Page1上の全てのfieldオブジェクトを列挙し、そのオブジェクトがボタン("button"クラス)でなければ、値をSOAPリクエスト文字列に連結していきます。(ボタンは、送信しても邪魔なため外します)
このとき、各フィールド名はPDFフォームのXFA XMLにおいて、UTF-8の1バイトコードなので、そのままでよいでのすが、fieldオブジェクトの値は、UTF-8のマルチバイト文字を含むため、URLEncodeします。
また、URLEncodeの連結文字「&」は、XFA XMLでは「&」でエスケープする必要があります。
SOAPリクエスト文字列ができたら、Net.SOAPオブジェクトのconnectメソッドを使い、WebサービスのWSDLを取得して、動的にプロキシーオブジェクトを生成し、リモートメソッドをコールします。
WSDLのURLは、とりあえずダミーにしておき、Webサービスが完成した後に、置き換えます。(この例では、すでに置き換えてあります)
せっかくなので、うまくいった場合には、SOAPレスポンスの文字列を表示するよう、メッセージボックスを入れておきます。
topmostSubform.Page1.tempSaveBtn::click - (JavaScript, client)
// Page1上の全てのフィールドを列挙してURLエンコード文字列を作成
var objects = xfa.layout.pageContent(0, "field", false);
var cnt, req = "";
for (cnt = 0; cnt < objects.length; cnt++) {
   if (objects.item(cnt).ui.nodes.item(0).className != "button") {
       if (cnt > 0) { req += "&amp;"; }
       req += objects.item(cnt).name + "=" + encodeURIComponent(objects.item(cnt).rawValue);
   }
}
// SOAP over HTTPで Webサービスを呼び出す
var proxy = Net.SOAP.connect("http://localhost:8080/WS4PDF_JBOSS/services/ExportPdfForm?wsdl");
var res = proxy.exportData(req);
xfa.host.messageBox("保存結果は " + res + "でした。");
これで、PDFフォームは完成です。できあがったPDFフォームを、ローカルファイルに保存します。

WebサービスクライアントのPDFフォームができたところで、Webサービスを実装します。
PDFフォームのスクリプトのWSDLのURLでお気づきかと思いますが、今回は、APサーバに、いつものTomcat 6.0ではなく、JBoss APサーバの最新版: JBoss AS 7.1.1.Final "Brontes"を使いました。

EclipseからJBoss ASを使えるようにするためには、新規にサーバーを登録します。
下部のサーバータブで右クリックしてコンテキストメニューを表示して、「新規」-「サーバー」を選択して、「新規サーバーの定義」ウィンドウを表示します。
「サーバーのタイプを選択」で、『JBoss AS 7.1』を選択します。

サーバーのタイプは、『JBoss AS 7.1』を選択

「JBoss Runtime」ウィンドウで、適当なRuntimeの名前を付けて、ホームディレクトリーには、JBoss AS 7.1.1.Final "Brontes"をインストールしたディレクトリ(例えば、"c:\jboss-as-7.1.1.Final")を入力します。
JREは、必ず、最新のJDKのJREを指定してください。(ここ、重要)

JBoss 7.1サーバーの設定 />
アドレス(127.0.0.1)、ポート(8080)などは、デフォルトのままです。
完了すると、<strong><span style=『JBoss 7.1 Runtime Server』という表示が、「ローカル・ホストの Tomcat v6.0サーバー」に加わります。

では、Eclipse上に、JBoss AS 7.1用のWebサービスを作成します。
方法としては、(1)JBossWSを用いる方法、(2) Axisを用いる方法、(3) Axis2を用いる方法の 3通りありますが、Acrobat SDKのAPIは、基本的にJAX-RPCと初期のJAX-WSしかサポートしていないため、『(2) Axisを用いる方法』を用います。(Axisのバージョンは、v1.4)

Eclipseの「ファイル」-「新規」-「動的Webプロジェクト」で、「新規動的Webプロジェクト」を表示し、プロジェクト名を"WS4PDF_JBOSS"にします。

プロジェクト・エクスプローラの"Java Resource/src"で右クリックして「新規」で、"com.motosoft.ws4pdf.web.service"パッケージを作成します。
作成したパッケージで右クリックで「新規」-「クラス」で、"ExportPdfForm.java"を作成します。
package com.motosoft.ws4pdf.web.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public class ExportPdfForm {
    @WebMethod
    public String exportData(String req) throws UnsupportedEncodingException {
        // URLEncodeされたパラメタを分解して表示する
        String[] params = req.split("&");
        for (int i=0; i < params.length; i++) {
            String[] kv = params[i].split("=");
            System.out.println("Key=" + kv[0] + ", " + "value=" +  URLDecoder.decode(kv[1],"utf-8"));
        }
        return "OK";
    }
}
"WS4PDF_JBOSS"プロジェクトで右クリックして「新規」-「Webサービス」から、Webサービスウィザードを表示し、「Webサービス・タイプ」で『ボトムアップ Java bean Webサービス』を選択し、「サービス実装」で、今回作成した「ExportPdfForm」クラスを指定します。
「構成」で、「サーバー・ランタイム」を 『JBoss AS 7.1』、「Webサービス・ランタイム」を『Apache Axis』に設定し、サービスEARプロジェクト(デプロイするEAR格納用)に『WS4PDF_JBOSS_EAR』を指定し、他はデフォルトにします。

JBoss AS 7.1上でAxis 1.4の設定を行う

「Webサービス Java Beanの識別」ウィンドウで、"exportData"メソッドを選択し、「スタイルおよび使用」で『文書/リテラル』をチェックします。
「サーバーを始動」ボタンをクリックすると、ローカルホスト上でJBoss AS 7.1が起動し、Webサービスが使えるようになります。

忘れないうちに、『WS4PDF_JBOSS_EAR』プロジェクトを JBoss AS 7.1サーバに追加しておきます。

JBoss AS 7.1サーバにWebサービスがデプロイできている

Webブラウザから、WebサービスのWSDLを取得するURL(http://localhost:8080/WS4PDF_JBOSS/services/ExportPdfForm?wsdl)を開き、WSDLが表示されることを確認します。
IE9上で、WSDLが表示されることを確認

ここまでの作業で、Webサービスを呼び出すAcrobat ScriptによるクライアントとなるPDFフォームと、JBoss AS 7.1.1でホスティングされたWebサービスができあがりました。
しかし、Acrobat ScriptによるクライアントとなるPDFフォームを、Adobe Reader Xで表示させても、セキュリティ上の制限によりWebサービスを呼び出すことができません。
これは、うっかり、悪意があるWebサービスへ接続するAcrobat Scriptを含むPDFフォームを開くことによるセキュリティリスクから保護するためです。
Adobe Reader Xから、Webサービスを呼び出すには、アドビ社が販売するサーバ製品「Adobe LiveCycle Reader Extensions ES3」を購入し、『Webサービスの実行を許可』する隠し権限を付与する必要があります。

しかし、Acrobat X Proを保有していれば、「Adobe LiveCycle Reader Extensions ES3」付与できる隠し権限をオールマイティで許可できてしまうため、これを利用して、PDFフォームからWebサービスを呼び出してみましょう。
LiveCycle ES2 DesignerでPDFフォームに追加した、『一時保存』ボタンをクリックすると、PDFフォームのAcrobat ScriptがSOAP over HTTPで、JBoss AS 7.1.1上のAxisサーブレットを経由し、JAX-WSでWebサービスと通信し、レスポンスを返します。

PDFフォームからWebサービスを呼び出し

上記のように、、Acrobat X Proを保有していれば、何でもアリなので、PDFフォームの開発にも有益です。

JBoss AS 7.1.1のコンソールログは、以下のように、PDFフォームに入力された値がアップロードされます。
20:24:34,534 INFO  [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-5) Coyote HTTP/1.1を http-localhost-127.0.0.1-8080 で起動します
20:24:34,566 INFO  [org.jboss.as.remoting] (MSC service thread 1-5) JBAS017100: Listening on localhost/127.0.0.1:4447
20:24:34,566 INFO  [org.jboss.as.remoting] (MSC service thread 1-6) JBAS017100: Listening on /127.0.0.1:9999
20:24:34,566 INFO  [org.jboss.as.server.deployment.scanner] (MSC service thread 1-4) JBAS015012: Started FileSystemDeploymentService for directory C:\jboss-as-7.1.1.Final\standalone\deployments
20:24:34,581 INFO  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) JBAS015003: Found WS4PDF_JBOSSEAR.ear in deployment directory. To trigger deployment create a file called WS4PDF_JBOSSEAR.ear.dodeploy
20:24:34,628 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-6) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
20:24:34,659 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015876: Starting deployment of "WS4PDF_JBOSSEAR.ear"
20:24:34,675 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) JBAS015876: Starting deployment of "WS4PDF_JBOSS.war"
20:24:35,252 INFO  [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-4) Add Service
 id=com.motosoft.ws4pdf.web.service.ExportPdfForm
 address=http://localhost:8080/WS4PDF_JBOSS/ExportPdfForm
 implementor=com.motosoft.ws4pdf.web.service.ExportPdfForm
 invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker
 serviceName={http://service.web.ws4pdf.motosoft.com/}ExportPdfFormService
 portName={http://service.web.ws4pdf.motosoft.com/}ExportPdfFormPort
 wsdlLocation=null
 mtomEnabled=false
20:24:35,440 情報    [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-4) Creating Service {http://service.web.ws4pdf.motosoft.com/}ExportPdfFormService from class com.motosoft.ws4pdf.web.service.ExportPdfForm
20:24:35,878 情報    [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-4) Setting the server's publish address to be http://localhost:8080/WS4PDF_JBOSS/ExportPdfForm
20:24:35,987 INFO  [org.jboss.wsf.stack.cxf.deployment.WSDLFilePublisher] (MSC service thread 1-4) WSDL published to: file:/C:/jboss-as-7.1.1.Final/standalone/data/wsdl/WS4PDF_JBOSSEAR.ear/WS4PDF_JBOSS.war/ExportPdfFormService.wsdl
20:24:35,987 INFO  [org.jboss.as.webservices] (MSC service thread 1-3) JBAS015539: Starting service jboss.ws.port-component-link
20:24:36,003 INFO  [org.jboss.as.webservices] (MSC service thread 1-7) JBAS015539: Starting service jboss.ws.endpoint."WS4PDF_JBOSSEAR.ear"."WS4PDF_JBOSS.war"."com.motosoft.ws4pdf.web.service.ExportPdfForm"
20:24:36,003 INFO  [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-7) register: jboss.ws:context=WS4PDF_JBOSS,endpoint=com.motosoft.ws4pdf.web.service.ExportPdfForm
20:24:36,268 INFO  [org.jboss.web] (MSC service thread 1-7) JBAS018210: Registering web context: /WS4PDF_JBOSS
20:24:36,268 INFO  [org.jboss.as] (MSC service thread 1-5) JBAS015951: Admin console listening on http://127.0.0.1:9990
20:24:36,268 INFO  [org.jboss.as] (MSC service thread 1-5) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 3388ms - Started 193 of 272 services (78 services are passive or on-demand)
20:24:36,519 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "WS4PDF_JBOSSEAR.ear"

20:24:41,339 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=CLIENT_SEX, value=女
20:24:41,339 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=CLIENT_BIRTHDAY, value=1992/11/22
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=DOCTOR_AUTH_DATE, value=2012-05-10
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=PAYMENT_ORDER, value=1
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=CARTE_NO, value=CT10842780
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=CLIENT_NAME, value=指原莉乃
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=DOCTOR_NAME, value=秋元康
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=DIVISION_NAME, value=1
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_DAY_OF_WEEK, value=3
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_ZONE, value=1
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=RESERVATION_ZONE, value=1
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_HOUR, value=10
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=RESERVATION_HOUR, value=9
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=RESERVATION_MINUTES, value=0
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_MONTH, value=5
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_DAY, value=23
20:24:41,355 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Key=EXAMINATION_MINUTES, value=0

次回は、また、Acrobat X Proだけを用いて、オールマイティーな裏技で、PDFフォームに初期データを埋め込んでブラウザへ表示する方法を書く予定です。

[シリーズブログ]
ひみつのPDFフォーム
[1] [2] [3] [4] [5] [6] [7]
nice!(0)  コメント(0) 
共通テーマ:パソコン・インターネット

ひみつのPDFフォーム(その6) [アーキテクトぽい]

※このブログの内容は、アドビ社から公開されている情報に基づき、個人の趣味で記述しています。

PDFフォームに入力したデータを、Webサーバへ送信するには、送信ボタンを使えば簡単にできます。

※OS: Windows 7 Ultimete SP1
※Java SE: Java SE SDK 6 Update 19
※Java IDE: Eclipse 3.7.2 Indigo SR2
※ + Pleiades All in One e3.7 Java
※Webサーバ/APサーバ: Apache Tomcat 6.0.35
※Webブラウザ: IE 8.0, Safari 5.1.5
※PDF表示: Adobe Reader X 10.1.3
※PDF作成: Adobe Acrobat X Pro 10.1.3
※PDFフォーム作成: Adobe LiveCycle Designer ES2 9.0.0

PDFフォームの送信ボタンは、HTMLのSUBMITボタンのような働きをし、PDFフォームに入力されたデータを、HTTP POSTリクエストでWebサーバへ送信できます。
PDFフォームに入力したデータは、XML形式、または、URLエンコード形式を選択することができますが、HTMLフォームとの互換性を考慮し、URLエンコード形式を用いることにします。

PDFフォームから送信されたデータを受け取るサーブレットを作ります。
Eclipseを起動し、プロジェクトエクスプローラ上の、作成した動的 Webプロジェクトで右クリックし、「新規」 - 「サーブレット」を選び、適当なJavaパッケージ名を付けます。
ここでは、クラス名は"SubmitPdfForm"にして、完了をクリックします。
SubmitPdfFormサーブレットを作成します

できあがったサーブレットの雛形"は"SubmitPdfForm.java"に、コードを書いていきます。
まずは、doPostメソッドに、Webブラウザで開いたPDFフォームから送信されてきたHTTP POSTリクエストデータを取り出して、コンソールに表示するようにします。
ただ、それだけだと、HTTP POSTリクエストのレスポンスがカラッポになり、Webブラウザ画面が真っ白になりますので、簡単なHTMLでメッセージを返すことにします。
       
/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    // PDFフォームからのHTTP POSTリクエストデータを読み込む
    Enumeration<?> params = request.getParameterNames();
    while (params.hasMoreElements()) {
        String key = (String)params.nextElement();
        String value = request.getParameter(key);
        System.out.println("INFO: Key=" + key + ", value=" + value);
    }

    // 適当なレスポンスを返す
    response.setContentType("text/html");
    response.setCharacterEncoding("Windows-31J");
    PrintWriter out = response.getWriter();
    out.print("<html><body><font size=\"6\">");
    out.print("PDFからのデータを読み込みました。");
    out.print("</font></body></html>");
}
URLエンコードを選択した場合は、サーブレットのコードは、HTMLフォームからフォームデータを受け取る場合と同じコードになります。
サーブレットができたところで、メニューから「実行」-「実行」で、ローカルホストのTomcat 6.0サーバを起動し、サーブレットを呼び出せる状態にします。

LiveCycle Designer ES2で、すでに作成済みのPDFフォームの「保存」ボタンをクリックし、オブジェクトタブで、コントロールの種類を、"標準"から"送信"に変更します。
コントロールの種類を、

さらに、送信タブに切り替えて、送信先URLに、さきほど作成したサーブレットのURLである、"http://localhost:8080/WS4PDF/SubmitPdfForm" を指定します。
送信形式は"URL エンコードデータ(HTTP Post)"、データエンコーディングは"UTF-8"に設定して、PDFフォームを保存します。
送信ボタンの設定

ローカルディスクに保存したPDFフォームからフォームデータを送信することも出来てしまう(セキュリティ警告が出ますが、無視して実行可能)のですが、ここでは、Webブラウザに表示したPDFフォームをWebサーバへ送信するものとします。

WebブラウザにPDFフォームを表示するには、「ひみつのPDF(その4)」で作成した、LoadPdfTemplateサーブレットを経由して、PDFフォームをHTTP GETで取得します。
"C:\pdf_template に、OrderForm107.pdf"を配置しておき、IE8を起動して、アドレスバーに以下のURLを入力して、ウィンドウ内にPDFフォームを表示します。
http://localhost:8080/WS4PDF/LoadPdfTemplate?template=OrderForm107.pdf

PDFフォームが表示されたら、テキストフィールドやコンボボックスにデータを入力します。
テキストフィールドやコンボボックスにデータを入力します

PDFフォームへのデータ入力を終えたら、「保存」ボタンをクリックし、SubmitPdfFormサーブレットへデータを送信します。

サーブレットから、レスポンスのHTMLが返ってきて、「PDFからのデータを読み込みました。」と表示されます。
サーブレットからのレスポンス

このように、HTTP POSTでPDFフォームを送信した場合、入力したPDFフォームの表示が書き換わってしまう点に注意です。
これを回避し、PDFフォームの表示を書き換えないためには、工夫が必要になります。

Eclipseのコンソールペインには、以下のようなコンソールログが表示され、PDFフォームからのデータを受信できたことがわかります。
INFO: PDF=c:\pdf_template\OrderForm107.pdf
INFO: Key=EXAMINATION_MINUTES, value=0
INFO: Key=EXAMINATION_HOUR, value=9
INFO: Key=CLIENT_BIRTHDAY, value=1986/3/11
INFO: Key=EXAMINATION_MONTH, value=4
INFO: Key=PAYMENT_ORDER, value=1
INFO: Key=CARTE_NO, value=CT80010001
INFO: Key=DOCTOR_AUTH_DATE, value=2012-04-24
INFO: Key=DIVISION_NAME, value=1
INFO: Key=CLIENT_SEX, value=女
INFO: Key=EXAMINATION_DAY_OF_WEEK, value=1
INFO: Key=DOCTOR_NAME, value=秋元康
INFO: Key=EXAMINATION_ZONE, value=1
INFO: Key=CLIENT_NAME, value=篠田麻里子
INFO: Key=RESERVATION_ZONE, value=1
INFO: Key=EXAMINATION_DAY, value=30
INFO: Key=RESERVATION_HOUR, value=8
INFO: Key=RESERVATION_MINUTES, value=0
コンボボックスの値は、LiveCycle Designer ES2で、テキストに連結した数値になります。
なお、Safari 5.1でPDFフォームを表示した場合には、PDFフォームの送信が機能しませんでした。

[シリーズブログ]
ひみつのPDFフォーム
[1] [2] [3] [4] [5] [6] [7]

タグ:PDF
nice!(0)  コメント(0) 
共通テーマ:パソコン・インターネット
前の5件 | - アーキテクトぽい ブログトップ
caution.gif当ブログ記事は、日本国著作権法および国際法により権利が保護されています。無断で 画面の写真、ハードコピー、その他の二次複製物を無断で使用することは権利の 侵害になりますのでご注意下さい。
This blog post, right has been protected by copyright law and international law. Without permission screen photo of, hard copy, that you use the other secondary copies without permission is a violation of the rights Please note.
- - - - -
All rights reserved. Copyright (C) Motosoft(Toshi At Kuroneko) 2007-2017.