justCF

I recently needed to create some ColdFusion code to call into Zillow so I thought it would be worth sharing.

The first thing you will need is an ID from Zillow to give you access to the http services. They use the term web services but they are really http services. You can find out everything you need to know about getting started and the Zillow APIs here: Getting Started with Zillow

Once you have your ID you can enter it into the below code and test it on your site.

I posted a demo here: DEMO

view plain print about
1<h1>Zillow Zestimate</h1>
2<cfparam name="form.address" default="671 Lincoln Ave" >
3<cfparam name="form.city" default="Winnetka">
4<cfparam name="form.state" default="IL">
5<cfparam name="form.Zip" default="60093">
6<cfoutput>
7<form name="zform" method="post" >
8    Address: <input type="text" name="address" value="#form.address#" size="35"/>
9 City: <input type="text" name="city" value="#form.city#" size="20"/>
10 State: <input type="text" name="state" value="#form.state#" size="3"/>
11 Zip: <input type="text" name="Zip" value="#form.Zip#" size="14"/>
12 <input type="submit" name="getzestimate" value="Get Zestimate" />
13</form>
14
15<cfif isdefined("form.getzestimate") >
16    <cfset hz = 'na'>
17    <cfset lz = 'na'>
18    <cfset csz = form.city & '+' & form.state & '+' & form.zip>
19 <cfset zurl = 'http://www.zillow.com/webservice/GetSearchResults.htm?zws-id=ENTER YOUR WSID HERE&address=#urlEncodedFormat(form.address)#&citystatezip=#urlEncodedFormat(csz)#'>
20 <cfhttp method="get" url="#zurl#" result="zsearch">
21 <cfset xmlResult = trim(zsearch.FileContent)>
22 <cfset request.zillow = XmlParse(REReplace( xmlResult, "^[^<]*", "", "all" ) ) />
23 <cfif findnocase('error',request.zillow.searchresults.message.text ) lt 1>
24 <cfset h = trim(request.zillow.searchresults.response.results.result.zestimate.valuationrange.high.xmltext)>
25 <cfset l = trim(request.zillow.searchresults.response.results.result.zestimate.valuationrange.low.xmltext)>
26 <cfif isnumeric(h)>
27 <cfset hz = dollarformat(h)>
28 </cfif>
29 <cfif isnumeric(l)>
30 <cfset lz = dollarformat(l)>
31 </cfif>
32 <h3>Zestimate Range: From #lz# to #hz#</h3> <a href='#request.zillow.searchresults.response.results.result.links.homedetails.xmltext#'
33 target="_new">
<h3>View Property at Zillow.com</h3></a>
34     <hr />
35        All the other Property Details<br />
36        <cfdump var='#request.zillow#'>
37 <cfelse>
38     Zillow could not recognize address
39 </cfif>
40</cfif>
41</cfoutput>

Often times we get cases where we need the complete stack trace of an error and not what is reported by any custom error handler template.

Here is a great way to track your errors that also allows inspection of the entire cfcatch structure at a later time, without interfering with any custom templates.

view plain print about
1<cftry>
2    <cfinclude template="asdfasdf.cfm">
3<cfcatch type="any">
4<cfdocument filename="errorreport#gettickcount()#.pdf" format="pdf">
5 ColdFusion Error<br />
6 <cfdump var="#cfcatch#">
7</cfdocument>
8</cfcatch>
9</cftry>

In the above code I create a missing template exception, then have the cfcatch simply use cfdocument with a unique filename, to dump out the cfcatch to a PDF file.

You can adjust the location etc as you see fit of course.

The result is a PDF for every occurence showing the complete error and hopefully allowing you to quickly get to a resoluiton.

I needed to have a user easily enter a latitude and longitude where there might not be a true address, so I created a simple script to populate form variables when a user doubleclicks a Google Map.

The below is just javascript and html which uses the Google Map API V2 to place a map on the page which by default centers the map when you doubleclick.

The function that is fired in a dblclick event will then set the 2 form variables and leave a marker behind to help the user know where they clicked.

You will need to change the center points and the form names, but all this could be dynamically set as well.

Hope you can use this in your apps.

Note: you will need to fix the 2 InvalidTag's with script.

