本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

Java Web開発者フレームワーク内でのVoiceXMLページの作成 : XML

JavaサーブレットとJSPを使用してVoiceXMLを生成する

Brett D. McLaughlin, Sr., Author and Editor, O'Reilly Media, Inc.
Photo of Brett McLaughlin
Brett McLaughlin氏は、Logo (小さな三角形を覚えていますか?) の時代からコンピューターの仕事をしています。現在の専門は、JavaおよびJava関連のテクノロジーを使ったアプリケーション・インフラストラクチャーの構築です。ここ数年は、Nextel Communications and Allegiance Telecom, Inc. でこれらのインフラストラクチャーの実装に携わっています。Brett氏は、Javaサーブレットを使ってWebアプリケーション開発のための再利用可能なコンポーネント・アーキテクチャーを構築するJava ApacheプロジェクトTurbineの共同設立者の1人です。同氏はまた、オープン・ソースのEJBアプリケーション・サーバーであるEJBossプロジェクトと、オープン・ソースのXML Web公開エンジンであるCocoonにも貢献しています。

概要: ほとんどのWeb開発者にとって、HTML、XHTML、またはXMLの出力は、たいした作業ではありません。Webアプリケーションの作成と導入という日常的なプロセスの一部にすぎません。インターネットでページを表示することと電話で問い合わせに答えることの間には大きな隔たりがあるように見えますが、実際にはそうでもありません。この記事では、Webページを動的に作成するのと同じテクニックで、(ヴァーチャルな)電話に対応できることを説明します。

日付:  2006年 1月 17日
レベル:  中級 この記事の原文:  英語
アクティビティー: 2823 ビュー
お気軽にご意見・ご感想をお寄せください: 


過去5年間で、Webはその歴史上、かつてないほど大きく成長しました。かつては「Webブラウザー」という名前のソフトウェア・プログラム向けの、大部分がテキストベースのメディアであったものが、接続機能を備えたあらゆるデバイスのための情報ソースとなりました。Webページにアクセスできるデバイスのリストに最初に加わったのは、携帯電話でした。その後、ポケットベル、ハンドヘルド・デバイス、パーソナル・プランナーなど、Webに無線接続できるあらゆるものが続きました。最近では、テレフォニーがこの騒動に加わり、通常の電話回線を通じてWebプログラムにアクセスしたいという要求が高まってきました。

この最後のカテゴリーのアプリケーション、すなわち、ユーザーが電話を通じてオンライン・サービスにアクセスするものを、電話アプリケーションと呼ぶことにします。電話では「リンクをクリック」することはできないため、アプリケーションとの対話は、ほとんどすべて音声によって処理されます。ユーザーは、リンクをクリックする代わりに「アカウント情報」と言ったり、録音された指示に従ってダイヤルボタンを使用したりします。

既存の(または若干、手が加えられた)Webアプリケーションを通じて電話に応答するというのはパワフルなアイデアであり、多くのWeb開発者が試してみたいと思っています。Webアプリケーションと電話アプリケーションについて知っておくべき最も重要なことは、どちらもほぼ同じテクノロジーの積み重ねによって作成できるということです。HTML、XHTML、およびXMLは、Webインターフェースの基盤となる最も一般的なテクノロジーです。VoiceXML(VXML)はそれらに密接に関係するテクノロジーであり、電話クライアントに対してWebとの対話を可能にします。JavaServer Pageとサーブレット、PHPスクリプト、およびRubyアプリケーションのすべてが、ハンドヘルドやWebブラウザー経由でのリクエストと同様に、容易に電話リクエストに応答することができます。この記事では、Javaプラットフォームを使用して、単純なVoiceXMLアプリケーションを扱う方法を中心に説明しますが、PHP、Perl、または読者のお気に入りのその他のプログラミング言語にも応用できます。

VoiceXML、CCXML、またはCallXML?

Voxeoから始める


この記事の練習問題を実行するには、無料のVoxeoデベロッパー・アカウントを作成する必要があります。VoxeoはVoiceXMLに必須のサービスではありませんが、すばらしいツール・セットだけでなく、数千ページに上るVoiceXML、CallXML、およびCCXMLのドキュメントがあります。この記事では、VoiceXMLプログラミングだけでなくVoxeoも紹介しています。今後、developerWorksでもVoxeoに関する記事が増えるでしょう。

