(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Создание VoiceXML-страниц в интегрированной среде Web-разработки на языке Java

Брэт Маклафлин

За последние пять лет Web-технология распространилась наверное дальше, чем за любой другой период своей истории. То, что раньше было, по существу, текстовой средой для программ, называемых Web-браузерами, стало информационным источником для любого устройства, обладающего коммуникационными возможностями. Сначала к устройствам, способным обращаться к Web-страницам, присоединились мобильные телефоны, за которыми последовали пейджеры, наладонные устройства, персональные планировщики и все, что могло соединяться без проводов с Web. За последние годы к ним примкнула традиционная телефония, и стало популярным желание сделать Web-программы доступными по обычным телефонным линиям.

Эту последнюю категорию приложений, где пользователь обращается к интерактивным службам по телефону, лучше называть телефонными приложениями . Поскольку телефоны, очевидно, нельзя использовать по методу "нажми на ссылку", почти все взаимодействия с приложением управляются голосом. Вместо нажатия на ссылку пользователь говорит "Информация по счету", либо использует клавиатурную панель, следуя предписанным инструкциям.

Способность обслуживать телефоны посредством существующих или слегка модифицированных Web-приложений является мощной идеей, одной из тех, которые хотели бы исследовать многие Web-разработчики. Самым важным фактом о Web и телефонных приложениях является то, что вы можете использовать практически один и тот же набор технологий для создания обоих типов приложений. HTML, XHTML и XML являются тремя самыми общими технологиями, лежащими в основе Web-интерфейсов, а VoiceXML (или VXML) является родственной технологией, делающей Web-взаимодействия доступными для телефонных клиентов. JavaServer Pages и сервлеты, PHP-сценарии и Ruby-приложения - все они могут отвечать на телефонные запросы так же легко, как и на поступающие запросы от наладонных устройств или от Web-браузеров. В данной статье я сконцентрируюсь на использовании Java-платформы для управления простыми VoiceXML-приложениями, но вы можете применить большую часть рассматриваемой информации равным образом и к PHP, Perl или другому предпочитаемому вами языку программирования.

VoiceXML, CCXML или CallXML?

 
Начало работы с Voxeo!

Вы должны создать бесплатную учетную запись Voxeo-разработчика для выполнения упражнений данной статьи. Хотя Voxeo не является обязательной службой для VoiceXML, она предоставляет отличный набор инструментальных средств, а также тысячи страниц документации по VoiceXML, CallXML и CCXML. Данная статья служит введением как в Voxeo, так и в VoiceXML-программирование, и вы можете ожидать услышать в будущем еще больше о Voxeo на developerWorks.

Самым широко используемым стандартом для создания голосовых приложений является VoiceXML. Большинство VXML-браузеров поддерживают VoiceXML 2.0, который является VXML-версией, используемой в данной статье. VXML - это W3C-спецификация, которая быстро расширяется, но пока остановилась на версии 2.1. На горизонте просматривается версия VXML 3.0.

CCXML обозначает Call Control XML (XML для управления вызовом) и представляет собой самый новый проигрыватель, отвечающий W3C-спецификации для телефонного языка разметки. CCXML является более продвинутой, чем большинство реализаций VoiceXML, предлагая поддержку функций обратного вызова, прослушивателей событий, многострочных и составных сессий. Но если вам специально не нужны эти функции, для вас, вероятно, более подошла бы VoiceXML, которая является более стабильной и широко используемой реализацией.

CallXML является платформозависимым для Voxeo. CallXML очень легко изучить, и он обеспечивает отличную поддержку тонального набора (обратите внимание на то, что он не поддерживает распознавание голоса). Большим недостатком CallXML является его зависимость от поставщика. Хотя Voxeo является хорошим сайтом с массой ресурсов, привязка к конкретному поставщику никогда не была хорошей идеей. Опять же, большинство разработчиков обнаружит, что VoiceXML подходит под их требования.

VoiceXML 101

Перед рассмотрением VoiceXML-картины со стороны Java вы должны иметь общее представление о работе VoiceXML-приложения. С этой целью я кратко рассмотрю очень простое VoiceXML-приложение. Пример приложения будет использоваться для просмотра VXML-файлов, предоставляя также доступ (и возможность использования) к предоставляемой по вызову Voxeo-службе (call-assignment service), что является ключевым для оставшейся части статьи.

Простая VXML-страница

VoiceXML начинается, по крайней мере, с одного VXML-файла. VoiceXML-версия XML используется для информирования телефонных приложений о том, что они должны (и могут) делать. В листинге 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. VXML-файл в листинге 1 состоит из одного элемента prompt (напоминание) и не предлагает какой-либо интерактивности; вы увидите более сложное использование VoiceXML в разделах о работе с Java-кодом. А пока используйте этот простой пример для проверки корректности работы вашей среды.

Загрузка приложения для общего доступа

Затем поместите ваш VXML-файл куда-нибудь для общего доступа. Если у вас есть ISP, просто загрузите VXML-файл на ваш Web-сайт; возможно, вы захотите создать каталог для ваших VoiceXML-файлов вне корневого Web-каталога, например, /voicexml или /voice. Убедитесь в том, что каталог и файл доступны в Web (проконсультируйтесь с вашим системным администратором или ISP, если вам не понятно, как это сделать).

В том случае, если у вас нет доступа к ISP, вы можете подписаться в Voxeo на использование файлового менеджера (File Manager) на сайте. Вы должны уже иметь учетную запись Voxeo, которая предоставляет вам 10 MB пространства для хостинга, т.е. это отличный бесплатный вариант (10 MB - это много VXML-файлов!).

После того, как ваше VXML-приложение будет доступно в интерактивном режиме, вы, наверное, захотите проверить возможность доступа к нему, введя URL в ваш Web-браузер. В зависимости от браузера может появиться либо запрос на загрузку XML-файла, либо он каким-либо образом визуализируется вашим браузером. Это просто тест для проверки доступности VXML, поэтому не переживайте, если ваш компьютер не начал разговаривать с вами. Теперь вы готовы привязать VXML к телефонному номеру.

Назначение телефонного номера вашему приложению

 
Последний звонок для Voxeo!

Если у вас все еще нет учетной записи в Voxeo, сейчас самое время создать ее. Вам понадобятся инструментальные средства Voxeo для выполнения приведенных в статье примеров. Создание учетной записи является бесплатной процедурой без каких-либо обязательств. Вы получаете отличные инструментальные средства и поддержку.

В отличие от традиционных Web-приложений, вы не можете просто открыть Web-браузер и использовать ваш VXML-файл; по крайней мере, это не так, если вы хотите иметь голосовую реакцию. Для тестирования телефонного приложения вам, очевидно, понадобится телефон и номер, на который можно позвонить. Существует большое количество дорогостоящих способов отображения номеров на VoiceXML-приложения, но для тестирования и разработки Voxeo предлагает отличную бесплатную службу отображения.

Рисунок 1. Вызов Voxeo Application Manager
Рисунок 1. Вызов Voxeo Application Manager

Выберите Add Application, а затем VoiceXML 2.0 в качестве вашей платформы разработки.

Затем, укажите URL для вашего VXML-файла, а также название вашего приложения; вы можете использовать любое название, поскольку оно используется только в качестве справочной информации. На рисунке 2 показаны настройки для доступа к моему VXML-файлу. В ниспадающем списке Application Phone Number выберите вариант Staging. При этом приложению назначается временный телефонный номер, то есть, вы можете сделать реальный звонок с вашего собственного телефона.

Рисунок 2. Отображение VXML-файла на телефонный номер
Рисунок 2. Отображение VXML-файла на телефонный номер

Нажмите кнопку Create Application, и Voxeo назначит несколько телефонных номеров вашему приложению. На рисунке 3 показан получаемый экран (немного прокученный вниз) со всеми различными точками доступа к VXML-файлу.

Рисунок 3. Успешное отображение!
Рисунок 3. Успешное отображение!

Только одна эта функциональная возможность стоит времени, потраченного на регистрацию в Voxeo; теперь вы можете обратиться к вашему VXML-файлу по междугородному телефонному номеру, по номеру 800 и по Skype. Это здорово, поскольку вам не нужно использовать инструментальные средства Voxeo для тестирования вашего приложения. Еще лучше то, что вы можете позволить выполнить тестирование вашему начальнику без необходимости создавать дополнительную учетную запись на сайте Voxeo!

Тестирование приложения

Все что осталось сделать - позвонить по одному из номеров, предоставляемых Voxeo. После набора номера ваше VXML-приложение должно поднять трубку и проинформировать вас (бесчувственным механическим голосом), что "Things are working correctly! Congratulations!" ("Все работает нормально. Поздравляем!").

И это все: за пять минут вы имеете телефон, разговаривающий с использованием вашего XML-файла. Теперь вы готовы поработать немного с Java-кодом и узнать о динамическом генерировании VXML.

Java и VXML

На данный момент большинство Java-разработчиков пытается вручную кодировать VXML из своих Java-сервлетов, добавляет в них сотни выражений out.println(), беспокоится о типе выводимого содержимого, и обычно добавляет ненужную сложность во многие приложения. Перед началом выполнения этих более сложных программных задач, которые полезны при правильном использовании, освежите ваши знания, программируя в данном разделе элементарный VoiceXML-сервлет.

Создание прототипа VXML-файла

Для начала разработайте ваш VXML-файл. Не открывайте IDE и не начинайте кодировать в Java; вместо этого просто запустите текстовый редактор и не поддайтесь желанию немедленно добавить операторы package и import. Создайте простой VXML-файл, также как вы делали ранее в этой статье.

Например, в листинге 2 приведен еще один красивый элементарный VXML-файл. Это VXML-файл с распознаванием голоса, выбирающий любимый инструмент и предлагающий некоторый комментарий по выбору звонящего.

Листинг 2. Еще один элементарный 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>

      <!-- Вставить встроенный элемент grammar -->
      <grammar type="text/gsl">
        [guitar mandolin dobro (violin fiddle) banjo]
      </grammar>

      <!-- Обработать ситуацию, когда нет ответа -->
      <noinput>
        Did you say something? I didn't hear you.
        <reprompt />
      </noinput>

      <!-- Обработать ситуацию, когда не найдено совпадение -->
      <nomatch>
        I suppose that's OK, but it's not on my top five. 
        Want to try again?
        <reprompt />
      </nomatch>
    </field>

    <!-- Обработать различные варианты. -->
    <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 приведен сервлет, который делает именно это - загружает VXML, разработанный в листинге 2. Он не выводит никакой информации, поэтому пока не ждите от него многого.

Листинг 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 {
      // Загрузить VXML-файл 
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Вывести VXML-файл 
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // вывод VXML
      }
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }
}