<InvalidTag type="text/javascript"> // JavaScript Document var cm_map; var centerLon = '-81.655651'; var centerLat = '30.332184'; var zoomLevel = 12; var latforminput = ''; var lngforminput = ''; var marker; function cm_load() { // create the map and display in div name cm_map cm_map = new GMap2(document.getElementById("cm_map")); cm_map.addControl(new GLargeMapControl()); cm_map.addControl(new GMapTypeControl()); cm_map.setCenter(new GLatLng( centerLat, centerLon), zoomLevel); // initialize vars for form fields to populate latforminput = document.getElementById("latinput"); lngforminput = document.getElementById("lnginput"); // On Dblclick set form fields and leave a marker GEvent.addListener(cm_map, "dblclick", function(x,ll) { latforminput.value = ll.lat(); lngforminput.value = ll.lng(); marker = new GMarker(ll, {draggable: false}); cm_map.addOverlay(marker); //alert('lat:' + ll.lat() + ' lon:' + ll.lng() ); }); } setTimeout('cm_load()', 500); </script> <!--- Get Google Map API V2 and set Google key---> <InvalidTag src="http://maps.google.com/maps?file=api&v=2&key=ENTERYOURGOOGLEMAPKEYHERE" type="text/javascript"></script> <!--- Map Div ---> <div id="cm_map" style="width:300px; height:300px"> </div> <!--- Sample Form with values that will be populated when user Double Clicks on map---> <form name="setlatlng"> Lat: <input type="text" name="lat" id="latinput" value=""> <br /> Lng: <input type="text" name="lng" id="lnginput" value=""> </form>

In writing a map application with ColdFusion I needed to create some custom icons and discovered an easy way to take any small icon and create hundreds of them with sequential numbers overlayed on top of the icon.

There are a number of sites with free icons, but they all seem to stop at 99, I needed to go into the hundreds in some cases, which made me start to look at what cfimage can do for me.

First, I went I downloaded a default Google icon as my base (20x34px), then I created new blank icons with differing colors within Photoshop. I saved all the blank icons in a directory called /icons off my root directory. Once I have all the blanks I then edit the list in the below script.

The script will create a directory for each color, so for blue you will have /icons/blue/mapicon1.png thru mapicon99.png or however you create.

I think you could move the ImageNew out of the loop and into a variable but it works as written and is a one time conversion.

My next idea is to have user generated icons, by having the users select the background and text color.

I also want to create multiple lists to change the text color, since some backgrounds need black text.

This should be enough to get you started. Enjoy.

