Converting lines to a list in ColdFusion

I’m so used to dealing with comma-delimited lists in ColdFusion that I would sometimes take a data file that had one item per line and replace the newline characters with commas.

It’s easy to use the carriage return [chr(13)] and line feed [chr(10)] characters as list delimiters, though, and remove the intermediary step. Here’s a quick example:

<cfsavecontent variable="data">
this
is
a
list
with
one
word
per
line
</cfsavecontent>

<cfoutput>
    <ol>
        <cfloop list="#data#" delimiters="#chr(13)##chr(10)#" index="line">
            <li>#line#</li>
        </cfloop>
    </ol>
</cfoutput>

Which produces the following:

  1. this
  2. is
  3. a
  4. list
  5. with
  6. one
  7. word
  8. per
  9. line

(I can’t believe I didn’t think of this until today!)

Set operations in ColdFusion

Today I needed to get all the elements in one list that were not members of a second list. That may ring a bell — it’s known as a set difference, or a relative complement.

Although it would have been simple to loop through first the list and add only the elements not present in the second list to a new list, I thought I would look around to see if anyone had already implemented set operations in ColdFusion, e.g. on cflib.org. I was surprised that I didn’t find anything, so I decided to create my own, as much as an exercise as anything, and posted it to Bitbucket:
arraySet: ColdFusion set operations

I included the following operations:

  • union
  • intersection
  • set difference
  • subset
  • equality
  • size

In the process, I experimented with MXUnit, a unit testing suite for ColdFusion that integrates with Eclipse. (I am currently taking a Scala programming course that emphasizes Test-Driven Development, or TDD, so I thought I should try it in CF as well.)

Since I was implementing sets using arrays as the underlying data structure, I also decided to use cfinterface to define a set interface, which arraySet implements. I had never used cfinterface before, and although its usefulness has been questioned, it seemed more appropriate than extending a base set class.

Toad and Oracle Home

I recently upgraded work PC. One of the bigger hassles was setting up Toad and my Oracle connections again.

Steps (and mis-steps) I took:

  • I downloaded an Instant Client from the Oracle Instant Client Downloads
  • I selected a 32-bit client because I recall that Toad is picky about that, and a 10.2 client. I picked 10.2 primarily because I think that is what I had before, but also because I had downloaded a 64-bit 12.1 client that definitely did not work.
  • I copied it to my computer: C:\oracle\instantclient_10_2. That location is arbitrary–you should be able to save it anywhere.
  • I added an ORACLE_HOME environment variable (although this appears to have been unnecessary):
    C:\> SET ORACLE_HOME=C:\oracle\instantclient_10_2
  • I copied my old tnsnames.ora file to the same folder.
  • Start Toad

Error!
“No valid Oracle Client found. Please note that Toad only supports 32 bit Oracle Client installations. Please view the release notes for additional system requirements.”

When I try to select a client from the installed clients menu, another error:
“You do not have any Oracle homes installed!”

I had to add the client to the PATH environment variable. There are a couple ways you can do this:

  • C:\> PATH=%PATH%;C:\oracle\instantclient_10_2
  • Go to Control PanelSystemAdvanced System SettingsEnvironment VariablesSystem VariablesEdit

Toad then started without the error, but also did not recognize my tnsnames.ora file.

First I tried adding the TNS_ADMIN environment variable via the command-line:
C:\> SET TNS_ADMIN=C:\oracle\instantclient_10_2

For whatever reason, that did not solve the problem. I could echo the value back with echo %TNS_ADMIN%, but it did not appear under Environment Variables in the Control Panel.

I added TNS_ADMIN as a user environment variable in the Control Panel, restarted Toad, and then it recognized my tnsnames.ora file.

Scala function returns Unit but should return Int

I just started learning Scala last week. I created a stub method in one of my programs but was getting an error. Here’s my function:

def howMuch(max: Int) {
  var n = 0
  n
}

I tried to use the result in expression, e.g.

var m = 1
var n = howMuch(100)
m += n

Here’s the error I received:

error: overloaded method value - with alternatives:
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int
 cannot be applied to (Unit)
             m += n

It seemed clear to me that my function should be returning an Int, namely zero. Why was it returning the Unit value?

Answer: a missing equals sign in the function assignment. Here’s the function that returns an Int:

def howMuch(max: Int) = {
  var n = 0
  n
}

Using a lightweight web server to debug requests

I’ve been working a lot with the Canvas API lately. One task was to add communication channels (e-mail addresses) to user accounts. I was able to add them successfully following the documentation’s cURL example using the skip_confirmation flag:

curl 'https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels'
-H "Authorization: Bearer [...]"
-d 'communication_channel[address]=chris@osric.com'
-d 'communication_channel[type]=email'
-d 'skip_confirmation=1'

However, when I ran the ColdFusion script I wrote, the user received notification of the addition even though the skip_confirmation flag was set:

<cfhttp url="https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels" method="post">
<cfhttpparam type="header" name="Authorization" value="Bearer [...]" />
<cfhttpparam type="formfield" name="communication_channel[address]" value="chris@osric.com" />
<cfhttpparam type="formfield" name="communication_channel[type]" value="email" />
<cfhttpparam type="formfield" name="skip_confirmation" value="1" />
</cfhttp>

Why didn’t the latter work as expected?

I needed to be able to tell what was different about the 2 requests, but it would be difficult to capture that outbound requests. Tools like Fiddler and WireShark could help, but I was sending one request from my local machine and another from a remote web server.

My idea for capturing the request data was to send the request to a server under my control. I grabbed a Python echo server and modified it slightly to print the data received. Then, instead of sending the requests to the Canvas API I sent them to the echo server. Here are the results of the 2 requests:

cURL
POST / HTTP/1.1
User-Agent: curl/7.24.0 (i686-pc-cygwin) libcurl/7.24.0 OpenSSL/0.9.8t zlib/1.2.5 libidn/1.22 libssh2/1.3.0
Host: osric.com:50000
Accept: */*
Authorization: Bearer [...]
Content-Length: 100
Content-Type: application/x-www-form-urlencoded

communication_channel[address]=chris@osric.com&communications_channel[type]=email&skip_confirmation=1

ColdFusion
POST / HTTP/1.1
User-Agent: ColdFusion
Content-Type: application/x-www-form-urlencoded
Connection: close
Authorization: Bearer [...]
Content-Length: 118
Host: osric.com:50000

communication%5Fchannel%5Baddress%5D=chris%40osric%2Ecom&communications%5Fchannel%5Btype%5D=email&skip%5Fconfirmation=1

I noted the different content lengths for the same data, and upon closer inspection, ColdFusion was URL-encoding characters. I added the encoded attribute to the cfhttpparam tags with a value of “no”, and then the request bodies were identical:

<cfhttp url="https://mycanvas.instructure.com/api/v1/users/[user id]/communication_channels" method="post">
<cfhttpparam type="header" name="Authorization" value="Bearer [...]" />
<cfhttpparam type="formfield" encoded="no" name="communication_channel[address]" value="chris@osric.com" />
<cfhttpparam type="formfield" encoded="no" name="communication_channel[type]" value="email" />
<cfhttpparam type="formfield" encoded="no" name="skip_confirmation" value="1" />
</cfhttp>

Not surprisingly that solved the problem.

ANT deployment script and SFTP

My development team is moving away from developing on mapped drives/file shares to using cloud-hosted servers on Amazon Web Services (AWS). This is introducing a change to our usual workflow, as our access to the remote servers is limited to SSH and SFTP.

Although I previously used Apache Ant scripts through Eclipse to facilitate deploying application updates, the scripts were generally unpopular with the rest of the development team. (Many of them do not use Eclipse and preferred just to drop-and-drag files from their development sandboxes to the development or production servers.) Additionally, my original Ant scripts relied on the sync command to synchronize folders on the file shares.

Here is a revised Ant script that uses SCP (Secure Copy)–not SFTP but achieves the same goal–to deploy application files from a developer sandbox to the development or production server:

<project name="Deploy myapp" default="Sandbox to Dev">
  <input message="Username:" addproperty="username" />
  <input message="Password:" addproperty="passwd" />
  <property name="applicationFolder" value="myapp"/>
  <property name="site" value="osric.com"/>
  <property name="sandboxRoot" value="${basedir}"/>
  <property 
    name="development" 
    value="${username}:${passwd}@dev.osric.com:/home/web/${site}/${applicationFolder}"/>
  <property 
    name="production" 
    value="${username}:${passwd}@osric.com:/home/web/${site}/${applicationFolder}"/>
  <target name="Sandbox to Dev">
    <scp todir="${development}" trust="true">
      <fileset dir="${sandboxRoot}">
        <exclude name="**/build.xml"/>
        <exclude name="**/.*"/>
      </fileset>
    </scp>
  </target>
  <target name="Sandbox to Production">
    <scp todir="${production}" trust="true">
      <fileset dir="${sandboxRoot}">
        <exclude name="**/build.xml"/>
        <exclude name="**/.*"/>
      </fileset>
    </scp>
  </target>