Этот код довольно понятен. Он загружает XML-файл, указанный через каталог в конфигурационном контексте сервлета и постоянное имя файла, а затем выполняет итерацию по содержимому этого файла. Вы могли бы жестко закодировать путь к файлу в сервлете, но значительно лучше сохранить, по крайней мере, название каталога в вашем файле Web.xml, расположенном в каталоге WEB-INF/ вашего контекста сервлета. В листинге 4 приведен параметр context в Web.xml.

Листинг 4. Параметр context для сервлета

  <context-param>
    <param-name>vxml-dir</param-name>
    <param-value>/path-to-your-voicexml-dir/voicexml</param-value>
  </context-param>



Если вы откомпилируете ваш сервлет и попытаетесь загрузить его в Web-браузер, то получите чистый экран; все равно вы должны убедиться, что получаете как минимум это. Если возникают какие-либо ошибки, вы должны исправить их. Например, обычно возникают проблемы с правами доступа к файлам или опечатки в пути к VXML-файлу. Если вы получили чистый экран, значит готовы выполнять реальный вывод VXML-файла.

Вывод VXML из сервлета

Прежде всего, вы должны получить доступ к объекту output, для того чтобы можно было передавать содержимое в браузер. Это достаточно просто:

      
// Загрузить VXML-файл 
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Проинформировать браузер о выводе XML 
      out = res.getOutputStream();