<cfset whitecolorlist = "black,blue,blueball,brightgreen,chestnut,chocolate,cyan,darkblue"> <cfset currentDir = getdirectoryfrompath(getbasetemplatepath())> <cfoutput> <!--- Loop colors and create icons inside relative directory ---> <cfloop list="#whitecolorlist#" index="coloritem"> <cfset iconcolor = coloritem> <cfset currentcolordirectory = currentdir & iconcolor> <!--- create a directory for the color if it does not exist---> <cfif not directoryexists(currentcolordirectory)> <cfdirectory action = "create" directory = "#currentcolordirectory#" > </cfif> <cfloop from="11" to="99" index="i"> <cfset myImage=ImageNew("blank#iconcolor#.png")> <cfset ImageSetDrawingColor(myImage,"white")> <cfset attr = StructNew()> <cfset attr.style="bold"> <cfset attr.size=9> <cfset attr.font="verdana"> <cfset attr.underline="no"> <!--- Need to play with x offset depending how many characters.---> <cfif i lt 10> <cfset x = 7> </cfif> <cfif i gt 9 and i lt 100> <cfset x = 4> </cfif> <cfif i gt 99 and i lt 1000> <cfset x = 1> </cfif> <cfset ImageDrawText(myImage,i,#x#,12,attr)> <!--- Place image in a directory based on color ---> <cfimage source="#myImage#" action="write" destination="#currentcolordirectory#/mapicon#i#.png" overwrite="yes"> <img src="/icons/#iconcolor#/mapicon#i#.png"/> </cfloop> </cfloop> </cfoutput>

Just wanted to pass along some notes from doing a ColdFusion 8 upgrade to ColdFuison 9 64 bit JBoss install on RedHat this week.

First off, all went fairly well, but I think you might find the tips below helpful.

First get all the software:
- CF 9 Linux 64 bit
- CF 901 Updater 64 bit
- CF 9 Cumulative Hot Fix (optional)

The ColdFusion Installation docs are what we generally followed:
Deploying ColdFusion 9 on JBoss Application Server
You can get the Updater and the Hot Fixes following the below links:
ColdFusion Updaters
ColdFusion 901 Cumulative HotFix 1

Install CF9 using the J2EE install option.

Once installed you are left with the decision to test the install, which would put you down the road of expanding the ear and war per the instructions. However, the 901 updater executable requires you to apply it to an archived war file. So, you might want to apply the updater before expanding the ear and war and moving the resulting ear directory into JBoss's deploy directory.

We did not know the CF 9.01 updater required an archive, and we had already deleted the war file, so we had to recreate the war, apply the updater, re-exand and swap out the new war with the old war directory. So, just keep that in mind if your doing a complete install as we were doing.

Here are the complete docs for installing the CF 9.01 Updater:
Installing ColdFusion 9.01

Updating your Settings from ColdFusion 8 to ColdFusion 9
So to move the settings we followed the instructions inside the link below:
Migrating ColdFusion Settings for J2EE installations

So by following the above we did the following:
- copied all the neo-* files from ../web-inf/cfusion/lib out of the 8 install, and placed then in the ../web-inf/cfusion/lib/cf8settings directory inside 9
- adjusted the runmigrationwizard and the migratecf8 settings in ColdFusion 9 cfusion/lib/adminconfig.xml, change them to true
- restarted ColdFusion and entered the Admin to trigger the Migration

All the ColdFusion 8 settings were brought over. The migration wizard allows you to filter out settings if you don't necessarily want them all.

That was it, all went well, and all the settings were brought over and all datasources connected.

If you want your code to work across multiple domains when using Google Maps you will need to dynamically change your Google Maps key based on request. Google requires you have a unique key for each host that makes calls into Google.

I solved this by placing a few statements in my application.cfc onrequest function.

The code checks the cgi.http_host and then sets the correct key value.

I created the all the keys at http://code.google.com/apis/maps/signup.html

view plain print about
1<cfif findnocase("123.com", cgi.HTTP_HOST) GT 0>
2 <cfset ajaxparams['googlemapkey'] = 'actual key from google'>
3</cfif>
4<cfif findnocase("345.com", cgi.HTTP_HOST) GT 0>
5 <cfset ajaxparams['googlemapkey'] = 'actual key from google'>
6</cfif>
7<cfif findnocase("567.com", cgi.HTTP_HOST) GT 0>
8 <cfset ajaxparams['googlemapkey'] = 'actual key from google'>
9</cfif>
10<cfajaximport params="#ajaxparams#">

If you just have one host you can alternatively set the key inside the administrator.

As MAX unfolded this year you could feel a major shift across all products to developing apps for all screen sizes. This was not the year of the big release but a year to recognize the shift that is occurring to have all new applications consider all devices from browsers, phones, tablets, and TV consoles. I don't think it was just a coincidence we received free devices, in fact it underlines the transition we are all going through as we write applications for all devices.

It kind of feels like 1997 when everyone became aware the internet was going to overtake the majority of application development. You get that same feeling when you look out over the next 2-3 years when you look at convergence of apps across devices and the move into the family room. (In a strange connection, it's hard to believe the same guy who hit the game winner in game 7 in 1997 is the same guy who hit it in 2010.)

To best capture this evolution all you need to do is watch the opening video of MAX as Kevin Lynch walks thru some timeline charts that demonstrate the changes upon us with bandwidth, browser vs devices, screen size changes ,digital publishing and the now the family room.

MAX Opens with Multi-Screen Revolution

Throughout the conference we witnesed how products are adding features to support managing screen sizes. ColdFusion did a sneak peek around supporting multi-screens with setting up a scope which will carry the clients device meta data using the CS5 Device Central database. Dreamweaver is adding more support around using CSS versions to support differing layouts based on device.

One big announcement was the Flash Builder 'Burrito' Labs release which is now available to everyone inside http://labs.adobe.com . I'd encourage you to download and check out how easy it is to start writing Mobile applications.

Here is a great alert to keep on all the time or when you are trying to capture long running requests. The snapshot will then capture the running thread and make it easy to identify where the thread is with processing the request. Usually you can find the exact line number within the ColdFusion tag.

The below code will turn on monitoring and then set UnresponsiveServerAlert to create a snapshot anytime 1 or more requests goes over 5 seconds.

You can change any these settings including seting up notifications. You can set this up via the ColdFusion Administrator, but you might find it easier to setup alerts via script if you have a number of servers.

view plain print about
1<cfapplication name="compinvoker" sessionmanagement="Yes">
2<cfobject component="cfide.adminapi.administrator" name="admin">
3<cfobject component="cfide.adminapi.servermonitoring" name="sm">
4<!--- Login to CFAdmin using your admin password--->
5<cfset admin.login('admin')>
6
7<!---Turn on monitoring--->
8<cfset sm.startMonitoring()>
9
10<!--- For the record let's see the current settings--->
11<cfdump var="#sm.getAlertSettings("unresponsiveserveralert")#">
12
13<cfset alertSettings = StructNew()>
14<cfset alertSettings.alert_processing_cfc = ''>
15<cfset alertSettings.busytimethreshold = 5000>
16<cfset alertSettings.dumpsnapshot = true>
17<cfset alertSettings.enabled = true>
18<cfset alertSettings.hungthreadcount = 1>
19<cfset alertSettings.killthreadsenabled = false>
20<cfset alertSettings.killthreadthreshold = 0>
21<cfset alertSettings.notifyclientonalert = false>
22<cfset alertSettings.notifyonalert = false>
23<cfset alertSettings.rejectrequestsenabled = false>
24
25<!--- Set the unresponsiveserveralert alert --->
26<cfset sm.setAlertSettings("unresponsiveserveralert", alertSettings)>
27
28<!--- Let's verify the new settings--->
29<cfdump var="#sm.getAlertSettings("unresponsiveserveralert")#">

A quick block of code to demonstrate how to generate a stack trace from within ColdFusion. Using the server monitor API it is a fairly simple process.

view plain print about
1<cfapplication name="cfmonitor" sessionmanagement="Yes">
2<cfobject component="cfide.adminapi.administrator" name="admin">
3<cfobject component="cfide.adminapi.servermonitoring" name="sm">
4
5<cfset admin.login('YOURADMINPASSWORD')>
6<cfset filename = sm.dumpSnapShot()>
7<cfoutput>
8Snapshot was placed in: #filename#
9</cfoutput>

The code calls the login function passing in your ColdFusion Admin password in order to get access to the Admin API.

The dumpSnapShot function will create the stack trace and return the file path of the snapshot. The default location is usually ../web-inf/cfusion/logs/snapshots.

You might want to prompt for a password versus hardcoding in the tag as well.

Recently my team needed to share some lead information to track data about contacts, and interactions. I thought it would be a great solution for ColdFusion and PDF Forms and wrote an application to collect and save the PDF files.


The application works as follows:

  • The user logs into the ColdFusion application
  • The user is presented with a Tabbed Layout showing Open and Closed leads
  • The user can click on the Open leads and enter additional data, interactions
  • If the user enters a close date the PDF is considered closed and is moved to the Closed folder\tab
  • A user can also click the New Lead link and will be presented with a PDF with some prepopulated fields
  • When the user is done editing they submit the entire PDF to CF and the file is saved on the server.
  • Once any PDF is submitted into CF, it then sends an email to all users that are registered for different events

The PDF we are using in the application was built with Adobe Acrobat Form Designer. We added a Submit button to this PDF that allows us to send the entire PDF to ColdFusion. Once we have the entire PDF we are able to read the form data and make decisions on where to place the file. In our case we are looking at the close date to see if we need to remove this PDF from the Open que.

The use case can apply to any PDF form as it travels between team members, work queues, collects data, gets signed, has files attached until the PDF is finally considered complete.

You don't necessarily need to send the entire PDF, you can just as easily submit the form data with Acrobat button called the HTTP Submit. You would then need to handle prepopulating the form and data within CF before sent to the requestor.

Make sure to place the PDF repository inside a non-browsable location, to make sure it is only served via your CF application.

Instructions for installing: Download Application
1. The PDF submits to /jaxfusion/index.cfm so if you deploy to another directory you will need to change sample pdf
2. Place 3 files in a directory called jaxfusion off your web application root ie:C:\JRun4\servers\cfusion\cfusion.ear\cfusion.war\jaxfusion
3. Place the leads directory into a directory off the root. ie: C:\JRun4\servers\expertshelf\cfusion.ear\cfusion.war\Web-INF\leads
4. You will see the leadmanagement.pdf and 2 subdirecectories called open and closed inside the leads directory
5. Review settings in the application.cfm, if you placed files anywhere else you will need to make adjustments.
6. I added 2 users to a test query, you can use for testing.
7. You will need to adjust the mail settings to get notifications to work as well.

Next Steps
This design of this application was inspired after doing some work with Alfresco's Document Management. My next step is to take this application and integrate it with Alfresco's repository and user authentication features. Look for Part 2 of this application in a few weeks using Alfresco to store, version and secure the PDFs.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.5.004.