Over the last five years, the Web has been stretched perhaps further than at any other time in its history. What was once a largely text-based medium for software programs called "Web browsers" has become an information source for any device that has connectivity. Initially, mobile phones joined the list of devices that could access Web pages, followed by pagers, handheld devices, personal planners, and anything else that could make a wireless connection to the Web. In more recent years, telephony has entered this fray, and the desire to make Web programs accessible over normal phone lines has come into vogue.
This last category of applications -- where a user accesses an online service through a telephone -- is better called a telephone application. Since phones obviously can't be used to "click on a link," application interactions are almost all handled by voice. Instead of clicking a link, a user says "Account Information," or uses the keypad following pre-recorded instructions.
The ability to serve telephones through existing -- or slightly modified -- Web applications is a powerful idea, and one that many Web developers are eager to explore. The most important thing to know about Web and phone applications is that you can use virtually the same technology stack to create both. HTML, XHTML, and XML are three of the most common technologies underlying Web interfaces, and VoiceXML (or VXML) is a closely related technology that makes Web interactions available to phone clients. JavaServer Pages and servlets, PHP scripts, and Ruby applications can all respond to phone requests as easily as those that come in over a handheld or Web browser. In this article, I focus on using the Java platform to serve simple VoiceXML applications, but you can apply much of the discussion equally to PHP, Perl, or your programming language of choice.
The most commonly used standard for building voice applications is VoiceXML. Most VXML browsers support VoiceXML 2.0, which is the VXML version used throughout this article. VXML is W3C-specification-compliant and rapidly expanding, but still catching up with v2.1. VXML 3.0 is also on the horizon.
CCXML stands for Call Control XML, and is the newest player that meets the W3C specifications for telephony markup. CCXML is more advanced than most VoiceXML implementations, offering support for callbacks, event listeners, and multi-line and multi-party sessions. Unless you specifically need these features, however, you're probably best served by sticking with VoiceXML, which is more stable and in widespread use.
CallXML is a platform specific to Voxeo. CallXML is extremely easy to learn and provides great support for touchtone input (note that it does not support voice recognition). CallXML's big downside is that it is vendor-specific. While Voxeo is a great site with a ton of resources, it's never a good idea to get locked into a specific vendor. Again, most developers will find that VoiceXML meets their needs.
Before getting into the Java side of the VoiceXML picture, you should have a basic understanding of how a VoiceXML application works. To that end, I'll take you quickly through a very simple VoiceXML application. The example app will get you used to seeing VXML files, as well as ensuring you have access to (and can use) the Voxeo call-assignment service, which is crucial to the rest of this article.
VoiceXML begins with at least one VXML file, the VoiceXML-flavored version of XML used to inform telephony applications of what they should (and can) do. Listing 1 is a very simple VXML file. Save this file on your local machine (you can download the complete example source code from Download, but you should get used to working with these files yourself, anyway).
Listing 1. A very simple VXML file
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1">
<form>
<block>
<prompt>
Things are working correctly! Congratulations.
</prompt>
</block>
</form>
</vxml>
|
This is about as basic as VoiceXML gets; if you're unclear on the syntax check out some of the other VoiceXML articles listed in Resources. The VXML file in Listing 1 consists of a single prompt and doesn't offer any interactivity; you'll see much more advanced uses of VoiceXML in the sections on working with Java code. For now, use this simple test case to ensure your environment is working correctly.
Next, put your VXML file somewhere publicly accessible. If you have an ISP, just upload the VXML file to your Web site; you might want to create a directory for your VoiceXML files off of your Web root, like /voicexml or /voice. Make sure the directory and file are Web accessible (consult your system administrator or ISP if you're unclear on how to do this).
In the event that you don't have access to an ISP, you can sign up at Voxeo to use the site's File Manager. You should already have created a Voxeo account, and it comes with 10 MB of hosting space, so this is a nice free option. (Ten MB is a lot of VXML files!)
Once your VXML app is online, you might want to ensure you can access it by entering the URL into your Web browser. Depending on your browser, you might be asked to download the XML file, or see it rendered in some form by your browser. This is just a test to ensure the VXML is available, so don't be concerned if your computer doesn't start speaking to you. Once the VXML is online, you're ready to link it to a phone number.
Assign a phone number to your application
Unlike traditional Web applications, you can't just open up a Web browser and surf on over to your VXML file; at least, not if you want a voice response. To test out a phone-based application, you obviously need a phone, and that implies a number to call. There are plenty of high-dollar approaches to mapping numbers to VoiceXML applications, but for testing, staging, and development, Voxeo offers a great free mapping service.
Navigate over to Voxeo.com, log in (using the fields on the upper left side of the page). Under Account menu, select Application Manager, as shown in Figure 1.
Figure 1. Getting to the Voxeo Application Manager
Choose Add Application, and then select VoiceXML 2.0 as your development platform.
Next, provide the URL for your VXML file, as well as a name for your application; you can use anything you want for the name, as it's for your own reference. Figure 2 shows the settings to access my VXML file. From the Application Phone Number drop-down list, choose the Staging option. This assigns a temporary staging phone number to the application, so you can actually call in from your own telephone.
Figure 2. Mapping a VXML file to a phone number
Click Create Application and Voxeo will assign several phone numbers to your application. Figure 3 shows the resulting screen (scrolled down a bit), with all the different access points to the VXML file.
Figure 3. A successful mapping!
This feature alone is worth the time it takes to sign up for Voxeo; you can now access your VXML file through a toll number, an 800-number, and Skype, just to list a few. This is nice, since you don't have to use the Voxeo tools to test your application. Even better, you can let your boss test things out without needing an account on the Voxeo site!
All that's left is to call one of the numbers that Voxeo supplies. Once you dial, your VXML application should pick up, and let you know (in an unexciting mechanical voice) that "Things are working correctly! Congratulations."
And that's it: in about five minutes, you had your phone talking to an XML file. Now you're ready to get into some Java code, and learn about generating VXML dynamically.
At this point, most Java developers try to hand-code VXML from within their Java servlets, add in hundreds of out.println() statements, worry about the content type of the output, and generally add a lot of unnecessary complexity to many applications. Before you begin those more complex programming tasks -- all of which are useful when used properly -- get your feet wet with some very basic VoiceXML servlet programming in this section.
To begin with, develop your VXML file. Don't open up an IDE or start coding Java; instead, just fire up a text editor, and resist the urge to immediately add package and import statements. Instead, build a simple VXML file, much as you did earlier in this article.
For example, Listing 2 is another pretty basic VXML file. It's a voice-recognition VXML file that takes in a favorite instrument and offers some commentary on the caller's choices.
Listing 2. Another basic VXML file
<?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>
|
Write this VXML, save it, upload it to your ISP, and assign a number to it. Only after you do all of these steps -- ensuring that your VXML works -- are you ready to even begin thinking about coding Java.
If you jump right into Java, you'll probably make mistakes in your output, as well as mistakes in your code. The result is trying to simultaneously debug a VXML file (XML) and a servlet (Java), all within a Web framework, which is notoriously hard to debug in the first place. Rather than add all these variables -- no pun intended -- ensure that you start with a working VXML file. Then you're ready to get your Java code running.
With your VXML ready to use, you're finally set to get into some code. First, begin with a servlet that simply loads the VXML file. Listing 3 is a servlet that does just that -- loads up the VXML developed in Listing 2. There's no output, so don't expect much yet.
Listing 3. Loading a VXML file
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();
}
}
}
|
This code is pretty straightforward. It loads up an XML file -- specified through a directory in the servlet's configuration context and a constant filename -- and then iterates over the content of that file. You might hard-code the file's path in the servlet, but it's a much better idea to store at least the directory name in your Web.xml file, located in the WEB-INF/ directory of your servlet's context. Listing 4 shows the context parameter in Web.xml.
Listing 4. The context parameter for the servlet
<context-param>
<param-name>vxml-dir</param-name>
<param-value>/path-to-your-voicexml-dir/voicexml</param-value>
</context-param>
|
If you compile your servlet and try to load it in a Web browser, you'll only get a blank screen; still, you should make sure you get at least that. If you get any errors you'll need to correct them. For example, it's common to run into file-access problems or typos in the VXML file path. Once you get a blank screen, you're ready to actually output the VXML file.
Outputting VXML from a servlet
First, you need to get access to an output object, so you can send content to the browser. This is easy enough:
// 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();
|
Spitting out the content from the file itself is easy; you just use a single line of code:
// Output the VXML file
int readBytes = 0;
while ((readBytes = bis.read()) != -1) {
// output the VXML
out.write(readBytes);
}
|
While this might look like it's enough, you still need to let the browser know that you're sending XML to it. Remember, browsers are used to HTML, and some don't happily accept XML. You can set the content type, as well as the length of that content, by using the HttpServletResponse object again:
// Let the browser know that XML is coming
out = res.getOutputStream();
res.setContentType("text/xml");
res.setContentLength((int)vxml.length());
|
Listing 5 shows all of this code added into the servlet you saw back in Listing 3.
Listing 5. The VoiceXMLServlet, completed and ready to load VXML files
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();
}
}
}
|
Testing servlet-loaded VoiceXML
Compile your servlet with these changes, and restart your servlet engine if you need to. Browse to the servlet, and you should see output similar to Figure 4. Success!
Figure 4. The VoiceXML servlet outputting VXML
If you don't get output like this, try to ensure that your file is where you indicated it to be, and that you don't have any permission issues. You might also check your servlet engine's logs, or ask a system administrator for help.
Now you're ready to map a phone number to your servlet. Head back over to Voxeo.com's Application Manager and add a new application (you'll probably see the applications you worked with earlier). Make sure you select VoiceXML 2.0, and then enter a name for the new application and the URL for your servlet. Voxeo will create your application and assign it a phone number.
Dial in to this new number and you should hear the prompt from the VXML back in Listing 2. Congratulations! You've just coded a Java servlet that outputs VXML, and hooked a phone number into it.
You might want to make a couple minor additions to your servlet code. Neither are required, but both add a bit of robustness and documentation to the existing version.
First, you might want to allow users to access the VXML through a POST request. This could occur if a user clicked a button on a form, and that form made a POST request to the VoiceXMLServlet. It's a pretty simple operation to handle in the servlet; just write a version of doPost() that delegates to the doGet() method you already have, as shown here:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doGet(req, res);
}
|
Another simple addition is to actually let browsers know that you're outputting the content of a VXML file. To do this, set the Content-disposition response header in your servlet, like so:
// 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);
|
Now browsers (or other code) reading your response can discover the VXML file that was served. Be sure not to include your complete file path, though; that is a security risk!
Once you have a servlet that outputs a VXML file, it's a pretty small task to move from that -- using the code as a model or template -- to a servlet that outputs VXML dynamically. In other words, you can move away from simply loading a static VXML file, and start programmatically creating VXML.
The Java platform really begins to shine when you get into dynamic VoiceXML. It provides the ability to easily output XML, as well as interact with databases, directory servers, authentication stores, and sessions. As it turns out, building dynamic VXML gets rid of some of the formality of voice-based systems, as well.
In this section, I walk you through creating a Java servlet that outputs dynamic VXML.
Outputting VXML through out.println()
You've already seen how to get access to the ServletOutputStream, and then insert bytes into that output stream. However, dealing directly with bytes isn't nearly as manageable when you're not just transferring bytes from a source (like a static VXML file) to an output stream.
In cases where you want to create the VXML on your own, you're better off working with a PrintWriter. You can push entire strings out with that class, making it much more useful for creating and outputting dynamic content. It only requires a small change to your code, as shown below.
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();
}
}
|
Don't forget to also import the java.io.PrintWriter class: it's not automatically available to your servlet's code base.
With a PrintWriter, you can now output string-based content. For example, Listing 6 outputs the same VXML you saw back in Listing 1, except through a servlet, and without loading the VXML content from a static file.
Listing 6. Dynamically outputting 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);
}
}
|
You can compile this servlet, register it with Voxeo, and access it by phone, just as you did with Listing 1. Now let's move on to some examples that show off the dynamic programming capabilities of a language like Java.
One of the simplest things you can do with servlet-based VXML output is add some awareness of time. It's trivial to grab the current time and date with Java code, so that's a great place to start.
Using the Calendar class you can easily get the hour of the day (or anything else related to the current date, really). Listing 7 demonstrates code to get a new instance of the Calendar class, obtain the hour of the day (which is returned in a 24-hour format), and then put together a simple greeting based on that hour.
Listing 7. Dynamically outputting 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);
}
}
|
Differences between callers and VXML generators
Listing 7 also showcases another feature of VoiceXML and dynamically generated VXML: the possible disparity between the caller and the VXML itself. For instance, suppose a user living in New Zealand calls into the application shown in Listing 7. If it's 10:00 PM in New Zealand, but the server outputting the VXML is in Denver, Colorado, they'll probably be greeted with an odd message, such as "You're up early. Good morning." That's hardly appropriate, and it could get worse: if you've added in greetings for specific days of the week, you're really going to have some mismatches.
The basic problem stems from the VXML and Java running in the locale and time zone of a specific server, but being available to callers from all over the world. If your servlet doesn't take this into account, you're going to have some rather confused callers. You have several options:
- Ignore the difference and hope callers understand that your server just isn't running code in their time zone.
- Explicitly state that times and dates are local to the server; for instance, your afternoon greeting might be, "It's afternoon here. I hope you're having a nice day as well."
- Write code that asks for a time zone or the offset from GMT, and then develop greetings based on that information.
Unfortunately, none of these turns out to be an attractive option. The first does just what it says: basically ignores the caller. It should go without saying that ignoring callers is not the way to get and maintain a business. The second idea -- stating the local time and explicitly noting that it's local -- is not much more helpful, as it still tends to ignore the caller; it's just a little more considerate in the process.
The final option might seem at first to be attractive; it's easy to write VXML to allow the user to supply a number offset from GMT, and then respond based on that. However, callers tend to like to get to information as quickly as possible; the more response prompts you have, the greater risk of annoying your callers and having them hang up unsatisfied. Therefore, unless you are providing a time- or date-based service, requiring a caller to indicate the time zone is a waste of one of those prompts. Even worse, many callers don't know their offset from GMT, so you're faced with supporting time zones, time zone abbreviations, daylight savings time ... the list can get long and unwieldy.
So why even play with date-based VXML generation? Largely because it illustrates these very issues! You need to be very conscious of your audience, and try and give them information that is relevant to them, not to your server or your locality.
In the case of date-based processing, the lesson is that you should probably employ a final, better option for dealing with callers and avoid date- and time-based transactions altogether, unless absolutely necessary. If you expect callers from outside your time zone, you're just asking for trouble by trying to provide a time-related feature. The same principles apply for any data that might change across state, country, or continental lines.
Finally, there are obviously plenty of times when using a servlet for outputting VXML is not that great of an idea. If you're just spitting out VXML from a static file, you gain very little (perhaps a bit of flexibility), but adding code, compilation, debugging, a servlet engine, and a lot more to the complexity of your voice app. In these simple cases, stick with using static VXML files.
As you've seen so far in this article, sometimes a servlet-generated VXML does not make sense. Before finishing up, though, consider several cases where using a language like Java is a great telephone application solution. I won't provide full examples here, but look for them in future articles.
The most obvious application of Java concerning VoiceXML is using a database to feed a dynamic VXML output. This is probably what many of you expected to learn about when you began this article (although you wouldn't have learned as many lessons if that was the core example). In any case, JDBC makes it simple to connect to a database, and then use results from SQL queries to populate VXML.
For example, you could develop a table that contained all the grammar information for your VXM, and then load that grammar into each VXML file you output. Rather than having to code grammar for each and every VXML file, you can share a grammar between similar files. Even better, you can pre-load these grammars across all servlets, or instances of a particular servlet, and have the benefit of storing your grammars in a database without paying the cost for loading that grammar on each and every request.
Loading VXML based on user credentials
Another nice Java feature -- particularly as it relates to servlets, JSPs, and Web-based programming -- is the ability to store user credentials in a session. This gets you firmly into authentication and authorization, as well as very highly customized content.
For example, consider a voice application that begins by asking for a user ID number and a PIN (like most banking or financial applications do today). You can authenticate these credentials against a database -- already a notable strength of the Java platform -- and then store the caller's ID into a session variable. Then, each Java servlet or JSP that fields a request from that caller can figure out what options to offer the user based on those credentials.
While plenty of VoiceXML alternatives offer similar functionality, very few boast the ability to share code with Web-based versions of their applications. In other words, the Java platform lets you share not only a database between a VoiceXML and Web-based version of an application, but code components. Your VXML-producing servlets can use the same authentication and permissions utility classes as your HTML- and XHTML-producing servlets; your JSPs that respond to phone calls can share cached database connections with your JSPs that handle HTTP requests. As a result, you end up with an application infrastructure that can handle multiple types of clients, rather than having to create an entire application for each client type.
In this article I barely scratched the surface of the things you can do with VXML and the Java platform. I introduced the process of developing VXML, and then showed you how to integrate Java technology into that process. Along the way I dropped hints as to all kinds of interesting ways you can use Java code to develop rich, dynamic VoiceXML applications.
I also let you see some of the really common ways that VoiceXML developers misuse Java technology in voice applications. Trying to get clever with dates and times, attempting locale-based services, and forgetting about the difference between a server's local time and a caller's local time are sure ways to alienate and frustrate users. Consider Java a tool for VoiceXML, but not a showcase for the Date and Calendar classes.
I'll continue writing about these topics and more in future articles, starting with the principles laid down here and expanding on them. If you want to know more about building rich voice application, developing telephone apps that interact with databases, tracking users, and providing individualized content, keep an eye on this space. Also, go back to Voxeo.com and try getting a servlet or two to serve up your VXML. Then come back here next month for more.
| Description | Name | Size | Download method |
|---|---|---|---|
| Example code for this article | wa-voicexml.zip | 1KB | HTTP |
Information about download methods
Learn
-
X+V is a markup language, not a Roman math expression (Les Wilson, developerWorks, August 2003): Explore your options with a look at X+V (XHTML plus Voice) -- a Web markup language for developing multimodal applications.
- Multimodal interaction and the mobile Web, Part 1: Multimodal auto-fill (Gerald McCobb, developerWorks, November 2005): Take the first steps into multimodal interaction development.
-
Speech-enable Web apps using RDC with Voice Toolkit (Girish Dhanakshiru, developerWorks, March 2005): WebSphere developers can use the Voice Toolkit and Rational Application Developer (RAD) to add speech to any existing Web application.
-
Start developing CCXML applications (Susan Jackson and Hannah Parker, developerWorks, June 2004): A tutorial introduction to the Call Control XML (CCXML) language.
- Choosing a platform: Voxeo explains the difference between CallXML, CCXML, and VoiceXML.
- W3C's Voice Browser Activity page: Includes links to specs, FAQs, tools, and helpful articles.
- VoiceXML 2.1:
Read the W3C candidate recommendation.
- The CCXML Version 1.0 specification: Features the latest developments in call control technology.
- Java and XML, Second edition (Brett McLaughlin; O'Reilly Media, Inc., 2001): Includes material on XHTML, serving XML on the Web, and serving content to multiple types of devices.
- XML in a Nutshell, Third edition (Elliotte Rusty Harold, W. Scott Means; O'Reilly Media, Inc., 2004): A great all-in-one XML resource, with a chapter devoted to XML on the Web.
- Web Architecture zone: Find articles and tutorials on various Web-based solutions.
-
developerWorks XML zone: FInd hundreds of XML-related articles and tutorials.
-
developerWorks Wireless technology zone: Explore content about a variety of Wireless solutions.
-
developerWorks Java technology zone: Check out numerous, Java-related articles and tutorials.
Get products and technologies
-
Voxeo.com: An excellent source of VoiceXML information.
-
Voxeo Community Tools: A starting point for finding VoiceXML-related add-ons and utilities.
-
IBM trial software: Available for download directly from developerWorks.
Discuss
-
Get involved in the developerWorks community by participating in developerWorks blogs.

Brett McLaughlin has worked in computers since the Logo days. (Remember the little triangle?) In recent years, he's become one of the most well-known authors and programmers in the Java and XML communities. He's worked for Nextel Communications, implementing complex enterprise systems; at Lutris Technologies, actually writing application servers; and most recently at O'Reilly Media, Inc., where he continues to write and edit books that matter. Brett's upcoming book, Head Rush Ajax, brings the award-winning and innovative Head First approach to Ajax, along with bestselling co-authors, Eric and Beth Freeman. His last book, Java 1.5 Tiger: A Developer's Notebook, was the first book available on the newest version of Java technology. And his classic Java and XML remains one of the definitive works on using XML technologies in the Java language.
Comments (Undergoing maintenance)