Сама выдача содержимого из файла является простой процедурой; вы просто используете одну строку кода:

      
// Вывод VXML-файла  
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // вывод VXML
        out.write(readBytes);
      }


Хотя этого может показаться достаточно, вам все еще нужно проинформировать браузер о том, что вы передаете ему XML. Помните, браузеры используются для HTML, и некоторые с неохотой принимают XML. Вы можете установить тип содержимого, а также длину этого содержимого, снова используя объект HttpServletResponse:

     
 // Проинформировать браузер о том, что будет передаваться XML 
      out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());

В листинге 5 показан весь этот код, добавленный в сервлет, приведенный в листинге 3.

Листинг 5. Готовый к загрузке VXML-файлов VoiceXMLServlet

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 {
      // Загрузить VXML-файл 
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Проинформировать браузер о том, что будет передаваться XML 
      out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());

      // Вывод VXML-файла  
      int readBytes = 0;
      while ((readBytes = bis.read()) != -1) {
        // вывод VXML
        out.write(readBytes);
      }
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }
}

Тестирование загруженного в сервлет VoiceXML

Откомпилируйте ваш сервлет со всеми этими изменениями и перезапустите ваш контейнер сервлетов при необходимости. Откройте сервлет в браузере; вы должны увидеть вывод, аналогичный изображенному на рисунке 4. Работает!