</project>

There are a couple issues with this script to be aware of:

  • SCP is not included with Ant. The script produced the error “Problem: failed to create task or type scp”. I needed to:
    1. Download JSCH
    2. Place the file in Eclipse’s plugins/[ant folder]/lib folder
    3. Add the JAR file to the Ant build path (via Window–Preferences–Ant Home Entries (default)–Add External JARs…–select the jsch .jar file)
  • The password input is in plain text. Hiding password input in Ant provides a solution for Ant, but one that does not work from Eclipse. I have seen other possible solutions, so I’ll update this once I implement once and confirm that it works.

Set difference of two lists using BASH shell

Recently a handful of e-mail messages went undelivered due to some mis-communication between 2 servers.

One server had a record of all the addresses it thought it sent to over the period of time in question, and the other server a record of all the addresses to which it had actually delivered (including messages from several other servers).

I had both lists, but what I really wanted was just the set difference: only the elements of the first list that did not appear in the second. (In other words, a list of the recipients whose messages were never delivered).

I had two files:

  • possibly-delivered.txt
  • definitely-delivered.txt

First, the possibly-delivered.txt file had a bunch of extraneous lines, all of which contained the same term: “undelivered”. Since that term did not exist in any of the lines I was looking for, I removed all the lines using sed (stream editor):

sed '/undelivered/d' possibly-delivered.txt > possibly-delivered-edited.txt

I already knew (from prior investigations) that there should be 204 addresses in that list, so I performed a check to make sure there were 204 lines in the file using wc (word count):

wc -l possibly-delivered-edited.txt

204 lines returned. Great! Now, how to compare the 2 files to get only the results I wanted?

With a little help from Set Operations in the Unix Shell I found what I needed–comm (compare):

comm -23 possibly-delivered-edited.txt definitely-delivered.txt

However, comm warned me that the 2 files were not in sorted order, so first I had to sort them:

sort possibly-delivered-edited.txt > possibly-delivered-edited-sorted.txt
sort definitely-delivered.txt > definitely-delivered-sorted.txt

Again:
comm -23 possibly-delivered-edited-sorted.txt definitely-delivered-sorted.txt

This returned zero results. That was not possible (or at least, highly improbable!), so I checked the files. It looks like the sed command had converted my Windows linebreaks to Unix linebreaks, so I ran a command to put them back:
unix2dos possibly-delivered-edited-sorted.txt

Again:
comm -23 possibly-delivered-edited-sorted.txt definitely-delivered-sorted.txt

That returned my list of addresses from the first list that did not appear in the second list. (Quickly, accurately, and without tedium.)

Find Feature UI annoyance in Adobe Acrobat Pro

The Find feature in Adobe Acrobat Pro X has bothered me for some time now:

Adobe Acrobat's Find feature: note the size of the click-targets
Adobe Acrobat’s Find feature: note the size of the click-targets

The click-targets to find the previous or next occurrence of your search term are tiny. Minuscule. Verging on microscopic. Let’s say I’m searching a 600 page PDF on SharePoint and I’m looking for occurrences of the term workflow. As I click next repeatedly, trying to find the relevant section, I find that it’s very easy for my cursor to edge over just a little bit and close the Find dialog.

(Yes, I know: I can just keep pressing Enter and avoid this issue.)

Vizio Co-Star’s Google TV versus Apple TV

What kind of crazy person buys both a Vizio Co-Star (Google TV) and an Apple TV?

Apparently, I’m that kind of person.

Vizio Co-Star and Apple TV

I’ve had the Vizio Co-Star for 3 months, and the Apple TV just for a couple days. Maybe that’s a source of bias, but the summary version is, despite its shortcomings, I think Vizio Co-Star provides a superior experience.

Now for the long version: Continue reading Vizio Co-Star’s Google TV versus Apple TV

Balancing Tags in HTML and XHTML Excerpts

It is fairly common to want to take an HTML source of variable length and display an excerpt. Although some formats, such as Atom and RSS, anticipate this and create a separate summary element, we don’t always have the luxury of using such a data source.

Creating an excerpt introduces a problem, though: if we create an excerpt based on a number of words or characters, we may end up with unbalanced HTML or even broken tags.

One solution is to discard all tags and display plain text, but this is often unsatisfactory.

Here is my method of balancing tags. It assumes that the input is an excerpt of a valid XHTML snippet. The reason for this requirement has to do with self-closing tags, which I hope will be apparent from the description:
Continue reading Balancing Tags in HTML and XHTML Excerpts