音声アプリケーションを構築するために最もよく使用されている標準は、VoiceXMLです。ほとんどのVXMLブラウザーがVoiceXML 2.0をサポートしています。この記事でも、このバージョンのVXMLを使用します。VXMLは、W3C仕様に準拠し、急速に拡張されていますが、まだv2.1です。VXML 3.0も垣間見えてきました。

CCXMLは、Call Control XMLの略称で、テレフォニー・マークアップのW3C仕様を満たす最も新しいプレイヤーです。CCXMLは、ほとんどのVoiceXML実装より高度であり、コールバック、イベント・リスナー、多回線および多者通話セッションのサポートを提供します。ただし、これらの機能を特に必要としない場合は、より安定していて、広く使用されているVoiceXMLを使用し続ける方がよいでしょう。

CallXMLは、Voxeoに固有のプラットフォームです。CallXMLは、非常に覚えやすく、タッチトーン入力に対する優れたサポートを備えています(音声認識をサポートしていない点に注意してください)。CallXMLの大きな欠点は、ベンダー固有であることです。Voxeoは豊富な情報を備えた優れたサイトですが、特定のベンダーに縛られるのは、良い考えとはいえません。やはり、ほとんどの開発者のニーズを満たすのはVoiceXMLであると言えます。


VoiceXML 101

VoiceXML全体像の中のJava部分に踏み込む前に、VoiceXMLアプリケーションがどのように機能するか、基本的なことを理解しておく必要があります。そのために、ごく単純なVoiceXMLアプリケーションをざっと見てみましょう。このサンプル・アプリケーションによって、VXMLファイルに慣れることができ、また、この記事の説明に不可欠なVoxeoコール割り当てサービスにアクセスして使用することができます。

単純なVXMLページ

VoiceXMLは、少なくとも1つのVXMLファイルで始まります。これは、XMLのVoiceXML版であり、テレフォニー・アプリケーションにすべきこととできることを知らせるために使用されます。リスト1は、非常に単純なVXMLファイルです。このファイルをローカル・マシンに保存してください(「ダウンロード」から完全なサンプル・ソース・コードをダウンロードできますが、いずれにしても、これらのファイルを自分で使えるように慣れておく必要があります)。


リスト1.非常に単純なVXMLファイル
                
<?xml version="1.0" encoding="UTF-8"?>

<vxml version="2.1">
  <form>
    <block>
      <prompt>
        Things are working correctly! Congratulations.
      </prompt>
    </block>
  </form>
</vxml>


これは、VoiceXMLの基本です。構文について不明な点がある場合は、「参考文献」にリストされている他のVoiceXML記事を参照してください。リスト1のVXMLファイルは1つのプロンプトから成り、双方向性を備えていません。より高度なVoiceXMLの使用については、Javaコードの操作に関するセクションで説明します。今のところは、このシンプルなテスト・ケースを使用して、環境が正しく動作していることを確認してください。

アプリケーションをアップロードする

次に、VXMLファイルをパブリック・アクセスが可能な場所に置きます。ISPと契約している場合は、自分のWebサイトにVXMLファイルをアップロードするだけです。Webのルートとは別にVoiceXMLファイル用のディレクトリー(/voicexmlまたは/voiceなど)を作成した方がよいかもしれません。そのディレクトリーとファイルがWebアクセス可能であることを確認してください(この点が不明な場合は、システム管理者またはISPに問い合わせてください)。

VXMLアプリケーションがオンラインになったら、そのURLをWebブラウザーに入力して、アクセスできるかどうかを確認してください。ブラウザーによっては、XMLファイルをダウンロードするかどうかたずねられる場合があります。そうでない場合は、ブラウザーがXMLファイルを何らかの形式で表示します。これはVXMLを使用できることを確認するためのテストにすぎないので、コンピューターからの問いかけがなくても気にしないでください。VXMLがオンラインになると、それを電話番号にリンクする準備ができたということになります。

アプリケーションに電話番号を割り当てる

まだVoxeoにサインアップしていない場合


まだVoxeoにサインアップしてアカウントを作成していない場合は、今すぐサインアップしてください。この先の例をたどるには、Voxeoツールが必要です。アカウントの作成は無料で、何の義務も伴わずに優れたツールとサポートを利用できます。今すぐサインアップして、デベロッパー・アカウントを作成してください。