Рисунок 4. Сервлет VoiceXML, выводящий VXML
Рисунок 4. Сервлет VoiceXML, выводящий VXML

Если вы не видите аналогичного вывода в браузере, убедитесь, что ваш файл находится там, где вы указали, и что у вас нет каких-либо проблем с правами доступа к нему. Вы можете также проверить журналы регистрации вашего контейнера сервлетов (log-файлы), либо попросить помощи у вашего системного администратора.

Теперь вы готовы отобразить телефонный номер на ваш сервлет. Вернитесь к Application Manager сайта Voxeo.com и добавьте новое приложение (возможно, вы увидите приложения, с которыми работали раньше). Выберите VoiceXML 2.0, а затем введите название нового приложения и URL вашего сервлета. Voxeo создаст ваше приложение и назначит ему телефонный номер.

Наберите этот новый телефонный номер; вы должны услышать запрос из VXML, приведенного в листинге 2. Примите мои поздравления! Вы только что закодировали Java-сервлет, выводящий VXML, и назначили ему телефонный номер.

Некоторые необязательные дополнения

Вы, возможно, захотите сделать пару маленьких добавлений в код вашего сервлета. Они не являются необходимыми, но добавляют немного устойчивости и документированности в существующую версию.

Прежде всего, вы можете захотеть позволить пользователям обращаться к VXML через POST-запрос. Это могло бы случиться, если бы пользователь нажимал кнопку в форме, а эта форма выполняла POST-запрос в сервлет VoiceXMLServlet. Это довольно простая операция для обработки в сервлете; просто напишите версию doPost(), которая делегирует обработку методу doGet(), который у нас уже есть, как показано ниже:

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

    doGet(req, res);
  }


Другое простое дополнение - позволить браузерам узнать, что вы выводите содержимое VXML-файла. Для этого установите ответный заголовок Content-disposition в вашем сервлете:

      
// Проинформировать браузер о том, что будет передаваться XML 
      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. Она обеспечивает возможность простого вывода XML, а также взаимодействия с базами данных, службами каталогов, хранилищами информации для аутентификации и сессиями. Создание динамического VXML позволяет также избежать некоторой формальности голосовых систем.

В данном разделе я поэтапно рассмотрю создание Java-сервлета, выводящего динамический VXML.

Вывод VXML через out.println()

Вы уже видели, как обратиться к 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 {
      // Загрузить VXML-файл
      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);
      FileInputStream fis = new FileInputStream(vxml);
      bis = new BufferedInputStream(fis);

      // Проинформировать браузер о том, что будет передаваться XML 
      PrintWriter out = res.getOutputStream();
      res.setContentType("text/xml");
      res.setContentLength((int)vxml.length());

      // Вывести содержимое, используя PrintWriter
    } finally {
      if (out != null) out.close();
      if (bis != null) bis.close();
    }
  }


Не забудьте также импортировать класс java.io.PrintWriter: он не доступен автоматически для исходного кода вашего сервлета.

При помощи PrintWriter вы можете теперь выводить строковое содержимое. Например, код в листинге 6 выводит такой же VXML, как и код в листинге 1, за исключением того, что это делается через сервлет и без загрузки 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 {
      // Проинформировать браузер о том, что будет передаваться XML 
      out = res.getWriter();
      res.setContentType("text/xml");

      // Вывод 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);
  }
}


Вы можете откомпилировать этот сервлет, зарегистрировать его в Voxeo и обратиться к нему по телефону, так же как вы делали это для листинга 1. Теперь давайте перейдем к некоторым примерам, показывающим возможности динамического программирования такого языка, как Java.

Добавление индикации времени

