Whatever message this page gives is out now! Go check it out!
Step | Procedure | Description |
1 | Define communication channels in the Application.cfc | Client can subscribe or publish to a pre-defined set of channels. To listen to the channel, first register it at the application level. |
2 | Create WebSocket object using the cfwebsocket tag in your CFM template | Creates WebSocket connection with all required properties automatically, and wraps it in a JavaScript object that can invoke various JavaScript methods. The tag internally identifies the IP address and port of the server. |
3 | Implement the business logic using the JavaScript functions provided by the WebSocket object | On runtime, you can make use of the supported JavaScript functions for example, subscribe or publish to achieve your business goals. |
{
this.name="testapp";
this.wschannels=[{name = channelName,cfclistener= channel_listener_CFC}];
}name="websocketName"
onMessage="JavaScript function name"
onOpen="JavaScript function name"
onClose="JavaScript function name"
onError="JavaScript function name"
useCfAuth=true|false
subscribeTo="channel_list">Attribute | Req/Opt | Descriptions |
name | Required | The name of the WebSocket object. This is the reference to the JavaScript objects that are used to call WebSocket JavaScript functions. |
onMessage | Required | The JavaScript function that is called when the WebSocket receives a message from the server. The function requires one argument. |
onOpen | Optional | The JavaScript function that is called when the WebSocket establishes a connection.The function does not require any arguments. |
onClose | Optional | The JavaScript function that is called when the WebSocket closes a connection.The function does not require any arguments. |
onError | Optional | The JavaScript function that is called if there is an error while performing an action over the WebSocket connection. The function requires one argument. |
usecfAuth | Optional | If set to true (default), authentication is not required for WebSocket connection (provided they have already logged in to the application). This is the default value.If false, to authenticate, you have to use the javaScript function authenticate. |
subscribeTo | Optional | Comma-separated list of channels/subchannels to subscribe to. You can specify any or all channels set in the Application.cfc. |
{
this.name="websocketsampleapp1";
this.wschannels=[{name="stocks"}];
}<script type="text/javascript">
/* mymessangehandler function recieves all messages that comes via WebSocket. This function requires one argument.
*/
function mymessagehandler(messageObject)
{
//JavaScript messageobject is converted to a string.
var message = ColdFusion.JSON.encode(messageObject);
var txt=document.getElementById("myDiv");
txt.innerHTML +=message +"<br>";
}
</script>
<cfwebsocket name="mycfwebsocketobject" onmessage="mymessagehandler" subscribeto="stocks" >
<cfdiv id="myDiv"></cfdiv>Function | Description | Syntax | Parameters | |
authenticate | Authenticates the user to a specific channel. Returns true if the connection is open. | authenticate(id, password) For example, mycfwebsocketobject.authenticate("Ben", "password") |
| |
subscribe | Lets the client subscribe to a specific channel. You can send additional information such as age of the user (in the form of custom_header JavaScript object) to the server. This information can be used to take a decision on whether to let the client subscribe or not. Returns true if the connection is open. | subscribe(channel[, custom_header][, messageHandler]) For example, mycfwebsocketobject.subscribe(channel) |
| |
publish | Publishes the message to the channel. If the message is not available use the function invokeAndPublish.Message can be passed in any JavaScript data type (such as array, string, int, or a key-value pair) as a JavaScript object.You can send additional information (in the form of custom_header). The information can be used to decide if to allow the client to publish, for example Only platinum members have rights to publish. Returns true if the connection is open. | For example, publish(channel, message [, custom_header]) mycfwebsocketobject.publish("stocks",msg) |
| |
invokeAndPublish | Invokes a specified method in a CFC file to generate the message that has to be published. Used in scnearios where you have raw data (that needs to be processed) to create a message. Returns true if the connection is open. | For example, invokeAndPublish(channel, cfcName, functionName [, argumentsArray] [, custom_header]) mycfwebsocketobject.invokeAndPublish(ch, "employee", "getEmployeeDetails", ["eid_1"]) |
| |
getSubscriberCount | Provides the number of subscribers for a specific channel. Returns true if the connection is open. | For example, getSubscriberCount(channel) mycfwebsocketobject.getSubscriberCount("stocks") |
| |
getSubscriptions | Provides all channels the client is subscribed to, as a JavaScript array. Returns true if the connection is open. | getSubscription() | Supports inline call back functionality to receive asynchronous response. | |
openConnection | Opens a WebSocket connection (if not already open). Returns undefined on successful completion. | openConnection() | ||
isConnectionOpen | Verifies whether the WebSocket connection is open. Returns true if the connection is open. | isConnectionOpen() | ||
closeConnection | Closes a WebSocket connection. Returns undefined on successful completion. The boolean value represents the status of the call only for openConnection and closeConnection. | closeConnection() | ||
unsubscribe | Unsubscribes a client from the specified channel. After the client unsubscribes, the messages in the channel are not published to the client. Returns true if the connection is open. | For example, unsubscribe(channel) mycfwebsocketobject.unsubscribe(channel) |
|
When you use these functions, a boolean value indicating the status of the call or connection is returned. But the result of the call is acknowledged at the message handler side. You can categorize the responses at the message handler using the request type token as shown in the following example: if (token.reqType =="getSubscriberCount). |
component
{
this.name="websocketsampleapp3";
this.wschannels=[{name="stocks"}];
}<script>
//messagehandler recieves all the messages from websocket
function mycbHandler( messageobj)
{
var message = ColdFusion.JSON.encode(messageobj);
var txt=document.getElementById("myDiv");
txt.innerHTML +=message +"<br>";
}
//openhandler is invoked when socket connection is
function openHandler()
{
var txt=document.getElementById("myDiv");
txt.innerHTML +="open Handler invoked <br>";
}
function subscribeMe()
{
var channelname = document.getElementById("channelname").value;
mywsobj.subscribe(channelname);
}
function getSubscribers()
{
var channelname = document.getElementById("channelname").value;
mywsobj.getSubscriberCount(channelname);
}
function unsubscribe_Me()
{
var channelname = document.getElementById("channelname").value;
mywsobj.unsubscribe(channelname);
}
function publishClient()
{
var channelname = document.getElementById("channelname").value;
var message = document.getElementById("msg").value;
mywsobj.publish(channelname,message);
}
function get_Subscriptions()
{
mywsobj.getSubscriptions();
}
function invokenpublish()
{
cfcname = document.getElementById("cfcname").value;
fnname = document.getElementById("fnname").value;
channelname = document.getElementById("channelname").value;
mywsobj.invokeAndPublish(channelname, cfcname, fnname);
}
function invokefn()
{
cfcname = document.getElementById("cfcname").value;
fnname = document.getElementById("fnname").value;
channelname = document.getElementById("channelname").value;
mywsobj.invoke(cfcname, fnname);
}
function opensocket()
{
var txt=document.getElementById("myDiv");
txt.innerHTML+="opening socket"+"<br >";
x=mywsobj.openConnection();
}
function stopsocket()
{
var txt=document.getElementById("myDiv");
txt.innerHTML+="closing socket"+"<br >";
x=mywsobj.closeConnection();
}
function checksocket()
{
var x=mywsobj.isConnectionOpen();
var txt=document.getElementById("myDiv");
txt.innerHTML+=x+"<br >";
}
</script>
<form name="f">
<!---Define JS websocket object name and messagehandler and openhandler --->
<cfwebsocket name="mywsobj" onMessage="mycbHandler" onOpen="openHandler"/>
<br> Subscribe to:
<input id="channelname" name="channelname" type="text" value="stocks" >
<input id="stocksSubscribe" type="button" value="stocksSubscribe" onclick="subscribeMe();">
<input id="unsubscribeMe" type="button" value="unsubscribeMe" onclick="unsubscribe_Me();">
<input id="getSubscribersCF" type="button" value="getSubscribersCF" onclick="getSubscribers();">
<input id="getSubscriptions" type="button" value="getSubscriptions" onclick="get_Subscriptions();">
<br>
Message :<input id="msg" type="text" >
<input id="publishMe" type="button" value="publishMe" onclick="publishClient();">
<br>
CFC Name: <input id="cfcname" name="cfcname" type="text" value="invokeandpublish" >
Function Name: <input id="fnname" name="fnname" type="text" value="publishall" >
<input id="invoke_publish" type="button" value="invoke_publish" onclick="invokenpublish();">
<input id="invoke" type="button" value="invoke" onclick="invokefn();">
<br>
<input id="stop" name ="Close" type="button" value ="stop" onclick="stopsocket()" >
<input id="open" name ="Open" type="button" value ="open" onclick="opensocket()" >
<input id="check" name ="Check" type="button" value="check" onclick="checksocket()" >
<br>
<div id="myDiv"></div>
</form>Client | Channel subscribed to | Receives messages when publishing to Stocks | Receives messages when publishing to Stocks.Finance | Receives messages when publishing to Stocks.Banks | Receives messages when publishing to Stocks. Finance.Adobe |
Client 1 | Stocks | Yes | Yes | Yes | Yes |
Client 2 | Stocks.Finance | No | Yes | No | Yes |
Client 3 | Stocks.Banks | No | No | Yes | No |
Client 4 | Stocks.Finance.Adobe | No | No | No | Yes |
Function getSubscribers called with the channel | Returns the ID of clients subscribed to the following channels |
Stocks | Stocks |
Stocks.Finance | Stocks.Finance and Stocks |
Stocks.Banks | Stocks.Banks and Stocks |
Stocks.Finance.Adobe | Stocks.Finance.Adobe, Stocks.Finnance, and Stocks |
WebSocket object JavaScript function | Function(s) called in the channel listener CFC |
subscribe | allowSubscribe |
unsubscribe | afterUnsubscribe |
publish | allowPublish |
invokeAndPublish | allowPublish |
getSubscribers | None |
getSubscriptions | None |
invoke | None |
openConnection | None |
isConnectionOpen | None |
closeConnection | None |
Function | Descriptions | Syntax | Parameters |
allowSubscribe | Invoked before subscribing to a channel/sub-channel. Used to check if the requested client can be allowed to subscribe to the given channel. If returns true, allows the requested client to subscribe.Properties defined in the object subscriberInfo can be used decide on authorization. | allowSubscribe(subscriberInfo) |
|
allowPublish | Called before publishing to a channel/sub-channel. Used to check whether the requested client can be allowed to publish to the given channel. Properties defined in the publisherInfo struct can be used to take the authorization decision. If returns true, allows the requested client to publish. | allowPublish(publisherInfo) |
|
beforePublish | Invoked before publishing the message on requested channel/sub-channel. Used to execute a business logic if required and to format messages. | beforePublish(message, publisherInfo) |
|
canSendMessage | Invoked before sending the message to a subscribed client.Used to decide whether the message should be sent to a specific client. Called for all clients subscribed to a channel separately. Properties defined in the object subscriberInfo and publisherInfo help you find client's interest in the message. | canSendMessage(message, subscriberInfo, publisherInfo) |
|
beforeSendMessage | Invoked before sending the message to a subscribed client. Can be used to format the message as per client requirement before sending. This function is executed for each client. | beforeSendMessage(message, subscriberInfo) |
|
afterUnsubscribe | Called after you unsubscribe from a channel/sub-channel. Used to clear the settings if necessary.. | afterUnsubscribe (subscriberInfo) |
|
{
this.name = "channelspecifichandlerexample";
this.wschannels = [{name="stocks"}, {name="news"}, {name="products"}];
}<script type="text/javascript">
function stockhandler(stocksmessageobj){
//write appropriate logic here to handle data coming on stock channel
if (stocksmessageobj.data != null) {
var message = stocksmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Stock Handler: " + message + "<br />";
}
}
function newshandler(newsmessageobj){
//write appropriate logic here to handle data coming on news channel
if (newsmessageobj.data != null) {
var message = newsmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "News Handler: " + message + "<br />";
}
}
function productshandler(productsmessageobj){
//write appropriate logic here to handle data coming on products channel
if (productsmessageobj.data != null) {
var message = productsmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Product Handler: " + message + "<br />";
}
}
function subscribeMe(){
var channel = document.getElementById("channeloption").value;
switch (channel) {
case "stocks":
mysock.subscribe("stocks", {}, stockhandler);
break;
case "news":
mysock.subscribe("news", {}, newshandler);
break;
case "products":
mysock.subscribe("products", {}, productshandler);
break;
}
}
function mycbHandler(messageobj){
var message = ColdFusion.JSON.encode(messageobj);
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Message Handler : " + message + "<br />";
}
</script>
<cfwebsocket name="mysock" onmessage="mycbHandler"/>
<form>
<select id="channeloption">
<option>
stocks
</option>
<option>
news
</option>
<option>
products
</option>
</select>
<input id="subscribe" name="subscribe" value="Subscribe" type="button"
onclick="subscribeMe();">
</form>
<div id="myDiv">
</div><cfscript>
if(isdefined("form.publish"))
WsPublish(#form.channel#, #form.message#);
</cfscript>
<cfform method="post">
<cfselect name="channel">
<option>
stocks
</option>
<option>
news
</option>
<option>
products
</option>
</cfselect>
Message:
<input id="message" name="message" type="text">
<cfinput id="publish" name="publish" value="publish" type="submit">
</cfform>component
{
this.name = "customoptionexample";
this.wschannels = [{name="Testchannel", cfclistener="TestListener"}];
}<script type = "text/javascript">
function msgHandler(messageobj)
{
var ouputdiv=document.getElementById("myDiv");
var message = ColdFusion.JSON.encode(messageobj);
ouputdiv.innerHTML+=message +"<br >" +"<br>";
}
function subscribeMe()
{
var clientAge = document.getElementById("age").value;
TestSocket.subscribe("Testchannel", {age: clientAge}); }</script>
<cfwebsocket name="TestSocket" onMessage="msgHandler"/>
<br>
Age <input id="age" name="age" type="text">
<br>
<input id="stocksSubscribe" type="button" value="Subscribe" onclick="subscribeMe();">
<div id="myDiv"></div>component extends="CFIDE.websocket.ChannelListener"
{
public boolean function allowSubscribe(Struct subscriberInfo)
{
if(structKeyExists(subscriberInfo, "age"))
if((subscriberInfo.age gt 18)) {
return true;
}
else
{
return false;
}
else
return false;
}
}component
{
this.name = "customoptionexample1";
this.wschannels = [{name="bidchannel", cfclistener="bidListener"}];
boolean function onApplicationStart()
{
application.bidvalue = 1;
}
}<script type="text/javascript">
function msgHandler(messageobj){
if (messageobj.data != null) {
var ouputdiv = document.getElementById("myDiv");
var message = messageobj.data;
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
if (messageobj.code == -1 && messageobj.reqType == "publish") {
var ouputdiv = document.getElementById("myDiv");
var message = "Bid amount is less than current bid value";
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
}
function publishme(){
var bidvalue = document.getElementById("amount").value;
var clname = document.getElementById("name").value;
var message = "Bid placed by " + clname + " Amount " + bidvalue;
TestSocket.publish("bidchannel", message, {
value: bidvalue
});
}
</script>
<cfwebsocket name="TestSocket" onmessage="msgHandler" subscribeto="bidchannel"/><br>
Bid Amount:
<input id="amount" name="amount" type="text">
Name:
<input id="name" type="text">
<input id="publishmessage" type="button" value="Publish" onclick="publishme();">
<div id="myDiv">
</div>component extends="CFIDE.websocket.ChannelListener"{ public boolean function
allowPublish(Struct publisherInfo)
{
if(structKeyExists(publisherInfo, "value"))
if((publisherInfo.value gt application.bidvalue))
{
application.bidvalue = publisherInfo.value;
return true;
}
else
{ return false;
}
else
return false;
}
}{
this.name = "websocketApp1";
this.wschannels = [{name="selectorchannel"}];
}<script type="text/javascript">
function msgHandler(messageobj)
{
if (messageobj.data != null) {
var ouputdiv = document.getElementById("myDiv");
var message = messageobj.data;
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
}
function subscribeMe()
{
var amt = document.getElementById("amount").value;
var selectstring="value gt "+ amt;
TestSocket.subscribe("selectorchannel", {selector : selectstring});
document.getElementById("stocksSubscribe").style.display = 'none';
document.getElementById("l1").style.display = 'none';
document.getElementById("l2").style.display = 'block';
document.getElementById("publisme").style.display = 'block';
}
function publishme()
{
var amt = document.getElementById("amount").value;
TestSocket.publish("selectorchannel","Value is " +amt,{value: amt})
}
</script>
<cfwebsocket name="TestSocket" onMessage="msgHandler"/>
<br />
<lablel id="l1">Stock value above which you want to recieve message</lablel>
<label id="l2" style="display:none;">Value</label>
<input id="amount" name="amount" type="text">
<br>
<input id="stocksSubscribe" type="button" value="Subscribe" onclick="subscribeMe();">
<input id="publisme" type="button" value="Publish" onclick="publishme();" style="display:none;">
<div id="myDiv"></div>OnWSAuthenticate(username, password, connectionInfo)Parameter | Description |
username | Name of the user that has to be authenticated. |
password | Password for the user. |
connectionInfo | A struct that contains the following keys:
|
{
this.name="websocketsampleapp23";
this.wschannels=[{name="stocks",cfclistener="stocksListener"}];
function onWSAuthenticate(username, password, connectionInfo)
{
//write appropriate logic to fetch user password in funtion checkPassword
If(checkPassword(username) eq password)
{
connectionInfo.authenticated="YES";
//Role is the custom information that you provide
connectionInfo.role= "admin";
return true;
}
else{
connectionInfo.authenticated="NO";
return false;
}
writedump("#connectionInfo#","console");
}
}User: <input name="username" type="text" id="username" value="admin"><br>
Pass: <input name="password" type="text" id="password"><br>
<input type="submit" name="Submit" value="Submit">
</form>
<cfif structKeyExists(form,"username")>
<cflogout>
<cfset r = "user">
<cfif FORM.username is "admin">
<cfset r = "admin">
</cfif>
<cflogin idletimeout="1800">
<cfloginuser
name = "#FORM.username#"
password ="#FORM.password#"
roles = #r#>
</cflogin>
<cfoutput>Authorized user: #getAuthUser()#</cfoutput><br>
<cfoutput>Authorized role: #GetUserRoles()#</cfoutput><br>
<cflocation url="index.cfm">
</cfif>{
this.name = "myssoexample";
this.wschannels = [ {name = "sso", cfclistener="ChannelListener"}];
}var mycbHandler = function(msg)
{
if(msg.data)
{
var messageObject = msg.data;
var txt=document.getElementById("myDiv");
if((messageObject.indexOf("{")!=-1)){
var jsonValue = (new Function( "return( " + messageObject + " );" ))();
if(jsonValue){
txt.innerHTML+="<br>Authenticated : " + jsonValue.authenticated;
txt.innerHTML+="<br>UserName : " + jsonValue.username;
txt.innerHTML+="<br>Role : " + jsonValue.roles;
}
}
}
}
var openHandler = function()
{
mysock.publish("sso","hii");
}
</script>
<form name="f">
<cfwebsocket name="mysock" onMessage="mycbHandler" subscribeto="sso" onOpen="openHandler" useCFAuth="yes"/>
<div id="myDiv"></div>
</form>{
public any function beforeSendMessage(any message, Struct subscriberInfo)
{
writedump(var=subscriberInfo.connectionInfo, output="console");
return subscriberInfo.connectionInfo;
}
}Function Name | Syntax | Description |
WSgetSubscribers | WSgetSubscribers (channel) | Returns an array of struct with clientID and subcriberInfo as the keys. |
WSPublish | WSPublish(channel, message [, filterCriteria]) | Sends messages to a specific channel. Optionally, you can specify a filter criteria struct. |
WSGetAllChannels | WSGetAllChannels () | Provides all the channels defined in the Application.cfc as an array. |
{"clientid":2077108630,"ns":"coldfusion.websocket.channels","reqType":"subscribe","code":0,"type":"response","msg":"ok"}Key | Description |
clientid | Unique ID assigned to a client. |
ns | ColdFusion WebSocket namespace |
reqType | The type of request represented by the JavaScript functions (for example, publish, or invokeandpublish). |
code | See <code section> |
type | Either response or data.
|
msg | Applies to responses; ok if successful. On failure, returns the cause of failure. |
subscriberCount | An integer that stands for the subscriber count. |
channels | Applies to getSubscriptions, list of all subscribed channels. |
data | Message is conveyed through data. |
publisherID | Client ID of the publisher. If the message is from WSPublish, the ID is 0. |
channelname | Name of the channel. |
{"clientid":2077108664,"ns":"coldfusion.websocket.channels","channelsnotsubscribedto":"stocks.a","reqType":"subscribeTo","code":0,"type":"response","msg":"Subscription failed for channel(s) 'stocks.a'.","channelssubscribedto":"stocks"}