if (not structKeyExists(server, "cfjavascript")) {
// Cache helper function and broker instance in server scope
server.cfjavascript = structNew();
// Convert CFML structs, arrays and queries to Java HashMaps and Arrays - the LCDS API doesn't like CFML types
function convertToJava(x) {
var key = "";
var map = "";
var cols = "";
var row = "";
var colIndex = "";
var aRows = "";
var stRow = "";
// TODO: Should really convert straight to java array of maps
if (isQuery(x)) {
aRows = arrayNew(1);
cols = listToArray(x.columnList);
for (row = x.recordCount; row > 0; row--) {
stRow = structNew();
for (colIndex = arrayLen(cols); colIndex > 0; colIndex--) {
stRow[cols[colIndex]] = x[cols[colIndex]][row];
}
aRows[row] = stRow;
}
x = aRows;
}
if (isStruct(x)) {
map = createObject("java", "java.util.HashMap").init();
for (key in x)
map.put(key, convertToJava(x[key]));
return map;
} else if (isArray(x)) {
for (key=1; key <= arrayLen(x); key++)
x[key] = convertToJava(x[key]);
return x.toArray();
}
return x;
}
server.cfjavascript.convertToJava = convertToJava;
// Because LCDS is running in the ColdFusion JVM, we can talk directly to it's API
server.cfjavascript.broker = createObject("java", "flex.messaging.MessageBroker").getMessageBroker(javaCast("null", ""));
// This is the unique id for our ColdFusion server - it is a client of LCDS
server.cfjavascript.clientId = createUUID();
// Work out what the subtopic header name should be and cache it
asyncMessageClass = createObject("java", "flex.messaging.messages.AsyncMessage");
server.cfjavascript.SUBTOPIC_HEADER_NAME = asyncMessageClass.SUBTOPIC_HEADER_NAME;
}
// Create a message instance using attributes passed to the tag
message = createObject("java", "flex.messaging.messages.AsyncMessage").init();
message.setDestination("cfjavascript");
message.setClientId(server.cfjavascript.clientId);
message.setBody(createObject("java", "java.util.HashMap").init());
message.setMessageId(getTickCount() & randRange(1,99999));
message.setTimestamp(getTickCount());
message.setHeader(server.cfjavascript.SUBTOPIC_HEADER_NAME, attributes.topic);
for (key in attributes.headers) {
message.setHeader(key, attributes.headers[key]);
}
structDelete(attributes, "headers");
structDelete(attributes, "topic");
/*
Prefix javascript with code to copy arguments out of __args
passed to function literal into local scope, so that we can
refer to arguments without a prefix in Javascript.
*/
defs = "";
for (key in attributes) {
defs &= "var " & key & "=__args." & key & ";";
}
message.getBody().put("script", defs & thisTag.generatedContent);
message.getBody().put("arguments", convertToJava(attributes));
// Send the message through the cached broker instance
server.cfjavascript.broker.routeMessageToService(message, javaCast("null", ""));
// Don't output the javascript fragment to the page
thisTag.generatedContent = "";
import mx.messaging.events.MessageEvent;
import mx.collections.ArrayCollection;
// Pick up our selector details from the parameters passed to the SWF and subscribe to the destination
private function start() : void {
if (parameters.selector != null)
consumer.selector = parameters.selector;
if (parameters.topic != null)
consumer.subtopic = parameters.topic;
consumer.subscribe();
}
// Create a javascript function literal, setting its body and arguments to the message contents
private function messageHandler(event:MessageEvent):void {
ExternalInterface.call("function(__args) {" + (event.message.body.script as String) + "}",
event.message.body.arguments);
}