Одной из простейших функций, которые вы можете сделать с основанным на сервлете выводом VXML является добавление некоторой индикации времени. Тривиальной задачей является получение текущего времени и даты с использованием 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 {
      // Проинформировать браузер о том, что будет передаваться XML 
      out = res.getWriter();
      res.setContentType("text/xml");

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

      // Вывод приветствия, основанного на времени суток
      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: возможное несоответствие между вызывающим объектом и самим VXML. Например, предположим, что пользователь, живущий в Новой Зеландии, вызывает приложение, приведенное в листинге 7. Если в Новой Зеландии 10:00 после полудня, а сервер, выводящий VXML, расположен в Денвере, штат Колорадо, пользователь, вероятно, получит странное сообщение, например "You're up early. Good morning" ("Вы встали рано. Доброе утро"). Это совсем неправильно, а может быть еще хуже: если вы добавите приветствия на конкретный день недели, то действительно столкнетесь с несоответствиями.

Основным источником проблемы являются VXML и Java, работающие с региональными настройками и часовым поясом конкретного сервера, но доступные для вызова повсеместно. Если ваш сервлет не учитывает этого, некоторые ваши пользователи будут озадачены. У вас есть несколько вариантов:

  • Игнорировать различия и надеяться, что клиенты поймут, что ваш сервер работает не в их часовом поясе.
  • Явно указывать, что время и даты являются локальными для вашего сервера; например, ваше полуденное приветствие могло бы быть таким, "У нас полдень. Я желаю вам приятного дня в любом случае".
  • Написать код, который запрашивает часовой пояс или сдвиг относительно GMT, и разработать приветствия, основанные на этой информации.

К сожалению, ни один из этих вариантов не является привлекательным. Первый делает точно то, что было сказано: игнорирует пользователя, выполняющего звонок. Следует сказать, что игнорирование клиентов явно не является способом ведения бизнеса. Второй вариант (использовать локальное время и явно указывать это) не намного полезнее, поскольку склоняется к игнорированию пользователя, но просто делает это немного тактичней.

Последний вариант может показаться на первый взгляд привлекательным; легко написать VXML, позволяющий пользователям предоставлять числовой сдвиг относительно GMT и учитывающий это. Однако пользователи обычно хотят получить информацию как можно быстрее; чем больше вопросов вы будете задавать, тем сильнее возрастает риск надоесть пользователям и вынудить их повесить трубку неудовлетворенными. Следовательно, если вы предоставляете службу, требующую от пользователя указания часового пояса, у вас появляется дополнительный запрос. Что еще хуже - многие пользователи не знают своего часового пояса, поэтому вы столкнетесь с необходимостью поддержки часовых поясов, сокращений часовых поясов, времени перехода на летнее время … список может стать большим.

Зачем тогда беспокоиться?

Тогда зачем генерировать зависящие от времени VXML? Главным образом для демонстрации именно этих проблем! Вы должны быть очень деликатными с вашей аудиторией, пытаться предоставлять информацию, релевантную для пользователей, а не для вашего сервера или вашей местности.

В ситуации с обработкой времени вы должны, вероятно, использовать последний, лучший вариант работы с пользователями и полностью избегать основанных на времени и дате транзакций, до тех пор, пока это не будет абсолютно необходимо. Если вы планируете работать с пользователями, находящимися в другом часовом поясе, вы просто напрашиваетесь на проблемы, пытаясь предоставить основанные на времени функциональные возможности. Эти же правила применимы для любых данных, которые могут меняться в зависимости от штата, страны или континента.

Наконец, существует масса случаев, когда использование сервлета для вывода VXML не является хорошей идеей. Если вы просто выдаете VXML из статического файла, то выиграете немного (возможно, чуть-чуть гибкости), но добавите кодирование, компиляцию, отладку, контейнер сервлетов и многое другое к сложности вашего голосового приложения. В таких простых ситуациях придерживайтесь статических VXML-файлов.

Некоторые интересные идеи

Как вы до сих пор видели в данной статье, иногда генерирование VXML в сервлете не имеет смысла. Но перед завершением статьи рассмотрим несколько случаев, когда использование языка программирования, например Java, является отличным решением для телефонного приложения. Я не буду здесь приводить полные примеры, а рассмотрю их в будущих статьях.

Загрузка VXML из базы данных

Наиболее очевидным применением Java в VoiceXML является использование базы данных в качестве источника информации для VXML-вывода. Это, вероятно, именно то, что многие из вас ожидали узнать перед началом чтения данной статьи (хотя вы не захотели бы учить так много уроков, если бы это было главной темой статьи). В любом случае, JDBC упрощает подключение к базе данных и последующее использование результатов SQL-запросов для заполнения VXML.

Например, вы могли бы разработать таблицу, содержащую всю грамматическую информацию для вашего VXM, а затем загружать эту грамматику в каждый выводимый вами VXML-файл. Вместо необходимости кодировать грамматику для каждого VXML-файла вы можете совместно использовать ее в похожих файлах. Еще лучше, вы можете предварительно загружать эти грамматики во все сервлеты или экземпляры конкретного сервлета и пользоваться преимуществами хранения ваших грамматик в базе данных без накладных расходов на загрузку грамматики при каждом запросе.

Загрузка VXML на основе полномочий пользователя

Еще одной хорошей функциональной возможностью Java (особенно по отношению к сервлетам, JSP-страницам и Web-программированию) является способность хранения пользовательских полномочий в сессии. Это позволяет организовать аутентификацию и авторизацию, а также очень настраиваемое содержимое.

Например, рассмотрим голосовое приложение, начинающееся с запроса ID пользователя и PIN (как это делает большинство банковских и финансовых приложений). Вы можете аутентифицировать эти полномочия с использованием базы данных (уже замечательная возможность Java-платформы) и сохранить ID пользователя в сессионной переменной. Затем каждый Java-сервлет или JSP-страница, которые принимают запрос от пользователя, могут вычислить, какой вариант предложить пользователю на основе этих полномочий.

Хотя множество альтернатив VoiceXML предлагают аналогичную функциональность, очень не многие из них могут похвастаться способностью совместно использовать код с Web-версиями их приложений. Другими словами, Java-платформа позволяет вам совместно использовать с VoiceXML-версией и Web-версией приложения не только базу данных, но и программные компоненты. Ваши генерирующие VXML сервлеты могут использовать те же служебные классы для аутентификации и отслеживания полномочий, что и применяемые в сервлетах, генерирующих HTML и XHTML; ваши JSP-страницы, отвечающие на телефонные звонки, могут использовать кэшированные соединения с базой данных совместно с JSP-страницами, обрабатывающими HTTP-запросы. В результате вы имеете прикладную инфраструктуру, которая может обслуживать разные типы клиентов, вместо необходимости создания полного приложения для каждого типа клиентов.

В заключение

В данной статье я едва коснулся того, что вы можете сделать с VXML и Java-платформой. Я познакомил вас с процессом разработки VXML и показал, как интегрировать технологию Java в этот процесс. Попутно я дал несколько советов, касающихся всех видов интересных способов использования Java-кода для создания полнофункциональных, динамических VoiceXML-приложений.

Я также показал вам некоторые из действительно частых способов неправильного использования VoiceXML-разработчиками Java-технологии в голосовых приложениях. Попытки схитрить с обработкой даты и времени при предоставлении зависящих от региона служб и игнорирование различий между локальными часовыми поясами сервера и пользователя являются реальными путями оттолкнуть и расстроить пользователей. Рассматривайте Java как инструментальное средство для VoiceXML, а не как источник классов Date и Calendar.

Я продолжу рассмотрение этих и других тем в следующих статьях, начиная с заложенных здесь принципов и развивая их. Если вы хотите знать больше о создании полнофункциональных голосовых приложений, разработке телефонных приложений, взаимодействующих с базами данных, запоминающих пользователей и предоставляющих индивидуально настроенное содержимое, следите за событиями в этой области. Также зайдите на Voxeo.com и попробуйте заставить сервлет или два обслуживать ваш VXML. И возвращайтесь сюда в следующем месяце для получения дополнительной информации.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 17.04.2007 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
IBM Domino Enterprise Server Processor Value Unit (PVU) Annual SW Subscription & Support Renewal
IBM DOMINO COLLABORATION EXPRESS AUTHORIZED USER ANNUAL SW SUBSCRIPTION & SUPPORT RENEWAL
IBM Domino Messaging Server Processor Value Unit (PVU) License + SW Subscription & Support 12 Months
IBM DOMINO ENTERPRISE CLIENT ACCESS LICENSE AUTHORIZED USER ANNUAL SW SUBSCRIPTION & SUPPORT RENEWAL
IBM Domino Enterprise Server Processor Value Unit (PVU) License + SW Subscription & Support 12 Months
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
CASE-технологии
СУБД Oracle "с нуля"
Delphi - проблемы и решения
3D и виртуальная реальность. Все о Macromedia Flash MX.
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100