従来のWebアプリケーションと違って、Webブラウザーを開くだけでVXMLファイルに辿り着けるわけではありません。少なくとも、音声による応答を望む場合でなくてもです。電話ベースのアプリケーションをテストするには、電話、つまり、電話番号が必要です。VoiceXMLアプリケーションに電話番号をマッピングするための高価なアプローチはいろいろありますが、Voxeoには、テスト、ステージング、および開発用に、優れた無料のマッピング・サービスが用意されています。

Voxeo.comに移動し、ログインしてください(ページ左上のフィールドを使用します)。図1に示されているように、「Account」メニューから「Application Manager」を選択します。


図1.Voxeo Application Managerを表示する
Voxeo Application Managerを表示する

Add Application」を選択した後に、開発プラットフォームとして「VoiceXML 2.0」を選択します。

次に、VXMLファイルのURLとアプリケーションの名前を入力します。アプリケーション名は、参照しやすいものならどのような名前でもかまいません。図2に、マイVXMLファイルにアクセスするための設定を示します。「Application Phone Number」ドロップダウン・リストから「Staging」オプションを選択します。これにより、一時的な作業用電話番号がアプリケーションに割り当てられます。これで、実際に電話からアクセスできるようになります。


図2.VXMLファイルの電話番号へのマッピング
VXMLファイルの電話番号へのマッピング

Create Application」をクリックすると、Voxeoがいくつかの電話番号をアプリケーションに割り当てます。図3に、VXMLファイルへのさまざまなアクセス・ポイントが表示された結果画面(少し下へスクロールしてください)を示します。


図3.マッピング成功!
マッピング成功!

この機能だけでも、時間をとってVoxeoにサインアップする価値があります。これで、市外局番、800番番号(フリーダイヤル)、SkypeなどからVXMLファイルにアクセスできるようになりました。Voxeoツールを使用しなくてもアプリケーションをテストできるのですから、よいサービスです。さらによいことに、Voxeoサイトのアカウントがなくても、上司にテストしてもらうことができます。

アプリケーションをテストする

最後に残った作業は、Voxeoが表示した番号の1つに電話をかけるのみです。ダイヤルすると、VXMLアプリケーションが電話に出て、「Things are working correctly! Congratulations.」と(面白みのない機械音声で)応答するはずです。

これだけです。5分ほどで、電話からXMLファイルに話しかけられるようになりました。さて、これで、Javaコードに踏み込んで、VXMLの動的な生成について説明する準備ができました。


JavaとVXML

現時点では、ほとんどのJava開発者は自分のJavaサーブレットの中からVXMLコードを書き、数百個のout.println()ステートメントに追加し、出力のコンテンツ・タイプを心配しています。そして、一般に、多くのアプリケーションに不必要な複雑さを盛り込もうとしています。このような、より複雑なプログラミング・タスク(すべて、正しく使用すれば有用なものばかりです)を始める前に、このセクションでは、ごく基本的なVoiceXMLサーブレットのプログラミングに挑戦してみましょう。

VXMLファイルのプロトタイピング

はじめに、VXMLファイルを開発します。IDEを開いたり、Javaのコーディングを始めたりする必要はありません。テキスト・エディターを起動するだけです。そして、すぐにパッケージを追加して、ステートメントをインポートしたいという欲求に逆らってください。代わりに、この記事ですでに見たような単純なVXMLファイルを作成します。

たとえば、リスト2は、もう1つのごく基本的なVXMLファイルです。これは音声認識VXMLファイルであり、好きな楽器音を聞き取って、発信者の選択に応じて何らかのコメントを返します。


リスト2.もう1つの基本的なVXMLファイル
                



<?xml version="1.0" encoding="UTF-8"?>

