| CCXML 1.0-W3C Development Guide | Home | Frameset Home |
|
<transition> placement
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
</ccxml>
<transition> element, but introduce the usage of the 'state' attribute: This allows us to have multiple <transition> elements for the same events, but gives us a finer grain of control based on the state that the application is currently in. To illustrate in greater detail, consider the following code snippets, both of which are meant to handle a specific user-defined event that has been kicked off via the <send> element:
<transition state="'niceGuy'" event="myEvent">
<dialogstart src="'niceCaller.vxml'" type="'application/voicexml+xml'"/>
</transition>
<transition state="'meanGuy'" event="myEvent">
<dialogstart src="'meanCaller.vxml'" type="'application/voicexml+xml'"/>
</transition>
<eventprocessor> can only be scoped to a single state variable. Let's take a look:
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="app_state" expr="'initial'"/>
<eventprocessor statevariable="app_state">
</eventprocessor>
</ccxml>
<eventprocessor> will use "app_state" for the state variable. This does not mean that we must use state information as part of our specific event check; instead, it forces us to use the specified state variable if we choose to check for state, (which we do, in this case!).
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="app_state" expr="'initial'"/>
<var name="in_connID"/>
<eventprocessor statevariable="app_state">
<transition state="initial" event="connection.alerting">
<assign name="app_state" expr="'accepting'"/>
<accept/>
<assign name="in_connID" expr="event$.connection.connectionid"/>
<log expr="'*** connection.alerting app_state = ' + app_state + ' ***'"/>
<log expr="'*** in_connID = ' + in_connID + ' ***'"/>
</transition>
<transition state="accepting" event="connection.connected">
<assign name="app_state" expr="'incall_0'"/>
<send name="'continue'" target="session.id" delay="'3000ms'"/>
</transition>
</eventprocessor>
</ccxml>
<ccxml> scope, whose value will be available to us regardless of which <transition> we are at in the CCXML 1.0 document. This is an empty variable when we declare it, but you see that as soon as we hit the "connection.alerting" event <transition>, we assign this variable the value of the 'connection.connectionid' property: This variable assignation allows us to programmatically disconnect a specific call leg later on in our tutorial. <transition> for the 'connection.connected' event will only execute when app_state='alerting'. This further illustrates that a <transition> tag handles more than one conditional requirement: for our first example, the state (as defined within the "app_state" variable) must be equal to "initial" as well as the raw event itself being "connection.alerting". If either of these is not true, then there is no match, and the <transition> handler is skipped. Case in point: we are changing the value (via the <assign> tag) to a new value -- should our state variable never be reset to "initial", then this <transition> will never be visited again. <send> a user-defined event to this same application. With <send> we are able to post an event to any session we have the identifier of. In this example, we send one simple event to ourselves by specifying a value of "session.id" in the 'target' attribute. Additionally, we will delay the sending for 3000 milliseconds, allowing us to implement our "timer" functionality, or just pause our application for any given period of time. <send> element requires us to catch a user-defined event. How the heck do we do that? Easy, we just code a <transition> that is looking for the event name we just sent in the 'event' attribute, making sure that we are also looking for the correct application state in the 'state' attribute, as explained earlier:
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="app_state" expr="'initial'"/>
<var name="in_connID"/>
<eventprocessor statevariable="app_state">
<transition state="initial" event="connection.alerting">
<assign name="app_state" expr="'accepting'"/>
<accept/>
<assign name="in_connID" expr="event$.connection.connectionid"/>
<log expr="'*** connection.alerting app_state = ' + app_state + ' ***'"/>
<log expr="'*** in_connID = ' + in_connID + ' ***'"/>
</transition>
<transition state="accepting" event="connection.connected">
<assign name="app_state" expr="'incall_0'"/>
<send name="'continue'" target="session.id" delay="'3000ms'"/>
</transition>
<transition state="incall_0" event="continue">
<assign name="app_state" expr="'incall_1'"/>
<log expr="'*** incall_0 app_state = ' + app_state + ' ***'"/>
<send name="'continue'" target="session.id" delay="'1000ms'"/>
</transition>
<transition state="incall_1" event="continue">
<disconnect connectionid="in_connID"/>
<assign name="app_state" expr="'disconnecting'"/>
<log expr="'*** incall_1 app_state = ' + app_state + ' ***'"/>
</transition>
</eventprocessor>
<transition>. To further illustrate the usage of application state, we again reassign our "app_state" variable to a value of 'incall_1', and again send another "continue" event to ourselves, this time with a 1000ms delay.<transition> to seek out a condition where the event is "continue", but this time, where the application state is now 'incall_1'. <disconnect> event, but what if we want to detect an earlier event (say, for example, your impatient little sister called and the four seconds of silence overwhelmed her)? Clearly, you might want to know when this situation occurs. In order to do so, we employ the 'cond' attribute of the ever-popular <transition> element, which works just like an if/elseif/else conditional logic block. Basically, the events contained within this handler will only execute if:<transition> 'event' evaluates to 'true'<transition> 'cond' evaluates to 'true'<exit> gracefully.<exit> tag to avoid any runaway call sessions, (we covered this concept in our previous tutorial). As a final line of defense, we include a <transition> handler for any "wildcard" error events that might occur via the "error.*" event value, so that we can be sure that no matter what happens, we can <exit> without bringing our IVR platform down with a zombie session.
<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="app_state" expr="'initial'"/>
<var name="in_connID"/>
<eventprocessor statevariable="app_state">
<transition state="initial" event="connection.alerting">
<assign name="app_state" expr="'accepting'"/>
<accept/>
<assign name="in_connID" expr="event$.connection.connectionid"/>
<log expr="'*** connection.alerting app_state = ' + app_state + ' ***'"/>
<log expr="'*** in_connID = ' + in_connID + ' ***'"/>
</transition>
<transition state="accepting" event="connection.connected">
<assign name="app_state" expr="'incall_0'"/>
<send name="'continue'" target="session.id" delay="'3000ms'"/>
</transition>
<transition state="incall_0" event="continue">
<assign name="app_state" expr="'incall_1'"/>
<log expr="'*** incall_0 app_state = ' + app_state + ' ***'"/>
<send name="'continue'" target="session.id" delay="'1000ms'"/>
</transition>
<transition state="incall_1" event="continue">
<disconnect connectionid="in_connID"/>
<assign name="app_state" expr="'disconnecting'"/>
<log expr="'*** incall_1 app_state = ' + app_state + ' ***'"/>
</transition>
<transition event="connection.disconnected">
<log expr="'*** call was disconnected ***'"/>
<exit/>
</transition>
<transition event="connection.failed"
cond="('incall_0' == app_state) || ('incall_1' == app_state)">
<log expr="'*** premature disconnection detected in state [' + app_state + '] ***'"/>
<voxeo:sendemail to="'yourEmail@there.com'"
from="'myApp@here.com'"
type="'debug'"
body=" 'premature disconnection detected!' "/>
<exit/>
</transition>
<transition event="connection.failed">
<log expr="'*** not premature... wise, learned, mature disconnection ***'"/>
<exit/>
</transition>
<transition event="error.*">
<log expr="'*** unhandled error.* event detected ***'"/>
<voxeo:sendemail to="'yourEmail@there.com'"
from="'myApp@here.com'"
type="'debug'"
body="'unhandled error event detected!'"/>
</transition>
</eventprocessor>
</ccxml>
<eventprocessor>, nothing would work at all (we wouldn't get our four seconds of silence!). <transition> handlers| ANNOTATIONS: EXISTING POSTS |
atacama
|
|
| Step 2 (well, in the second Step 2, not the first Step 2) says "...assign our "app_state" variable a user-defined value of 'alerting'', but the value set in the code is 'accepting'. The next sentence also says 'alerting', but the next paragraph correctly says "accepting". | |
voxeojeff
|
|
| Hi there,
Good catch! You're right, the "alerting" should be "accepting" in this case. I'll go ahead and let our documentation gurus know that this should be fixed. :-) Thanks, Jeff |
| login |
|