ColdFusion + Ext JS Position: Los Angeles

This was forwarded to me yesterday. Anyone who might be interested, ping me on the contact form and I'll forward you the details:

ColdFusion Developer will be responsible for the development of financial reporting systems. He/She will also develop detailed system design and programming specifications, support daily business activity by providing technical support of systems and regularly meet with the IT project lead to review progress and problems related to the job. Additionally he/she will design intuitive and effective UIs using modern client-side technologies, including AJAX, Sencha Ext JS, and other JavaScript libraries.

ColdFusion developer with 5 years+ experience. Knowledge of ColdFusion CFC components, and MVC frameworks, and current feature set in ColdFusion 9.

Knowledge of (Sencha/4.1) Ext JS

Excellent knowledge of JavaScript, HTML, CSS, Web services, and importing Web-based data to Excel.

Good written and verbal communication skills.

Maintains a solid knowledge of information system software development life cycle and quality assurance

Demonstrates proficiency in systems analysis of business requirements.

Good knowledge of relational databases and SQL, experience with Oracle including writing stored procedures, triggers, views etc?

ColdFusion 10 is Now Available

Adobe has released ColdFusion 10. The engineering team has done a fantastic job putting this release together. Here's a short list of some of what's new:

  • Improved/Updated
    • caching
    • ORM
    • webservices
    • scheduler
    • hotfix management
    • security
    • MS Exchange integration
    • security
    • Solr
    • charting (now html 5)
    • Java integration
    • Flex and AIR lazy loading
    • VFS
    • more!
  • html 5 support
  • websockets
  • RESTful services
  • greater cfscript parity
  • geo-tagging
  • CFC auto constructors
  • method chaining
  • closures
  • Tomcat (no more JRun)
  • more!
    • Wow! A lot of changes and additions. The team has been in overdrive, and it all looks spectacular. Download the free Developer's Edition and start playing.

      As a bonus, they also release an update to ColdFusion Builder as well!

CFQueryReader v2.1: Now with metaData support

The Sencha guys just keep upping the bar, and Ext JS 4.1 is no exception. I've been reading Loiane Groner's Ext JS 4 First Look, to review it, and continually find new, cool stuff. 4.1, however, takes it even further. While upgrading CFQueryReader, I was working with 4.1 RC2. And, while extending the base classes, I came across a new feature that wasn't fully documented yet: adding metaData to a server-side store response for changing configuration on the fly. Sometimes it would be nice to just...change up. Now that 4.1 is fully released, I had to make sure that this worked in CFQueryReader.

So, last night I sat down and hammered out this functionality. It took a lot more than I realised, and I learned a lot more about the Ext JS internal code, but I think CFQueryReader is better for it. Consider the following ColdFusion method:

view plain print about
1/**
2 *    FUNCTION getWithMeta
3 *    This function returns the ColdFusion Query object as part of a struct object.
4 *
5 *    @access remote
6 *    @returnType struct
7 *    @output false
8 */

9function getWithMeta(numeric pageIndex = 1, numeric pageSize = 50, string sort = "", string search = "") {
10    var retVal = {"success" = true, "pageIndex" = ARGUMENTS.pageIndex, "pageCount" = 0, "recordCount" = 0, "message" = "", "getEntries" = "", "metaData" = {"root" = "getEntries", "totalProperty" = "recordCount", "successProperty" = "success", "messageProperty" = "message", "idProperty" = "id", "fields" = []}};
11    StructAppend(LOCAL.retVal, GetEntries(argumentCollection: ARGUMENTS), true);
12    var colArr = ListToArray(LOCAL.retVal.getEntries.columnList);
13    LOCAL.retVal.metaData.fields = [
14        {"name" = "id", "type" = "string", "mapping" = JavaCast("int",0)},
15        {"name" = "title", "type" = "string", "mapping" = JavaCast("int",3)},
16        {"name" = "posted", "type" = "date", "mapping" = JavaCast("int",2)},
17        {"name" = "views", "type" = "int", "mapping" = JavaCast("int",1)}
18    ];
19    return LOCAL.retVal;
20}