<vxml version="2.1">
  <form id="MainMenu">
    <field name="instrument">
      <prompt>What is your  favorite musical instrument?</prompt>

      <!-- Insert an inline grammar -->
      <grammar type="text/gsl">
        [guitar mandolin dobro (violin fiddle) banjo]
      </grammar>

      <!-- Handle the case when they give no answer -->
      <noinput>
        Did you say something? I didn't hear you.
        <reprompt />
      </noinput>

      <!-- Handle the case when no match is found -->
      <nomatch>
        I suppose that's OK, but it's not on my top five. 
        Want to try again?
        <reprompt />
      </nomatch>
    </field>

    <!-- Handle the various options. -->
    <filled namelist="instrument">
      <if cond="instrument == 'guitar'">
        <prompt>That's right! Hang up and go practice.</prompt>
      <elseif cond="instrument == 'mandolin'" />
        <prompt>Nice... and only four strings to keep in tune.</prompt>
      <elseif cond="instrument == 'dobro'" />
        <prompt>Boy, that's no fun to learn, is it?</prompt>
      <elseif cond="instrument == 'violin'" />
        <prompt>We call that a fiddle, Mr. Fancy Pants.</prompt>
      <elseif cond="instrument == 'fiddle'" />
        <prompt>Does playing classical music on a 
        fiddle make it a violin?</prompt>
      <elseif cond="instrument == 'banjo'" />
        <prompt>Wow, I hope you live alone.</prompt>
      </if>
    </filled>
  </form>
</vxml>


このVXMLを書いて保存し、ISPにアップロードして、番号を割り当ててください。これらのステップのすべてを実行し、VXMLが機能していることを確認したら、Javaのコーディングについても考える準備ができたことになります。

直接Javaに飛び込むと、おそらく出力でもコードでも間違いを犯すでしょう。その結果、VXMLファイル(XML)とサーブレット(Java)を、デバッグしにくいことで有名なWebフレームワークの中で、同時にデバッグするはめになります。(しゃれを言うつもりはなく)これらのすべての変数を追加する代わりに、実用的なVXMLファイルから始めてください。そうすれば、すぐにJavaコードを走らせることができます。

ファイルの読み込み

VXMLを使用する準備ができたら、いよいよコードにとりかかります。まず、VXMLファイルを読み込むだけのサーブレットから始めます。リスト3は、それだけ、すなわち、リスト2で作成したVXMLを読み込むだけのサーブレットです。出力はないので、期待しすぎないでください。


リスト3.VXMLファイルの読み込み
                
package com.ibm.vxml;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;

public class VoiceXMLServlet extends HttpServlet {

  private static final String VXML_FILENAME =
    "simple-voice_recog.xml";

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    String vxmlDir = getServletContext().getInitParameter("vxml-dir");

    BufferedInputStream bis = null;
    ServletOutputStream out = null;

    try {
      // Load the VXML file
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Output the VXML file 
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // output the VXML
      }
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }
}


このコードは、かなり単純です。サーブレットの構成コンテキスト内のディレクトリーと定数ファイル名によって指定されたXMLファイルを読み込んで、そのファイルの内容を反復します。ファイルのパスをサーブレットにハードコード化してもかまいませんが、少なくともディレクトリー名は、サーブレットのコンテキストのWEB-INF/ディレクトリーにあるWeb.xmlファイルに格納する方がよいでしょう。リスト4に、Web.xmlのコンテキスト・パラメーターを示します。


リスト4.サーブレットのコンテキスト・パラメーター
                
<context-param>
    <param-name>vxml-dir</param-name>
    <param-value>/path-to-your-voicexml-dir/voicexml</param-value>
  </context-param>



サーブレットをコンパイルして、それをWebブラウザーで読み込もうとしても、空白の画面しか表示されません。それでも、このことを確かめておいてください。エラーが表示された場合は、訂正する必要があります。たとえば、ファイル・アクセスの問題やVXMLファイル・パスのタイプミスなどは、よくある間違いです。空白の画面が表示されたら、VXMLファイルを実際に出力する準備ができたことになります。

サーブレットからのVXMLの出力

まず、出力オブジェクトにアクセスして、内容をブラウザーに送ることができるようにする必要があります。これは非常に簡単です。

// Load the VXML file
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Let the browser know that XML is coming
      out = res.getOutputStream();
            

ファイルそのものから内容を吐き出すのも簡単です。1行のコードでできます。

// Output the VXML file 
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // output the VXML
        out.write(readBytes);
      }

