Tuesday, April 30, 2013

Breaking change in Coldfusion 10 vs Coldfusion 9

Here is one breaking change:
  • DeserializeJSON of null value
Test Code to show the change:
result = deserializeJSON('{"test": null}');
writedump(result);
writeoutput(result.test);

In CF9, result.test is string value: "null".
In CF10, the above code will have error, because result.test is "undefined".

Debugging DotNet component on Coldfusion Server

Here is a recipe to setup Visual Studio debugging of remote Coldfusion server's .NET application.

Environment: Visual Studio 2012, Coldfusion 9
Setup:
  1. Coldfusion Server: 
    1. install "Remote Tools for Visual Studio 2012 Update 2"
    2. Start "Remote Debugger Configuration Wizard" and configure accordingly
    3. Start "Remote Debugger" As Administrator
  2. Visual Studio computer:
    1. Click Debug > Attach to Process
    2. In "Qualifier" type the Coldfusion server's computer name
    3. Check "Show processes from all users"
    4. Click "Refresh"
    5. Select "JNBDotNetSide.exe"
    6. Click "Attach"

Done!

To see it in action, set a break point in your code, load a Coldfusion page that invokes your .NET application, Visual Studio debugger should break accordingly.

Wednesday, April 03, 2013

test embedding Skydrive Spreadsheet

Above is an example to embed skydrive document to blog. Only catch? Use the "JavaScript" instead of the "Embed Code" version. It works beautifully, impressive.

Wednesday, March 20, 2013

ExtJS Store Shared Between Multiple ComboBox Controls

Environment: ExtJS 4.1.3, auto loaded store, shared by multiple comboboxes

Problem:
Combobox with auto-complete behaves strangely. Sometimes, the list is obviously filtered down by something else.

Cause:
The same data store instance is shared by multiple combobox on the page. "doQuery" function in the combobox will try to reserve the store's filter that is not created by the combobox itself (see ComboBox.js > clearFilter, and doQuery implementation). This design allows the auto-complete filter of different dropdown pickers to interfere with each other.

Solution:
1. create custom control, then override "doQuery" function to call store.clearFilter()
Pros:
- Clean, reusable design
Cons
- Validation still has cross contamination of conflicting filtering
- In cases you want to preserve an existing filter, this solution need more tweaks or configuration input to make it working

2. Declare store of the combobox using the following style: store: {type: 'myStoreAlias'}, instead of store: 'myStoreName'. This way it will ensure each combobox has their own instance of the store, thus not interfering each other's filtering.
Pros:
- No other hidden surprises lurking around
Cons:
- Pretty much have to abandon the store: 'myStoreName' completely, because in a module design, you just don't know which combobox may live in the same page with another one and using the same store
- Network and memory overhead to maintain multiple copies of the same data

Wednesday, March 13, 2013

Coldfusion Error: "Value can not be converted to requested type."

Symptom: All of a sudden the test cases that worked before, stopped working. Error message is: "Value can not be converted to requested type.". Wasted hours trying to diff and check typos with no avail. Finally, surrender, and Googled the following article published in 2006:

ColdFusion Query Error: Value Can Not Be Converted To Requested Type

http://www.bennadel.com/blog/194-ColdFusion-Query-Error-Value-Can-Not-Be-Converted-To-Requested-Type.htm

So, it is an old problem that never go away. Everything clicks now. Database schema was just updated with a few new columns. "SELECT *" combined with CFQUERYPARAM seems to have some caching issue and everything just messed up from there.

Solution? remove SELECT *, change to use explicit column names. The problem simply goes away for good.

Friday, March 01, 2013

HTML + JavaScript Charting Solutions

  • Ext JS, Example (good for intranet application)
  • d3.js (extremely popular at this moment)
  • Dojo Charting
  • YUI Chart
  • Google Chart (Big down side, at least at this time, is that Google will receive every single data point you want to plot. Not a good thing for any data that requires privacy!)
  • Flotr2
  • Flash charts? lots of good choices there, but not accessible on mobile clients, and in danger of being completely out in a few years?

Tuesday, February 19, 2013

Support JSONP in Coldfusion

Let say you already have a Coldfusion page that serves JSON data to your AJAX web application, now you want to support JSONP from cross domain client call. Here is the code snippet that will do it:

Solr in Coldfusion 9