I reused my getEntries method, to get my query. Here, I'm creating a metaData object, at the root of the return, to define the dataset. Configuration options that I normally define client side (root, totalProperty, etc) I put in to the metaData key. When the response is received by the client, the reader will pass this metaData in to our app, applying this configuration to our reader, store, model, and so on. In the above method, we let the metaData map our columns to fields, rather than doing it client side (CFQueryReader will automatically skip the column mapping if metaData.fields is present in the response.) Our client side store might now look like this:

view plain print about
1Ext.create('Ext.data.Store', {
2    storeId: 'entryStore',
3    model: 'Entry',
4    remoteSort: true,
5    proxy: {
6        type: 'ajax',
7        url: '/com/cc/Blog/Entries.cfc',
8        extraParams: {
9            returnFormat: 'json',
10            method: 'getWithMeta'
11        },
12        limitParam: 'pageSize',
13        pageParam: 'pageIndex',
14        sortParam: 'sort',
15        reader: {
16            type: 'cfquery'
17        }
18    },
19    autoLoad: true
20});

A full example of this, in action, can be seen on a demo page of the CFQueryReader site. The full source code, of the example, can be found in the CFQueryReader GitHub repository.

Ext JS 4.1 Grid: Part1: Basic Config

Many moons ago, I wrote a series on My First Ext JS Data Grid. It was very popular. In fact, it got me the gig co-authoring two books on Ext JS and spawned an open source project targeted at integrating Ext JS with ColdFusion. But, I did that series back in 2007, using Ext JS 1.1 (maybe?), and an update is long overdue.

[More]

ColdFusion Query Column Order: Did You Know?

Now first let me say that I've only seen this behavior on ColdFusion 9.01 with Cumulative Hotfix 2. My ColdFusion 10 VM blew up this morning, and I haven't had 7 or 8 for a while now, so someone else might have to verify this behavior on those platforms for me.

This morning I was testing out a new feature of Ext JS 4.1, and ran into something interesting. One of the reasons that I wrote CFQueryReader, as well as serializeCFJSON, was because of the way that ColdFusion handles it's JSON conversions of it's native query object.

view plain print about
1{
2    "COLUMNS":["ID","NAME","EMAIL"],
3    "DATA":[
4        [1,"Ed Spencer","ed@sencha.com"],
5        [2,"Abe Elias","abe@sencha.com"],
6        [3,"Cutter","no@address.giv"]
7    ]
8}

I've written before, about how Adobe's dataset serialization is much trimmer, but many client-side libraries and plugins expect a more standardized format.

view plain print about
1{
2 "users": [
3 {
4 "id": 1,
5 "name": "Ed Spencer",
6 "email": "ed@sencha.com"
7 },
8 {
9 "id": 2,
10 "name": "Abe Elias",
11 "email": "abe@sencha.com"
12 }
13 ]
14}

It's not too difficult for us, client-side, to map the column to the proper data position in the record array. In fact, that's basically what CFQueryReader and serializeCFJSON both do. But why is it even necessary? Most of these client-side libraries allow us to write mappings in configurations anyway, so why write something else to do it?

Well, there's two reasons really. First of all, the client-side developer may not have that much insight into the server-side developer's code (they can be different people), and would probably be unaware of API changes. The second reason? Well, if you've used ColdFusion for a while, you might know that there was a time when you could not depend on the column order always being the same. At one point, the columns were returned in alphabetical order. This would make it really hard to figure the position out prior to run time, unless you have intimate knowledge of every change to your API as it happens.

It appears that this isn't as much of a problem today. Kind of. I'll run this query:

view plain print about
1LOCAL.sql = "SELECT    SQL_CALC_FOUND_ROWS id,
2        views,
3        posted,
4        title
5FROM    tblblogentries
6WHERE 0 = 0";
7LOCAL.q = new Query(sql = LOCAL.sql, datasource = VARIABLES.dsn);
8LOCAL.retVal.getEntries = LOCAL.q.execute().getResult();

If you dump the results to the page, you'll see the following:

Now, server-side, ever query comes with a variable we can use to reference the columns used in a query. I'll use ColdFusion's ArrayToList(LOCAL.q.columnList) method to dump the query's columnList property to the page:

Look closely and you'll see that both appear to be in alphabetical order. The query dump and the column list showed them in alphabetical order. That said, we then look at the JSON return:

Wait a minute? Now the columns appear in the same order that they are in the query. That's a change.Let's change the column order in the query, and see if it changes anything.

view plain print about
1LOCAL.sql = "SELECT    SQL_CALC_FOUND_ROWS id,
2        title,
3        posted,
4        views
5FROM    tblblogentries
6WHERE 0 = 0";

Notice that, again, the column order matches that of the order it was used in the query. Running a cfdump of the query, and it's columnList, still show alphabetical order. Why is it different? Why does this matter? Well, I'm going to show you that in a follow-up post (on Ext JS 4.1 and ColdFusion), but in the mean time it's a good thing to know, that the JSON returnFormat will give you query column orders identical to that used in the query. And, as I said above, somebody please verify this for me on other versions of the platform.

JQuery Plugin: serializeCFJSON

Quick note about my serializeCFJSON project out on GitHub. I wrote this quick JQuery plugin to convert ColdFusion's JSON representation of it's native query objects. ColdFusion represents datasets in a trim manner, as an object containing two arrays: One, an array of column names, and the other, an array of arrays, each representing one record of the set. Most representations of recordsets are an array of objects, each record represented as a collection of name/value pairs. ColdFusion's representation is much smaller, removing a lot of unnecessary duplication, but many pre-built frameworks and plugins look for the name/value pair objects.

What the plugin does is convert ColdFusion's representation into the more standard form. Ajax transfer is unaffected, as the trimmer format is still being passed. What we get is some very minor client-side overhead in the creation of a new object. What's more, the plugin recursively searches through a JSON object and converts any ColdFusion query that it finds. So, if you nest your query inside a larger object, the plugin will still convert it for you.

I put up a demo in the Projects menu, at the top of this site. This is a refactor of my Grouped jqGrid example, using the plugin for the data conversion. The full sample code for the demo can be found in the GitHub repository.

Take her out for a spin, and let me know what you think.

CFQueryReader 2.0: Site and Demo Updates

Note: I mistakenly posted this under the wrong title. I must get more sleep ;)

I finally got around to a major overhaul of the CFQueryReader site, including all new demos and documentation of the latest build for Ext JS 4.x.

The new demos for Ext JS 2.x and 3.x include links to legacy API's for both versions of the library. The 3.x version includes an example of using Ext Direct, and the new 4.x demo includes paging data grids.

(Big thanks to Loiane's Ext JS 4 First Look, which showed me very quickly how dead simple Ext JS grids and data stores have become.)

I have not yet tested CFQueryReader with Sencha Touch, but it should work. Any feedback just let me know.

Ext JS 4 and ColdFusion: CFQueryReader 2.0

Wow! It's been too long. I've been so buried playing with new stuff I haven't had much time to write about it. Time to rectify that.

My position over the last year and a half hasn't required me to use Ext JS. And without a project I really haven't had much time to dive in to Ext JS 4. But, I am reviewing Loiane's Ext JS 4 First Look right now, and decided the simplest way to get in was to apply what she was telling me. I knew some of the basics, but Ext JS 4 is a big change, and Loaine's book quickly helped me to grok differences in the class model, updates to the data api, and more. In no time at all I had completely rewritten CFQueryReader, for parsing the native JSON return of a ColdFusion query object. I need to verify, but I'm fairly certain there are more lines of comments than there are code, in the new file. And it is wicked simple. First, include the js file, then define a record of data:

[More]

Intro to jqGrid Part 7: Grouping

OK, I know I said I was done, but I kept playing around and figured I should share. jqGrid, like other (read: Ext JS) good grid implementations, has the ability to group your data. What does that mean exactly? Well, let's look at our demo for inspiration. We've created a grid of blog post entries. Entries have associated Categories. We can reconfigure our grid to show the entries grouped by Category, with Category headers and accordion like separation.

[More]

ColdFusion Security Hotfix and Big Forms

The other day, Adobe released a new Security Hotfix for it's ColdFusion server. There were a number of things addressed in the hotfix, to help protect against Denial of Service attack using a hash algorithm collision. (My wife would say I sound like Charlie Brown's teacher right about now.) Ok, the important thing is you need to update your server.