これで十分なように見えるかもしれませんが、XMLを送ることをブラウザーに知らせる必要があります。ご承知のように、ブラウザーはHTMLに慣れているため、XMLを受け入れたがらない場合があります。この場合も、HttpServletResponseオブジェクトを使用して、コンテンツ・タイプとそのコンテンツの長さを設定することができます。

 // Let the browser know that XML is coming
      out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());
            

リスト5は、このコードのすべてを、リスト3で見たサーブレットに追加したものを示しています。


リスト5.VoiceXMLServlet(VXMLファイルを読み込むことができる完成版)
                



package com.ibm.vxml;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;

public class VoiceXMLServlet extends HttpServlet {

  private static final String VXML_FILENAME =
    "simple-voice_recog.xml";

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    String vxmlDir = getServletContext().getInitParameter("vxml-dir");

    BufferedInputStream bis = null;
    ServletOutputStream out = null;

    try {
      // Load the VXML file
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Let the browser know that XML is coming
      out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());

      // Output the VXML file 
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // output the VXML
        out.write(readBytes);
      }
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }
}

サーブレットによって読み込まれたVoiceXMLのテスト

これらの変更を加えたサーブレットをコンパイルして、必要に応じてサーブレット・エンジンを再起動します。ブラウザーでサーブレットを表示し、図4のような出力が表示されたら、成功です!


図4.VoiceXMLサーブレットによるVXMLの出力
VoiceXMLサーブレットによるVXMLの出力

このような出力が表示されない場合は、ファイルが指定したとおりの場所にあることと、パーミッションに問題がないことを確認してください。サーブレット・エンジンのログを調べたり、システム管理者に問い合わせてみることもできます。

さて、電話番号をサーブレットにマップする準備ができました。Voxeo.comのApplication Managerに戻って、新しいアプリケーションを追加します(おそらく、以前に作業したアプリケーションが表示されているはずです)。VoiceXML 2.0を選択して、新しいアプリケーションの名前とサーブレットのURLを入力します。Voxeoがアプリケーションを作成して、電話番号を割り当てます。

この新しい番号にダイヤルすると、リスト2のVXMLからのプロンプトが聞こえるはずです。おめでとう!VXMLを出力するJavaサーブレットを書いて、それに電話番号を引っ掛けただけです。

追加オプション

サーブレットのコードに2つの小さな追加を加えた方がよいかもしれません。どちらも必須ではありませんが、既存のバージョンに若干の堅牢性とドキュメンテーションを付け加えます。

まず、ユーザーがPOST要求を通じてVXMLにアクセスできるようにできます。これは、ユーザーがフォームのボタンをクリックして、そのフォームがVoiceXMLServletにPOST要求を行った場合に発生します。サーブレットでの処理は、かなり簡単な操作です。すでにあるdoGet()メソッドに委任するdoPost()を書くだけです。

public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    doGet(req, res);
  }


もう1つの簡単な追加は、VXMLファイルの内容を出力することを実際にブラウザーに知らせることです。このためには、サーブレットのContent-dispositionレスポンス・ヘッダーを次のように設定します。

// Let the browser know that XML is coming
      out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());
      res.addHeader("Content-Disposition",
        "attachment; filename=" + vxml);
            

これにより、レスポンスを読み取るブラウザー(またはその他のコード)は、サーブされたVXMLファイルを発見することができます。ただし、完全なファイル・パスを含めないようにしてください。セキュリティー・リスクとなります!


動的VoiceXML

VXMLファイルを出力するサーブレットができたら、そこから(そのコードをモデルまたはテンプレートとして使用して)VXMLを動的に出力するサーブレットを作成するのは、かなり簡単です。言い換えると、単に静的なVXMLファイルを読み込むことから出発して、VXMLのプログラマティックな作成を始めることができます。

Javaプラットフォームが実際に輝き始めるのは、動的VoiceXMLに踏み込んだときです。Javaプラットフォームは、XMLを容易に出力するだけでなく、データベース、ディレクトリー・サーバー、認証ストア、およびセッションと対話する機能も提供します。結局のところ、動的VXMLの構築は、音声ベース・システムの堅苦しさを取り除くことにもなります。

このセクションでは、動的VXMLを出力するJavaサーブレットの作成をご紹介します。

out.println()によるVXMLの出力

