Re: External communication with SCXML

Ok, here is what I came up with …

Pulling data (David's solution):

<scxml datamodel="ecmascript">
	<script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" />
	<state id="start">
		<onentry>
			<fetch 
				target="http://data.wien.gv.at/daten/wfs?service=WFS&amp;request=GetFeature&amp;version=1.1.0&amp;typeName=ogdwien:BAUMOGD&amp;srsName=EPSG:4326&amp;outputFormat=json&amp;maxfeatures=5" 
				callback="data.wien" 
				type="json" />
		</onentry>
		<state id="wait">
			<transition event="data.wien" target="final">
				<script>
					dump(_event);
				</script>
			</transition>
		</state>
	</state>
	<final id="final" />
</scxml>

The data.wien.gv.at server is just any server that delivers JSON content - if anyone has a more "canonic" server for my examples, I'd be glad to substitute. This solution is pretty much the one described by David, though I do not support all request types yet. The target is fetched asynchronously and the callback event is generated as soon as downloading is complete. This works quite well and I like the way it integrates into SCXML's language features.

For serving data, I came up with the following:

<scxml datamodel="ecmascript">
	<script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" />
	<state id="start">
		<!-- 
			I went for explicit invokers instead of a response element in executable content
			as it provides better control over the path where to serve data.
			-->
		<invoke type="httpserver" id="servlet.data">
			<!-- server path where to listen -->
			<param name="path" expr="'data'" />
			<!-- the name of events originating from requests at this url -->
			<param name="callback" expr="'http.data'" />
		</invoke>
		<invoke type="httpserver" id="servlet.exit">
			<param name="path" expr="'exit'" />
			<param name="callback" expr="'http.exit'" />
		</invoke>
		<state id="loop">
			<transition event="http.data" target="loop">
				<script>
					dump(_event);
				</script>
				<!-- Sending a http reply is to send the invoker id a "reply.<requestId>" event -->
				<send target="#_servlet.data" eventexpr="'reply.' + _event.data.reqId">
					<!-- This will end up as a header field -->
					<param name="Foo" expr="_ioprocessors" />
					<!-- JSON string in the content, _ioprocessors as an example -->
					<content expr="_ioprocessors" />
				</send>
			</transition>
			<transition event="http.exit" target="final">
				<script>
					dump(_event);
				</script>
				<!-- This will never get delivered as we terminate before -->
				<send target="#_servlet.exit" eventexpr="'reply.' + _event.data.reqId" /> 
			</transition>
		</state>
	</state>
	<final id="final" />
</scxml>

Data can now be requested via "wget -qSO - http://hostname:port/data" and "wget -qSO - http://hostname:port/exit" closes the interpreter session.

Serving data is somewhat more convoluted then fetching. I offer "httpserver" invokers, which take again a callback as the name of the events they will generate and a path as part of an url, where the interpreter is waiting for basichttp events anyway. As soon as I have a request at the invokers url, I populate _event with _event.reqId, _event.content, _event.headers and _event.type, set the callback as its name and deliver it to the interpreters external queue.
To reply to such a request, I expect an event called "'reply.' + _event.reqId" send to the invoker's id. Params or namelist will end up as header fields and the content as the response content obviously. To give an idea about the performance: the above request/reply cycle takes a little more than 10ms to complete (measured with "time wget …") on localhost.

I do like to have explicit "httpserver" invokers (though I might rename them to "httpservlet" still) to have control over the path where the interpreter will accept requests, but the way the replies are constructed takes some getting used to. One remaining problem is that the last send is never delivered: The event from "http.exit" will trigger the transition to the final state and the invoker will already be gone. But I don't think this is something a response element could solve as it will have the same problem.

Does anyone have some suggestions on how to integrate more closely with SCXML's language features?

Best regards
Stefan

P.S.: the example in http://www.w3.org/TR/scxml/#DataSharing is wrong: ought to be "targetexpr="'#_' + myInvoke"" with an underscore after #

Received on Thursday, 14 February 2013 01:50:04 UTC