Now for the fun part. We loaded the fix to our testing servers to run our app around the block prior to pushing this up to production. And, it's a good thing we did. We're preparing for a large deployment, and testing is pretty heavy right now. First thing in is that a form would no longer submit, throwing a 500 error every time. I didn't show me a 500 error, just a blank page. I had to look at Firebug to see the error code response. Now, if you've ever encountered a 500 error from the server then you know they don't typically tell you much. I reproduced the error locally and then went looking through the log files on the server.

In a multi-server configuration there are two core areas to look at log files. The first are the basic JRun logs. On a Windows systems, these files are located in the C:\JRun4\logs folder. Here you will typically find a {instance}-out.log file, and a {instance}-event.log file, for each ColdFusion instance you have configured. Right out of the gate you have admin-event and admin-out logs for the JRun administrator, and cfusion-event and cfusion-out for the default ColdFusion instance. I checked both files for my instance, and saw there weren't any items to tell me about the 500 error, so I then went looking at the ColdFusion logs.

Each ColdFusion instance has it's own set of log files, that you can see in the logs viewer in the ColdFusion Administrator. That said, the ColdFusion Administrator is not really the best place to go through these files, especially when you're really having issues. At this point, you just want to open them yourself. First, you have to find them. You do this through your instance, C:\JRun4\servers\{instance}\cfusion.ear\cfusion.war\WEB-INF\cfusion\logs. You'll probably find multiple log files here, from the application and eventgateway and mail logs, to individual logs from cflog calls.

Our issue, with submitting our form, was answered by the JRun -event logs, which gave me a few error messages saying something like this:

view plain print about
103/27 07:52:00 error ROOT CAUSE:
2coldfusion.filter.FormScope$PostParametersLimitExceededException: POST parameters exceeds the maximum limit specified in the server.
3    at coldfusion.filter.FormScope.parseQueryString(FormScope.java:397)
4    at coldfusion.filter.FormScope.parsePostData(FormScope.java:346)
5    at coldfusion.filter.FormScope.fillForm(FormScope.java:296)
6    at coldfusion.filter.FusionContext.SymTab_initForRequest(FusionContext.java:377)
7    at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:33)
8    at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
9    at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)
10    at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:126)
11    at coldfusion.CfmServlet.service(CfmServlet.java:200)
12    at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
13    at jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
14    at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
15    at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
16    at jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
17    at jrun.servlet.FilterChain.service(FilterChain.java:101)
18    at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
19    at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
20    at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
21    at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
22    at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
23    at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
24    at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

"Dude! What is that!?!" Well, luckily I had installed my security hotfix, locally, just that morning, so I remember reading over the instructions. In it's notes it had stated the following:

  1. Customers who want to change postParameterLimit, go to {ColdFusion-Home}/lib for Server installation or {ColdFusion-Home}/WEB-INF/cfusion/lib for Multiserver or J2EE installation. Open file neo-runtime.xml, after line
    view plain print about
    1"<var name='postSizeLimit'><number>100.0</number></var>"
    add the below line and you can change 100 with desired number.
    view plain print about
    1"<var name='postParametersLimit'><number>100.0</number></var>"

Just a heads up, that neo-runtime.xml file is minified, so you'll want to Find "postSizeLimit" to get that statement in the right place. We tried that postParametersLimit value (100) and found that our form had more than that (many were hidden, but that's another post all together), so we adjusted the number to 200. After restarting the instance again, we tested the form once more with complete success.

Hopefully this will help someone else avoid this issue. It's important to remember that Adobe does try to document these types of situations with hotfixes, so when you run into issues they should be your first source of troubleshooting information.

Previous Entries / More Entries