ServletOutputStreamにアクセスして、その出力ストリームにバイトを挿入する方法はすでに見ました。しかし、ソース(静的VXMLファイルなど)から出力ストリームへバイトを移すだけでない場合、バイトを直接扱うのは、それほど簡単ではありません。

自分でVXMLを作成したい場合は、PrintWriterを使う方がいいでしょう。そのクラスで文字列全体を押し出すことができ、動的コンテンツの作成と出力がより便利になります。必要なのは、次に示すように、コードにちょっとした変更を加えるだけです。

  
public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    String vxmlDir = getServletContext().getInitParameter("vxml-dir");

    BufferedInputStream bis = null;
    ServletOutputStream out = null;

    try {
      // Load the VXML file
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Let the browser know that XML is coming
      PrintWriter out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());

      // Output content using PrintWriter
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }

java.io.PrintWriterクラスをインポートすることも忘れないでください。サーブレットのコード・ベースから自動的に使用可能になるわけではありません。

PrintWriterによって、文字列ベースのコンテンツを出力できるようになりました。たとえば、リスト6リスト1で見たのと同じVXMLを出力しますが、サーブレット経由である点が異なり、静的ファイルからVXMLコンテンツを読み込むわけではありません。


リスト6.VXMLの動的な出力
                



package com.ibm.vxml;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;

public class DynamicVoiceXMLServlet extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    BufferedInputStream bis = null;
    PrintWriter out = null;

    try {
      // Let the browser know that XML is coming
      out = res.getWriter();
      res.setContentType("text/xml");

      // Output VXML
      out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
      out.println("<vxml version=\"2.1\">");
      out.println(" <form><block><prompt>");
      out.println("  Things are working correctly! Congratulations.");
      out.println(" </prompt></block></form>");
      out.println("</vxml>");

    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }

  public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    doGet(req, res);
  }
}

リスト1でしたのと同じように、このサーブレットをコンパイルして、Voxeoに登録し、電話でアクセスすることができます。では、Javaのような言語の動的プログラミング機能を明らかにする例をいくつか見てみましょう。

時間対応の追加

サーブレット・ベースのVXML出力でできる最も簡単なことの1つは、ある程度の時間対応の追加です。Javaコードで現在日時を把握するのは簡単なことなので、ここから始めるとよいでしょう。

Calendarクラスを使用して、時間(または現在の日付に関する何でも)を簡単に取得できます。リスト7は、Calendarクラスの新しいインスタンスを取得し、時間(24時間形式で返されます)を取得し、その時間に基づいた簡単な挨拶を作るコードを示しています。


リスト7.VXMLの動的な出力
                



package com.ibm.vxml;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import javax.servlet.*;
import javax.servlet.http.*;

public class DynamicVoiceXMLServlet extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    BufferedInputStream bis = null;
    PrintWriter out = null;

    try {
      // Let the browser know that XML is coming
      out = res.getWriter();
      res.setContentType("text/xml");

      // Output VXML
      out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
      out.println("<vxml version=\"2.1\">");
      out.println(" <form><block><prompt>");

      // Output a greeting based on the time of day
      Calendar cal = Calendar.getInstance();
      int hour = cal.get(Calendar.HOUR_OF_DAY);
      if (hour < 6) {
        out.println("You're up early. Good morning.");
      } else if (hour < 12) {
        out.println("Good morning. How's your day so far?");

      } else if (hour < 18) {
        out.println("Half the day is done... good afternoon!");
      } else{
        out.println("Hope you are enjoying your evening.");
      }

      out.println(" </prompt></block></form>");
      out.println("</vxml>");

    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }

  public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

    doGet(req, res);
  }
}

発信者とVXMLジェネレーターの時差

リスト7は、VoiceXMLと動的に生成されるVXMLのもう1つの特徴も示しています。すなわち、発信者とVXMLそのものの時差の可能性です。たとえば、ニュージーランドに住んでいるユーザーがリスト7に示されているアプリケーションに電話したとします。ニュージーランドが午後10時でも、VXMLを出力するサーバーがコロラド州デンバーにある場合、「早起きですね。おはようございます。」などのおかしな挨拶になってしまいます。これだけならまだしも、もっと困ったことになる可能性もあります。たとえば、特定の曜日向けの挨拶を追加した場合、実際に不一致が起こってしまいます。

