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); }