ColdFusion 10 Scheduled tasks and misfires

In the event that you missed the changes in ColdFusion 10, I will recap one of them. The scheduled task engine was replaced with the Quartz Job Scheduler. This fancy new scheduler comes with more features then you will probably ever use. There are now handlers for when tasks start, finish, and error. Tasks can now call other tasks when they finish. You can even define rules for when a task fails or fails to start on-time.

There is also greater control on when tasks run. You can now schedule tasks to run faster than every 60 seconds. You can also use crontime to schedule a task. For example, this... "0 23 ? * MON-FRI" states to run a task every weekday at 23:00:00. You could even do something crazy like this "2-59/3 1,9,22 11-26 1-6 ? 2003" which translates into "In 2003 on the 11th to 26th of each month from January to June every third minute starting from 2 past 1am, 9am and 10pm".

But in creating crazy schedules or faster run times you now run into another feature of the new scheduled task engine, misfires. Misfires are a fancy name for a task that didn't start when it should have. For example, if the task was scheduled to start at 10:00:00 and it is now 10:00:01 and the task has not started it is now considered misfired.

Missing the start time is just one of a few reasons a task can misfire. Some of the others are, the scheduler engine is down, there were no available worker threads, or a task was configured to start in the past. You can also generate a misfire by resuming a paused task. By default the scheduler uses a "smart policy" to handle misfires.

[More]

Developer Week Slides and Code

Sorry for the delay in getting this posted. Here are the slides and the sample code from my ColdFusion Developer Week 2012 presentation; User Experience upgrade through HTML5 charts and videos.

The sample code does contain the sample videos as well so it is a bit large (45mb).

Download Sample Code

Till next time...

--Dave

ColdFusion Developer Week

In just a couple days begins ColdFusion Developer Week. Developer week is a full week of online sessions all about ColdFusion 10.

Yours truly will be speaking on HTML5 charts and video. While neither of these are new to ColdFusion 10 they did get a overhaul.

So, signup, attend a couple sessions, and build something great. Oh... and the best part... it is all FREE!

Here are the details....

ColdFusion Developer Week is happening between the 4th and 8th June.

With the launch of ColdFusion 10, we are back with the 2nd ColdFusion Developer Week, a series of free, live webinars hosted by seasoned ColdFusion experts. The webinars cover a wide range of topics, from what ColdFusion is and how to code it, to more in-depth topics related to CF10- HTML5, REST, ORM, Security enhancements and more.

If you are a new developer, someone with little or no ColdFusion experience, or even if you have been using ColdFusion all your life, these sessions are ideal for you. The ColdFusion Developer Week provides something for everyone so sign up now.

http://adobe.com/go/cfdeveloperweek

See you there...

--Dave

ColdFusion 10 released

Here is the obligatory blog about the release of the next version of ColdFusion 10. I have to say I am very excited about this release and the new features in it.

Go get it.. Go build something amazing.

www.coldfusion.com

Till next time,

--Dave

Websockets demo: Log Watcher

So, I really wanted to create a demo for websockets that was not the norm. I wanted to try something that was more of a "what could I really do with with this" demo. After bouncing around a few ideas I finally settled on this, Log Watcher.

How many times have you wished you could tail a log file on your remote ColdFusion server? How many times have you remoted into your server to tail a log? If you are anything like me (probably not but for arguments sake lets say you are) you have probably done it once this week. At the very least once in the past few weeks.

What is log tailing? Well, to sum up it is viewing a log file as new lines are written to the file. This can be accomplished on unix using "tail -f {log}" or using something like BareTail on windows.

Now, what if you didn't have to remote into the server to tail the log? This is where Log Watcher comes in. Log Watcher allows you to tail a log via a web browser. This low overhead app does the same thing as a server based tail but with a little more flare.

