900 likes | 1.13k Views
Effective Application Design Patterns Using VoiceXML & CCXML/SCXML . Scott McGlashan, Hewlett-Packard Ian Sutherland, Oracle. Agenda. Introduction Resource Caching using HTTP Efficient application design models Separating presentation from data CCXML and VoiceXML techniques
E N D
Effective Application Design Patterns Using VoiceXML & CCXML/SCXML Scott McGlashan, Hewlett-Packard Ian Sutherland, Oracle
Agenda • Introduction • Resource Caching using HTTP • Efficient application design models • Separating presentation from data • CCXML and VoiceXML techniques • Deployment example • Designing applications with SCXML • SCXML overview • SCXML calling VoiceXML • Conclusions
Why Application Efficiency is important • Application efficiency is about writing applications in a way which maximizes their performance • Deployment architecture • Increased number of simultaneous session per VoiceXML and application server • Decreased network traffic between servers • User experience • Reduced wait for prompts, information and user input • Related issues: • Application maintenance • Application is easy to maintain and upgrade • Application robustness (‘high availability’) • Application can tolerate errors in any component • Goal: application which is efficient, robustness and easy to maintain and upgrade
How to Address Application Efficiency • Achieve application efficiency by addressing • Resource caching: how to avoid fetching resources at all • Data-driven application model • Separate between presentation and data • Presentation documents are fetched only once and then cached • Data is fetched from within a cached presentation document without performing a page transition • Data is then passed between cached presentation pages • Deploying a data-driven approach • Robust application architecture • Document organization • Running and upgrading the application
Resource Caching • VoiceXML follows the web model: platform fetches document from application server • Pro: open, layered architecture • Con: efficiency? – latency to fetch and process documents • Examples: • <audio src=“http://www.example.com/welcome.wav”/> • <goto next=“http://www.example.com/menu.vxml”/> • resource needs to fetched from web server • Latency to fetch document in first use, again in same session or other sessions (imagine 1,000,000 simultaneous sessions!) • HTTP caching helps make applications efficient by re-using previously fetched document where possible • Optimized platforms may store compiled VoiceXML, script and grammar documents in memory for even greater efficiency
HTTP 1.1 caching model Application Server origin server network VoiceXML Interpreter Local Cache user agent
HTTP 1.1 caching model Application Server origin server network GET /welcome.wav HTTP/1.1 Host: www.example.com VoiceXML Interpreter (1) VoiceXML platform requests new document Local Cache user agent
HTTP 1.1 caching model Application Server origin server network HTTP/1.1 200 OK Date: Mon, 07 Aug 2006 10:00:00 GMT Expires: Thu, 10 Aug 2006 10:00:00 GMT ETag: “b6128-5913-3b494b3b” Content-Length: 470000 Content-Type: audio/x-wav <audio data …> VoiceXML Interpreter (2) Application server response with document Local Cache user agent
HTTP 1.1 caching model Application Server origin server network (3) VoiceXML platform places document in local cache VoiceXML Interpreter welcome.wav Local Cache user agent
HTTP 1.1 caching model Application Server origin server network (4) VoiceXML platform needs http://www.example.com/welcome.wav on Tuesday 08 Aug 2006 Is it in local cache? Yes Is it unexpired? Yes Use version in local cache – no fetch required VoiceXML Interpreter welcome.wav Local Cache user agent
HTTP 1.1 caching model Application Server origin server network (4) VoiceXML platform needs http://www.example.com/welcome.wav on Tuesday 08 Aug 2006 Is it in local cache? Yes Is it unexpired? Yes Use version in local cache – no fetch required VoiceXML Interpreter welcome.wav Local Cache HTTP/1.1 200 OK … Expires: Thu, 10 Aug 2006 10:00:00 GMT … user agent
HTTP 1.1 caching model Application Server origin server network (4’) VoiceXML platform needs http://www.example.com/welcome.wav on Friday 12 August 2006 Is it in local cache? Yes Is it unexpired? No Request document again VoiceXML Interpreter welcome.wav Local Cache user agent
HTTP 1.1 caching model Application Server origin server network GET /welcome.wav HTTP/1.1 Host: www.example.com If-None-Match: “b6128-5913-3b494b3b” (5) VoiceXML platform requests new document with cached version’s ETag information VoiceXML Interpreter welcome.wav Local Cache user agent
HTTP 1.1 caching model Application Server origin server network HTTP/1.1 304 Not Modified Date: Wed, 15 Sep 2004 23:59:59 GMT Etag: “b6128-5913-3b494b3b” VoiceXML Interpreter (6) Application determines if its document has changed. If not, only sends headers back – VoiceXML platform uses cached version. Otherwise, sends back new version. welcome.wav Local Cache user agent
HTTP Basic Caching • HTTP caching minimizes network traffic • If not in cache, resource is always fetch • If unexpired document in cache – no fetch • If expired document in cache – conditional fetch to validate cached version: • not modified on application server – request but no fetch • modified on application server – fetch required • App server needs to provide cache information: • Expires header: when the resources expires in the cache • Date header: when resource generated • Etag header: unique id for resource contents • Note not all app servers provide this information
Configuring App Server for Caching • App server may be configured so that ‘Expires’ header is set on directory level; e.g. Apache 1.3/2.0 • Verify mod_expires module is compiled • Load module in httpd.conf: • LoadModule expires_module modules/mod_expires.so • Configure expiration for directory: • E.g. All files in /pp/20060806/ expire 1 year after access: • <IfModule mod_expires.c> • <LocationMatch "/pp/20060806/"> • ExpiresActive on • ExpiresDefault "access plus 1 year" • </LocationMatch> • </IfModule>
Configuring App Server for Caching • Application server may not be configurable by developer, alternatives are per directory and per resource (generally less efficient) • Use .htaccess file per directory • Set HTTP header directly using dynamic document generation such as ASP, JSP, servlets, etc: e.g. • <% response.setHeader(“Expires”, “Thu, 10 Aug 2007 10:00:00 GMT”); %>
More control over HTTP caching • On app server: • Use “Cache-Control: max-age=100” to specify the maximum age of a specific resource before it expires (overrides Expires header) • Use “Cache-Control: no-cache” (or “Cache-Control: max-age=0”) to ensure that a resource isn’t cached (always fetched)
More control over HTTP caching • In VoiceXML document: • Use maxage attribute to specify maximum age of cache resource – if older, then fetch from server: • <audio src=“welcome.wav” maxage=“86400”/> • Use maxstale attribute to allow use of expired resource in cache, e.g. use cached resource if expired by no more than 300s • <grammar src=“menu.grxml” maxstale=“300”/> • Maxage/maxstale values can be set on directly on document, audio, script, grammar and object URIs • Maxage/maxstale can also be set using properties; e.g. scriptmaxage • Generally, these are not required if app resources are configured with long expiration time on the application server
URIs and Caching • The value of a URI defines a resource: • <protocol><server>[:<port>][<path>]resource[?QueryString] • http://example.com:8080/mypath/myresource?a=b&c=d • Relative URIs are expanded into absolute URIs • If http://example.com/pp1/pp.vxml contains <audio src=“media/welcome.wav”/> then the absolute URI is http://example.com/pp1/media/welcome.wav • VoiceXML’s xml:base attribute can be used to override the default behavior
URIs and Caching • Different URIs = different resources; e.g. • http://example.com/user/mary/welcome.wav and http://example.com/user/john/welcome.wav are different • http://example.com/promptSerlvet?user=annika&type=welcome and http://example.com/promptSerlvet?user=johnny&type=welcome are different
Cache-aware resource management • Use a common library of resources and reference them consistently; e.g. vxml/, grammar/, script/, prompt/, etc • If you serve the same content on different pages, to different users, or from different sites, it should use the same URI; • E.g. http://example.com/pp1/media/welcome.wav • Use relative URIs within VoiceXML documents (to support version upgrades) • Ensure that resources which don’t change within the application lifecycle are cached with a long expiration time • If a resource does change, then use a different URI; e.g. instead of http://example.com/media/welcome.wav to refer to the welcome prompt for all versions of an application, give it a name – e.g. welcome20060806.wav - or place it a directory path – e.g. /pp/20060806/media/welcome.wav - with a name which reflects its versioning
Cache-aware resource management • Avoid session-specific information in the URI unless it really is necessary • Even if the resource can be cached, it has little re-use value for other users and sessions • Where possible, analyze common patterns in an application rather than use unique URIs • For user configurable main menu (50 patterns, 500,000 users), use http://example.com/menu/pattern2.grxml rather than http://example.com/menu/main.jsp?user=john • Use SSL (HTTPS) carefully: encrypted resources are not stored in shared and proxy caches (but are stored in local cache) • Use HTTP POST carefully: GET can be cached but POST is practically impossible • Use Cookies carefully: if Set-Cookie header is present, typically the resource is not cached
Resource caching summary • Resource caching with HTTP allow previously fetched documents to be re-used by the VoiceXML platform • Best case: resource is in cache and unexpired – no fetch, no document compilation required • Worst case: resource is never put in cache – fetch and compile each time • Resource caching can be enabled by the application server setting a few simple HTTP header • Setting “Expires” header allows basic caching • More control via dynamic documents and in the VoiceXML document itself • Different URIs = different resources • Follow simple rules for cache-aware management of application resources; e.g. • ensure that resources which don’t change are cached with a long expiration time • Significant reductions in network traffic and server load (up to 80%) with correct resource caching in typical applications
Which resources to cache • Cache ALL resources time with long expiration time except: • Application entry point document (for version management) • short expiration time • URIs of transient resources; e.g. advert prompts • short expiration time • URIs which send and receive data (only) that is unique to a user session • no-cache • But how do I write VoiceXML applications with cacheable documents yet still present dynamic data to the user?
Application design models • Static VoiceXML pages: resources are stored on the application file system • Works well for very simple applications, but no means to present dynamic data (e.g. from live data feed) to the user • Dynamic VoiceXML pages: use app server techniques (asp, jsp, servlets, etc) to dynamically generate documents • Documents frequently encode unique data and general presentation markup – reduced value in caching them • Data-driven static VoiceXML pages: separate between data and presentation • Use dynamic techniques to exchange data with the app server – non-cached data documents (cf. 2 above) • static VoiceXML pages which encode user information in ECMAScript variables (cf. Web 2.0, AJAX, etc) – cacheable presentation documents (cf. 1 above)
Non data-driven example 1/2 <vxml …> <form> <block> <var name=“callerid” expr=“session.connection.remote.uri”/> <submit next=“showBalance.jsp” namelist=“callerid”/> </block> </form> </vxml> doc1.vxml URIs to fetch: http://example.org/showBalance.jsp?callerid=1234 http://example.org/showBalance.jsp?callerid=5678 http://example.org/showBalance.jsp?callerid=9722 http://example.org/showBalance.jsp?callerid=1122 ….
Non data-driven example 2/2 <vxml …> <form> <block> <prompt> Your balance is 402 dollars. </prompt> </block> </form> </vxml> showbalance.jsp?callerid=1234 • Page transitions from doc1.vxml to showbalance.jsp?callerid=1234 • 2nd document has presentation and user session information: each showbalance.jsp URI is unique and so will return a 2nd unique document where the documents only differs in user session information • More network traffic, more document parsing • little value in caching it
data-driven example <vxml …> <form> <block> <var name=“callerid” expr=“session.connection.remote.uri”/> <script srcexpr=“’getBalance.jsp’ + callerid/> </block> <field> <prompt> Your balance is <value expr=“application.balance”/> </prompt> </field> </form> </vxml> doc1.vxml
Data-driven model features • No page transition required for fetching data from app server • Still HTTP document fetch, but only data - no presentation markup • Same VoiceXML document (and other resources) can be fetched, cached and re-used with different user session information • Minimize network traffic • Minimize markup documents which need to be processed • Data-driven model is a design choice which can significantly improve application performance • Cached presentation documents: no network traffic once in cache • Non-cached data only documents: network traffic only with data
General Data Fetching Model CCXML/ VoiceXML Platform Application Server Document a= b= Data Request Handler Cached data-driven CCXML/ VoiceXML jsp, asp, servlet, etc
General Data Fetching Model CCXML/ VoiceXML Platform Application Server HTTP data request (unique session/user parameter), e.g. callerid=1234 Document a= b= Data Request Handler Cached data-driven CCXML/ VoiceXML jsp, asp, servlet, etc
General Data Fetching Model CCXML/ VoiceXML Platform Application Server HTTP data request (unique session/user parameter), e.g. callerid=1234 Document a= b= Data Request Handler Cached data-driven CCXML/ VoiceXML jsp, asp, servlet, etc 2. HTTP data response (unique session/user information) a=100 b=tmp
General Data Fetching Model CCXML/ VoiceXML Platform Application Server HTTP data request (unique session/user parameter), e.g. callerid=1234 Document a=100 b=tmp Data Request Handler Cached data-driven CCXML/ VoiceXML jsp, asp, servlet, etc 2. HTTP data response (unique session/user information) a=100 b=tmp 3. Update variables in document with data from response
Instances of this model • CCXML: use BasicHTTP IO Processor to fetch data and inject into VoiceXML dialog • VoiceXML 2.0: use <subdialog> to fetch VoiceXML and extract data • VoiceXML 2.1: use <script> with “srcexpr” to fetch data as ECMAScript • VoiceXML 2.1: use <data> with “srcexpr” to fetch data as XML • Tip: the CCXML method can be used to fetch data at beginning of call and then VoiceXML methods can be used mid-call
If incoming call handled by CCXML, then CCXML can be used to fetch initial data and passed it directly to the VoiceXML dialog 1. Use BasicHTTP IO Processor to send/receive data <send> information to app server, receive data parameters in return External Component inject event CCXML access URI session session session session CCXML <send> Using CCXML to send/receive initial data
Using CCXML to send/receive initial data 2. Start VoiceXML dialog with parameters • <dialogstart type=“application/voicexml+xml” src=“…” parameters=“param1 param2” /> • Note: earlier versions of CCXML did not distinguish between parameters sent to web server and parameters sent to dialog 3. In VoiceXML document set ECMAScript variables from CCXML data • session.connection.ccxml.values is an array containing data sent from CCXML • CCXML pages should also be cacheable and data-driven!
start.ccxml 1/3 – register user <ccxml> <transition event=“connection.alerting” name=“evt”> <assign name=“application.callerid” expr=“evt.connection.remote”/> <send targettype=“basichttp” target=“http://appserver.com/pp/dataServlet” data=“register” parameters=“application.callerid”/> </transition> …
App server – dataServlet process request • public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException • { • callerid = request.getParameter(“application.callerid”); • params = database.lookupSubscriber(callerid); • …. • response.setContentType("application/x-www-form-urlencoded"); • String content = FormUrlEncoder.encode(params); • response.setContentLength(content.length()); • response.getOutputStream().println(content); • response.getOutputStream().flush(); • response.setHeader(“Cache-Control”,”no-cache”); • response.setStatus(200); • }
start.ccxml 2/3 – assign data and accept call <transition event=“register.reply” name=“evt”> <assign name=“application.lang” expr=“evt.lang”/> <assign name=“application.cos” expr=“evt.cos”/> <assign name=“application.balance” expr=“evt.balance”/> <assign name=“application.uri” expr=“evt.uri”/> <accept/> </transition>
start.ccxml 3/3 – dialog with data … <transition event=“connection.connected” name=“evt”> <dialogstart type=“’application/voicexml+xml’” src=“application.uri” parameters=“application.callerid application.lang application.cos application.balance”/> </transition> </ccxml>
Initial VoiceXML page – access data <vxml …> <assign name=“application.callerid” expr=“connection.ccxml.values.application.callerid”/> <assign name=“application.lang” expr=“connection.ccxml.values.application.lang”/> <assign name=“application.cos” expr=“connection.ccxml.values.application.cos”/> <assign name=“application.balance” expr=“connection.ccxml.values.application.balance”/> …
Using VoiceXML to fetch data without page transition • VoiceXML 2.0: <subdialog>: send parameters and receive VoiceXML document • BUT: includes presentation markup – need to extract data from markup • Not ideal, but only method in 2.0 • VoiceXML 2.1: <script>: send parameters and receive script • No presentation markup, only ECMAScript data • VoiceXML 2.1: <data>: send parameters and receive XML document • No presentation markup, only XML data
VoiceXML 2.0: <subdialog> 1/2 <vxml …> <form> <block> <assign name=“application.balance” expr=“’unknown.’/> </block> <subdialog name=“getbalance” fetchtimeout="10s“ srcexpr=“’/pp/dataServlet?application.callerid=‘ + session.connection.remote.uri”> <catch event="error.badfetch"> <throw event="serviceunavailable”/> </catch> <filled> … </filled> </subdialog> … </form>
App server – dataServlet process request from <subdialog> • public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException • { • callerid = request.getParameter(“application.callerid”); • params = database.lookupSubscriber(callerid); • …. • response.setContentType("application/voicexml+xml"); • String content = "<?xml version=\"1.0\"?>" + • "<vxml version=\"2.0\" xmlns=\"http://www.w3.org/2001/vxml\">" + • "<catch><return eventexpr=\"_event\" " + • "messageexpr=\"\'ppas data subdialog, message=\' + _message\"/>" + • "</catch>“ + • "<form><block>" + • "<var name=\“balance\" expr=\"'" + callerid.getBalance() + "'\"/>" + • "<return namelist=\“balance\"/>" + • "</block></form></vxml>"; • response.setContentLength(content.length()); • response.getOutputStream().println(content); • response.getOutputStream().flush(); • response.setHeader(“Cache-Control”,”no-cache”); • response.setStatus(200); • }
Fetched VoiceXML Document <?xml version="1.0"?> <vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"> <catch> <return eventexpr="_event“ messageexpr="_message"/> </catch> <form> <block> <var name=“balance" expr=“’420’”/> <return namelist=“balance"/> </block> </form> </vxml>
VoiceXML 2.0: <subdialog> 2/2 … <subdialog name=“getbalance” fetchtimeout="10s“ srcexpr=“’/pp/dataServlet?application.callerid=‘ + session.connection.remote.uri”> <catch event="error.badfetch"> <throw event="serviceunavailable”/> </catch> <filled> <assign name=“application.balance" expr=“getbalance.balance" /> </filled> </subdialog> <field> <prompt> Your balance is <value expr=“application.balance”/> </prompt> </field>
VoiceXML 2.1: <script> <vxml …> <assign name=“application.balance” expr=“’unknown.’/> <form> <block> <script srcexpr=“/pp/dataServlet?application.callerid=‘ + session.connection.remote.uri”/> </block> <field> <prompt> Your balance is <value expr=“application.balance”/> </prompt> </field> </form>
VoiceXML 2.1: <script> <vxml …> <assign name=“application.balance” expr=“’unknown.’”/> <form> <block> <script> application.balance = “420 dollars.”; </script> </block> <field> <prompt> Your balance is <value expr=“application.balance”/> </prompt> </field> </form>
VoiceXML 2.1: <data> <vxml …> <var name=“account”/> <assign name=“application.balance” expr=“’unknown.’”/> <form> <block> <data name=“account“ srcexpr="‘/pp/dataServlet?application.callerid=‘ + session.connection.remote.uri/> <script><![CDATA[ application.balance = account.documentElement.getElementsByTagName(“balance").item(0).firstChild.data; ]]></script> </block> <field> <prompt> Your balance is <value expr=“application.balance”/> </prompt> </field> </form>