基本的な問題の原因は、VXMLとJavaが特定のサーバーのロケールと時間帯で実行しているにもかかわらず、発信者は世界中のどこからでもそれらを使用できる点にあります。この点を考慮していないサーブレットは、発信者を戸惑わせることになります。いくつかの選択肢があります。

  • 時差を無視して、サーバーが別の時間帯でコードを実行していることを発信者が理解してくれることに期待します。
  • 時刻と日付がサーバーの現地時間であることを明言します。たとえば、午後の挨拶は、「こちらは午後です。あなたもよい1日をお過ごしのことと思います。」などとします。
  • 時間またはGMTからの時差を尋ねるコードを書いて、その情報に基づいて挨拶を作成します。

あいにく、これらのどの方法も、魅力的な選択肢ではありません。最初の方法は、基本的に発信者を無視するということです。発信者を無視するのは、ビジネス上問題があるのは言うまでもありません。2番目のアイデア、すなわち、現地時間を述べて、それがローカルであることを明言すると言うのも、あまりよいアイデアではありません。やはり、発信者を軽視していることになるからです。少し気を使っているだけに過ぎません。

最後のオプションは、一見、よさそうに思えます。ユーザーにGMTとの時差を指定してもらって、それに基づいて応答するVXMLを書くのは簡単です。しかし、発信者はできるだけ速く情報を得たいと思っています。応答プロンプトが多くなるほど、発信者が苛立って、通話を切ってしまう可能性が高くなります。したがって、時間または日付ベースのサービスを提供する場合を除いて、発信者に時間帯の指定を要求するのは、無駄なプロンプトを増やすだけです。さらに悪いことに、多くの発信者はGMTとの時差を知らないので、時間帯、時間帯の略記、夏時間などをサポートしなければならなくなり、そのようなサポートの項目は、増えていく可能性があります。

なぜ、わざわざ?

では、なぜ日付ベースのVXML生成に触れたのでしょうか。まさにこれらの問題を説明するためです。対象ユーザーに気を配る必要があり、自分のサーバーや自分の地域ではなく、ユーザーに関連した情報を提供するように努める必要があります。

日付ベースの処理の場合、おそらく最後の、発信者への対応としてより良いオプションを採用すべきであり、絶対必要でない限り、日時に基づくトランザクションも避けるべきでしょう。他の時間帯からの発信者を予想している場合、時間関連の機能を提供しようとすることはトラブルの元です。同じ原則が、州、国、または大陸によって変わるあらゆるデータに適用されます。

最後に、サーブレットを使用してVXMLを出力するのが、それほどよいアイデアではないケースも多々あります。静的ファイルからVXMLを吐き出すだけでは、得るものは少なく(おそらく、ごく限られた柔軟性くらいです)、コード、コンパイル、デバッグ、サーブレット・エンジンなど、音声アプリケーションの複雑さが増すだけです。このような単純な場合は、静的VXMLファイルの使用にとどめてください。


面白いアイデア

この記事で見てきたように、ときにはサーブレットによって生成されたVXMLが意味を成さないこともあります。しかし、それでおしまいにする前に、Javaなどの言語の使用が、優れた電話アプリケーション・ソリューションになるケースを考えてみてください。ここでは詳しく説明しませんが、今後の記事に期待してください。

データベースからのVXMLの読み込み

VoiceXMLに関するJavaの最も明白なアプリケーションは、データベースを使用した動的VXML出力のフィードです。これはおそらく、この記事を読み始めたときに読者の多くが知りたいと思っていたことではないでしょうか(これを中心的な例として説明しても、それほど多くを学べなかったと思いますが)。いずれにしても、JDBCはデータベースへの接続と、SQLクエリー結果を使用したVXMLのポピュレートを容易にします。

たとえば、VXMの文法情報のすべてを含んだテーブルを作成して、その文法を、出力する各VXMLファイルに読み込むことができます。VXMLファイルごとに文法をコード化しなくても、同様のファイル間で文法を共有することができます。さらに良いことに、すべてのサーブレットまたは特定のサーブレットのインスタンスにこれらの文法をプリロードすれば、文法をデータベースに格納するメリットとして、要求ごとに文法を読み込むコストをかける必要がなくなります。

ユーザー・クリデンシャルに基づくVXMLの読み込み