So, how does it work? Well, it is all made possible due to ColdFusion 10. The interface is a simple browser app using Bootstrap for the pretty (I don't do pretty). The real guts of the app is on the server. Here, threading is used and a couple java objects to do a constant read on a file. The data (rows) from the log file are pushed to the client using websockets.

To accomplish this there are a few things I had to overcome. First was dealing with thread management. Creating threads that are designed to run forever is not something you generally want to do in a browser based application. This turned out be one of the more challenging parts. But this became infinitely easier thanks to a new setting in ColdFusion 10 to set the timeout to none.

view plain print about
1<cfsetting requesttimeout="0">

Next was dealing with the display and that all logs are not created equal. Then there was the issue of the app crashing the ColdFusion server (more on this later). A lot of trial and error went into building a way to display the log rows effectively. Once I solved these issues I was off to the races.

The client portion of the app is very basic. The only coolness there is the tiny amount of code for the client to subscribe to a web socket. Now, thanks to how websockets were implemented this results to just one tag

view plain print about
1<cfwebsocket name="lrbase" onmessage="wsFunctions.mycbHandler" subscribeto="lrbase"/>

This one little tag brings in all the necessary bits to do websockets. All we have to put in is the name of the websocket (as defined in applicaiton.cfc), the message handler, and the name of the channel to auto subscribe to on load.

Then just a little javascript to process the incoming messages. Here I handle the incoming data and split it up so I can display the data in a table. Name spacing my javascript has become a little habit. I don't do it all the time, but I find it useful when I want to encapsulate some code.

view plain print about
1var wsFunctions = (function() {
2
3    var wsResponsProcessor = function(obj){ // handle responses from WS
4
5        if (obj.type == 'data'){
6            
7            $('#mainContent2').show();            
8            output = splitMessage(obj.data);            
9            if (rowOut == 1 && useTableFormat(currentLog)){
10                    $('#headerRow').html(output);
11            
12            } else {
13            
14                if (loadDirection == 1){
15                    $(document).scrollTop($(document).height());                         
16                    $('#contentTable').append('<tr><td>'+rowOut+'</td>'+output+'</tr>');
17                } else {
18                    $('#contentTable').prepend('<tr><td>'+rowOut+'</td>'+output+'</tr>');
19                }    
20            }
21            rowOut++;
22        }    
23     
24 }
25    
26    return {
27        
28        mycbHandler: function(aEvent){
29         wsResponsProcessor(aEvent);
30        }
31    };    
32})();

To sum up all this javascript. If the type is "data" it processes the message. It is possible for the message to be other types for example the response message when subscribing. The message is then passed of to the splitMessage function. This function handles splitting the message into columns if the log is formatted that way. Then depending on load direction the row is either appended or prepended to the display.

To get the ball rolling there is a click handler on the log list. This processed the selected log and makes a ajax call to the server.

The logLoader.cfm does a few things. First, it includes the kill.cfm file. This file runs and sets a server var that any currently running thread will see and cause the thread to terminate. We then sleep the call for 1.5 seconds to give any other thread a chance to terminate. We then create the thread name and call the thread component.

The thread component is where the "magic" happens. This is where the thread is created and starts reading the requested log file.

view plain print about
1<cffunction name="readLog" access="public">
2        <cfargument name="threadName" type="string" required="true" />
3        <cfargument name="log" type="string" required="true" />
4        <cfargument name="channel" type="string" required="true" />
5        
6        
7        <cfthread action="run" name="#arguments.threadName#" logfile="#arguments.log#" channel="#arguments.channel#">
8        
9            <cfset server.channels["#attributes.channel#"] = thread.name>
10            <cfsetting requesttimeout="0">
11            <cfscript>                
12                FileName = "#server.logbase#/#attributes.logfile#.log";
13                FileIOClass = createObject("java", "java.io.FileReader");
14                FileIO = FileIOClass.init(FileName);                
15                LineIOClass = createObject("java", "java.io.BufferedReader");
16                LineIO = LineIOClass.init(FileIO);
17            
</cfscript>
18            <cfloop condition="1 eq 1">
19                <cfif server.channels["#attributes.channel#"] is not thread.name>
20                    <cfexit>
21                </cfif>        
22                
23                <cfset CurrLine = LineIO.readLine()>
24                
25                <cfif IsDefined("CurrLine")>                    
26                    <!---send websocket message--->
27                    <cfset wspublish("lrbase.#attributes.channel#", CurrLine)>
28                <cfelse>        
29                    <cfthread action="sleep" duration="1000" / >
30                </cfif>
31                    
32            </cfloop>
33        </cfthread>
34    </cffunction>

Walking through the function the first thing is does is create a thread with an action of run. This will create a running thread that will be come "detached" from the request that created it. First a server var is set with this threads name and then the timeout is set to 0 (infinity). Next a couple java objects are utilized to read the file. This will allow for a non-blocking read on the file. This type if read is desired so that the system can still write to the file while it is being read.

Next a loop is created that has a condition that will never end. Then in the loop a check is made to see if the server var for the active thread matches the current thread. If not the loop will exit thus also ending the thread. Next a line in the file is read. This will always read the next unread line. So, it will start at line 1 and get the next line on every loop. Eventually the currline var will not be defined. This is because the whole file is read. If the var is defined a websocket message is published to the channel for the app. This will magically make it back to the client and displayed.

Now, if the currline var is undefined the thread is put to sleep for a second. This is here because this is where the ColdFusion server was crashing. Not putting the sleep here caused CF to spike the processor up to 100% and eventually die. After some trial and error the 1 second sleep seemed to be the sweet spot. Now the thread was never over 2% cpu load.

As the loop continues over time any new line written to the file will be picked up and processed.

So there you have it. You can download the code (attached to this post) and check it out. Just unzip the code and drop it into your web root for ColdFusion 10.

Till next time...

--Dave

ColdFusion 10 WebSocket Demo App

So,

Websockets what are they? Here is what wikipedia had to say on the subject http://en.wikipedia.org/wiki/WebSocket. Basically put, websockets let you do a server "push" to a client browser.

If you have ever used BlazeDs you will be familiar with this type of technology. However with BlazeDS there was a constant open connection to the server. With websockets there is no persistant open connection. This greatly reduces overall overhead for both the client and the server.

So, what can you build with websockets? Well lots of stuff, you can create the obligatory chat client. Maybe an ad system that feeds new ads to a client. Maybe even a game where 2 people can play against each other.

Well, I figured it would be better just to build something to demo its features then to just talk about it. So, with that, I made a game. It is a 2 player game that allows people to play against each other in the same fashion as Battleship.

The downloadable code is attached to this post. A couple notes about the code. To run it effectively you need to open 2 browsers, not to browser windows. Also, I didn't to an exhaustive amount of testing on the app. If you just use it as intended it should work just fine. Also, if you have a console (firebug, or Developer Tools) running you can see the messages passed back and forth. In the base.js file at the very bottom uncomment the console.log line to see the output. Take a look at the code. Use it as an example to build your own next great thing. Let me know if you have any issues, questions or comments. I will do my best to assist as much as possible.

Till Next time...

--Dave

ColdFusion 10 and Builder 2.01 Public Beta

Yea.. title just about covers it. So... Go get it and check out all the new hotness. There are many new things to talk about and use. Here is a short list of the features that interest me the most.

  • Websockets
  • Switch from jRun to Tomcat
  • Rest web services
  • Security enhancements
  • Charting
  • Scheduler
  • Hotfix updater

http://labs.adobe.com/technologies/coldfusion10/

Go get it for your self. Come up with your own list. Build something awesome.

Till next time...

--Dave