Some tips for using Coldfusion 9 Solr search:
  • Lesson Number 1: Make sure you review ALL the files under your collections \conf folder, many of them need to be commented out or changed from default values. Here is an incomplete list of what I changed:
    • Commented out words in protwords.txt
    • Deleted content in spellings.txt
    • Updated synonyms.txt, deleted the test words, and added new synonyms based on the vocabulary specific to my application's domain
    • schema.xml:
      • Updated default query operator from AND to OR
    • solrconfig.xml
      • commented out "solr", "rocks" and other similar configurations
    • Enable term highlighting (see http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSe9cbe5cf462523a0-5bf1c839123792503fa-8000.html \), but it's still not quite there. Still looking for a complte solution for this one.
  • In Coldfusion Admin, change Solr buffer limit from default value 40 to 80 (http://bloggeraroundthecorner.blogspot.com/2009/08/tuning-coldfusion-solr-part-1.html)
  • Ensure "Coldfusion 9 Solr Service" is started and set to "Automatic" startup type
  • To access Solr collection from remote Coldfusion servers, 
    • For the remote CF servers: change Solr server name in Coldfsuion Admin, DATA & Service > Solr Server > Solr Host Name
    • For the Solr Host: Allow remote server to have access to its Solr instance. Configure Jetty to listen on all incoming IP address. Coldfusion's default configuration is allow only 127.0.0.1, thus disabling remote CF server's access to it's hosted Solr instance. To change this, just open jetty.xml in {coldfusion home}\solr\ect, and comment out the host line which restricts to listen on 127.0.0.1 only (interestingly, I found this solution from this link: http://helpx.adobe.com/coldfusion/kb/coldfusion-9-limit-access-solr.html, which claims Coldfusion's default configuration is to listen on all ip addressed
  • Web access to Solr admin: http://{Your CF Server Name}:8983/solr/
  • Last and a big one, when you try to update multiple indexes, you will see error like this:
Error_opening_new_searcher_exceeded_limit_of_maxWarmingSearchers4_try_again_later

Stack Trace:
...
org.apache.solr.common.SolrException: Error_opening_new_searcher_exceeded_limit_of_maxWarmingSearchers4_try_again_later

Error_opening_new_searcher_exceeded_limit_of_maxWarmingSearchers4_try_again_later

request: http://localhost:8983/solr/.../update?commit=true&waitFlush=false&waitSearcher=false&wt=javabin&version=1
    at org.apache.solr.client.solrj.impl.CommonsHttpSolrServer.request(CommonsHttpSolrServer.java:424)
    at org.apache.solr.client.solrj.impl.CommonsHttpSolrServer.request(CommonsHttpSolrServer.java:243)
    at org.apache.solr.client.solrj.request.AbstractUpdateRequest.process(AbstractUpdateRequest.java:105)
    at coldfusion.tagext.search.SolrUtils.commitToServer(SolrUtils.java:1024)
    at coldfusion.tagext.search.SolrUtils.addDocument(SolrUtils.java:664)
    at coldfusion.tagext.search.IndexTag.doQueryUpdate(IndexTag.java:929)
    at coldfusion.tagext.search.IndexTag.doStartTag(IndexTag.java:254)
    at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722)


This error will be consistently showing up in production environment with even very light traffic, and became a big show stopper for the usage of Solr collection provided by Coldfusion (does not seem to be a Solr problem, instead a problem of Coldfusion integration problem). 

Root cause seems to be that Coldfusion commits every index update, and causing excessive Solr searcher warming. Combining with misconfigured default Solr configuration, this problem starts to appear for a collection of only a few hundred entries.

In Coldfusion 10, this problems seems like easier to solve by using the newly introduced "autoCommit" attribute, which should always be "no" (i.e. never use the default value). Then I guess configuring the "autoCommit" in solr config file will solve the above problem in Coldfusion 10.

However, production environment that is already in CF 9 is stuck. My solution for it is a combination attack:
    • Manually throttle cfindex update by adding a sleep after every update
    • Wrap try catch block around the cfindex update, then add a longer sleep time in the catch block, and add retry logic to try update again after the sleep
    • Database flag of index entries, this flag will be set only after index is updated successfully. A scheduled CF task will scan this flag to identify missed updates (due to the above error), and try to update index again
The above approach so far allows me to update thousands of indexes without any problem.

Wednesday, October 10, 2012

Downloadify Stopped Working in Google Chrome

Downloadify uses Flash's download functionality to enable client side download. It saves server side roundtrip.  There is also nice user extensions using Downloadify to export ExtJS grid on the client side. HTML 5 does have some limited support of client side download, but it suffers inconsistent support between browsers.

Ok, after all the justification for using it, Downloadify stopped working for Google Chrome recently. And here are the observations:
  • Environment: Windows, Google Chrome is up-to-date
  • Download still works in IE and Firefox;
  • Download only works in Chrome if I'm testing using Intranet URL. But it does not work if the URL looks like Internet address (i.e. http://localhost works, but http://10.10.10.1 won't work);
  • IE, Firefox are on Flash 11.3, and Chrome is running Flash 11.4
Solution:
Not really a solution. It's more like a workaround.
  1. In Chrome address bar type: "about:plugins"
  2. Click on "Details" button to expand into more detailed view
  3. Find "Flash" section, and disable the Flash player 11.4 (something called "PepperFlash"\"pepflashplayer.dll")
  4. Make sure there is another Flash player listed here, which should be Adobe's distribution

Root Cause?
I can only guess. Still not sure why and how to fix it properly.
Turns out Google Chrome has it's own Flash distribution. (Only guessing) It seems to be different from Adobe's official one, and somehow has higher default security settings.

itemId and id in ExtJS

The story: 
Here is a lesson for not reading document thoroughly. My very first ExtJS project goes smoothly until one day I created multiple tabs, and then closed some of them. All of sudden the layout completely messed up. In the debug console, there is null reference error. Call stack is deep in the ExtJS library.

Fast forward, after several hours of digging around, I found out I was using "id" config for several ExtJS controls. Then, close tab action will cause all the controls on the other tabs with the same "id" got deleted from DOM.

Solution:
Use "itemId" instead of "id" config for controls.

Comparison to ASP.NET
Came from ASP.NET world, I guess that is why I was using "id" config without any second thought. Below is a comparison of similar concepts in ASP.NET

ExtJS ASP.NET _
itemId  ID  (Recommended) HTML element's ID is automatically generated to ensure uniqueness, usually by concatenating ID of the container hierarchy. Programmer only need to ensure ID is unique within it's container.
id  ClientID  (Not recommended) Rendered HTML element will use this property as their ID. It's programmer's responsibility to ensure it is unique across the whole page (think when you starting to have multiple instances of the same control on a page).