特にサーブレット、JSP、およびWebベース・プログラミングに関して、Javaのもう1つの優れた特徴は、ユーザー・クリデンシャルをセッションに格納できることです。これにより、認証と承認が可能になり、非常に高度にカスタマイズされたコンテンツも可能になります。

たとえば、最初にユーザーID番号とPINを尋ねる音声アプリケーションを考えてみてください(今日のほとんどのバンキング・アプリケーションや金融アプリケーションのように)。これらのクリデンシャルをデータベースと照合して認証し(すでにJavaプラットフォームの注目すべき強みとなっています)、発信者のIDをセッション変数に格納することができます。こうすると、発信者からの要求に答える各JavaサーブレットまたはJSPは、それらのクリデンシャルに基づいてユーザーに提供するオプションを判断することができます。

VoiceXMLに代わる多くのものが同様の機能を提供していますが、それらのアプリケーションのWeb版とコードを共有できる機能を誇っているものは、ほとんどありません。言い換えると、Javaプラットフォームでは、VoiceXMLとWeb版アプリケーションの間で、データベースだけでなくコードのコンポーネントも共有できます。VXMLを生成するサーブレットは、HTMLやXGTMLを生成するサーブレットと同じ認証およびパーミッション・ユーティリティー・クラスを使用することができます。電話に応答するJSPは、キャッシュしたデータベース接続を、HTTP要求を処理するJSPと共有することができます。結果として、複数のタイプのクライアントを扱えるアプリケーション・インフラストラクチャーができあがり、クライアントのタイプごとにアプリケーション全体を作成する必要がありません。


まとめ

この記事では、VXMLとJavaプラットフォームでできることのほんの表面をなぞっただけにすぎません。VXMLを作成するプロセスを紹介し、そのプロセスにJavaテクノロジーを統合する方法を示しました。その過程で、Javaコードを使用してリッチで動的なVoiceXMLアプリケーションを開発するためのさまざまな面白い方法についてヒントを示しました。

また、VoiceXML開発者が音声アプリケーションで間違えやすいJavaテクノロジーの使用方法についても示しました。日付と時間を出し抜こうとしたり、ロケール・ベースのサービスを試みたり、サーバーのローカル時間と発信者のローカル時間の差を考えないと、確実にユーザーに反感を持たせたり、苛立たせることになります。Javaは、DateおよびCalendarクラスのショーケースではなく、VoiceXMLのためのツールだと考えてください。

今後の記事でも、これらのトピックについて書いていくつもりです。この記事で述べた原則から出発して、さらに詳しく説明します。リッチな音声アプリケーションの構築、データベースと相互作用する電話アプリケーションの開発、ユーザーの追跡、パーソナライズ・コンテンツの提供などについてさらに知りたい人は、このシリーズから目を離さないでください。また、Voxeo.comに戻って、1つか2つのサーブレットを使用してあなたのVXMLを処理してみてください。そして、来月また、ここに戻ってきてください。



ダウンロード

内容ファイル名サイズダウンロード形式
Example code for this articlewa-voicexml.zip1KBHTTP

ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために

議論するために

  • developerWorks blogsに参加して、developerWorksのコミュニティーに加わってください。

著者について

Photo of Brett McLaughlin

Brett McLaughlin氏は、Logo (小さな三角形を覚えていますか?) の時代からコンピューターの仕事をしています。現在の専門は、JavaおよびJava関連のテクノロジーを使ったアプリケーション・インフラストラクチャーの構築です。ここ数年は、Nextel Communications and Allegiance Telecom, Inc. でこれらのインフラストラクチャーの実装に携わっています。Brett氏は、Javaサーブレットを使ってWebアプリケーション開発のための再利用可能なコンポーネント・アーキテクチャーを構築するJava ApacheプロジェクトTurbineの共同設立者の1人です。同氏はまた、オープン・ソースのEJBアプリケーション・サーバーであるEJBossプロジェクトと、オープン・ソースのXML Web公開エンジンであるCocoonにも貢献しています。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, XML, Java technology
ArticleID=239924
ArticleTitle=Java Web開発者フレームワーク内でのVoiceXMLページの作成 : XML
publish-date=01172006
author1-email=brett@newInstance.com
author1-email-cc=dwxed@us.ibm.com

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。