<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Orange is my favorite color &#187; ColdFusion</title>
	<atom:link href="http://www.ghidinelli.com/c/webinternet/coldfusion/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ghidinelli.com</link>
	<description></description>
	<lastBuildDate>Fri, 27 Jan 2017 17:45:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Java / ColdFusion SSL handshake_failure Fix</title>
		<link>http://www.ghidinelli.com/2017/01/27/java-coldfusion-ssl-handshake_failure-fix</link>
		<comments>http://www.ghidinelli.com/2017/01/27/java-coldfusion-ssl-handshake_failure-fix#comments</comments>
		<pubDate>Fri, 27 Jan 2017 17:45:50 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1725</guid>
		<description><![CDATA[Fixing a Java/ColdFusion/JVM-based SSL handshake_failure when making an HTTPS request ]]></description>
			<content:encoded><![CDATA[<p>As PCI DSS rules and general security best practices evolve, more people are configuring their web servers to eliminate less-secure versions of SSL and TLS for their HTTP connections. If you are using a Java or JVM-based application, this may manifest itself in a sudden inability to connect resulting in a fatal handshake_failure. </p>
<p>What this is telling you is that you were able to connect but your client and the remote server were unable to find a mutually acceptable encryption algorithm to communicate over so further communication was aborted.</p>
<p>An easy way to tell if this is your problem as a Java/JVM client is to use the <a href="https://www.ssllabs.com/ssltest/analyze.html">Qualys SSL analyzer</a> and see whether it reports a Java client can connect. In my case, I saw the following failures when I entered the SSL endpoint I wanted to access:</p>
<p><a href="https://www.ghidinelli.com/wp-content/uploads/2017/01/java-ssl-handshake-failure.png"><img src="https://www.ghidinelli.com/wp-content/uploads/2017/01/java-ssl-handshake-failure.png" alt="" title="java-ssl-handshake-failure" style="width: 100%; max-width: 972px;" class="aligncenter size-full wp-image-1726" /></a></p>
<p>If you happen to be a ColdFusion user, you can add <tt>-Djavax.net.debug=ssl,handshake,verbose</tt> to your jvm.config, restart and make your HTTPS request and see the full list of ciphers being attempted and the ultimate failure in your log file. My logs with the handshake_failure can be seen in <a href="https://gist.github.com/ghidinelli/2768e0b28d767a5b018fd3f01cdc3e9f">this gist</a> for comparison.</p>
<h2>Fix with Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files</h2>
<p>The fix is easy to implement but not easy to find. I experienced this with Oracle&#8217;s JVM and not the OpenJDK so other JVM implementations may behave differently. In the case of Oracle&#8217;s JVM, strong encryption is disabled out of the box for export reasons so the JVM can not use an encryption algorithm stronger than 128-bit. Many web servers are now disabling 128-bit SSL in favor of 256-bit and 384-bit encryption algorithms so the fix is to turn these on in your JVM.</p>
<ol>
<li>Download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files from Oracle (this link is for Java 1.8, Google for alternative JVM versions): <a href="http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html">http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html</a></li>
<li>Extract the two JAR files into your <tt>jre/lib/security</tt> folder overwriting the US_export_policy.jar and local_policy.jar.</li>
<li>Restart the JVM</li>
</ol>
<p>You should now be able to connect to the remote server. If you&#8217;re still unable to connect, try enabling debugging and see which ciphers are attempted/ignored. The remote server may have an exotic configuration that requires you to contact them but the unlimited strength jurisdiction policy files should fix handshake_failure issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2017/01/27/java-coldfusion-ssl-handshake_failure-fix/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Preventing Long ColdFusion Initialization Timeouts</title>
		<link>http://www.ghidinelli.com/2015/11/21/preventing-long-coldfusion-initialization-timeouts</link>
		<comments>http://www.ghidinelli.com/2015/11/21/preventing-long-coldfusion-initialization-timeouts#comments</comments>
		<pubDate>Sat, 21 Nov 2015 17:08:19 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[devops]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1696</guid>
		<description><![CDATA[Request timeouts when initializing your ColdFusion app? This function will stop them.]]></description>
			<content:encoded><![CDATA[<p>My apps use a variety of frameworks which offer a lot of rapid development and agility but they also come at the cost of slower startup times. For a Coldspring-based app with a large service layer, you could easily run into timeouts when initially loading the application. Here&#8217;s a simple function to temporarily extend the processing timeout during initialization using CFTHREAD and the Admin API:</p>
<pre><code>&lt;cffunction name="extendRequestTimeoutDuringInit" output="false" access="public" returntype="any"&gt;

  &lt;cfthread action="run" name="delayRequestTimeoutDuringInit"&gt;
    &lt;cfset thread.adminapi = createObject("component", "cfide.adminapi.administrator") /&gt;
    &lt;cfset thread.adminapi.login('mysecretpassword') /&gt;
    &lt;cfset thread.runtime = createObject("component", "cfide.adminapi.runtime") /&gt;
    &lt;cfset thread.timeout = thread.runtime.getRuntimeProperty("TimeoutRequestTimeLimit") /&gt;
    &lt;cflog file="application" text="Extending RequestTimeout to #2*thread.timeout# seconds" /&gt;
    &lt;cfset thread.runtime.setRuntimeProperty("TimeoutRequestTimeLimit", 2*thread.timeout) /&gt;
    &lt;cfset sleep(2 * thread.timeout * 1000) /&gt;
    &lt;cfset thread.runtime.setRuntimeProperty("TimeoutRequestTimeLimit", thread.timeout) /&gt;
    &lt;cflog file="application" text="Restored RequestTimeout to #thread.timeout# seconds" /&gt;
  &lt;/cfthread&gt;

&lt;/cffunction&gt;</code></pre>
<p>I call this in Server.cfc when my instance starts up but you could also call it from any reinit routine in OnRequestStart or OnApplicationStart. Previously when we pushed code, the first user request would kick off the initialization process while other requests queued. Many of those first requests would exceed our page timeout setting of 60 seconds. Running the above function uses a background thread to double the timeout and later reset it once the application has initialized so users no longer see timeout/error screens.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2015/11/21/preventing-long-coldfusion-initialization-timeouts/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jstat in Java 1.8 Can&#8217;t Find Process Run as Root</title>
		<link>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root</link>
		<comments>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root#comments</comments>
		<pubDate>Thu, 20 Aug 2015 17:55:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1649</guid>
		<description><![CDATA[Jstat not working under Java 1.7 u75 or higher including Java 8? There's a bug! Here's how to work around it to get your JVM details.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a handful of times on <a href="https://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm">observing and tuning the JVM</a> using tools such as Jstat. I recently upgraded our servers to Java 8 and found that my Jstat script could no longer find the process no matter what I tried.</p>
<p>It turns out <a href="https://bugs.openjdk.java.net/browse/JDK-8073858">there is a bug</a> from JDK 1.7 u75 onwards that is present at least through JDK 1.8 u60 which prevents Jstat, when run as root, from introspecting JREs running as other users.</p>
<p>To solve, simply run jstat as the user who owns the JRE process.  You can pass the username to sudo when running jstat like:</p>
<p><code>sudo -u nobody jstat -gcutil -t &lt;pid&gt; 1s 30</code></p>
<p>And you&#8217;ll be treated to your output again. In my case, I have two server instances running so I like to see their output side by side at the console.  Here&#8217;s my script for doing that using /usr/bin/paste and some console redirection trickery:</p>
<p><script src="https://gist.github.com/ghidinelli/a57dd23c03005f0980e8.js"></script></p>
<p>The username can be figured out from the process but this was a quick fix for the above bug.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2015/08/20/jstat-in-java-1-8-cant-find-process-run-as-root/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redirecting ColdFusion logs in a Docker Container</title>
		<link>http://www.ghidinelli.com/2015/07/06/redirecting-coldfusion-logs-docker-container</link>
		<comments>http://www.ghidinelli.com/2015/07/06/redirecting-coldfusion-logs-docker-container#comments</comments>
		<pubDate>Mon, 06 Jul 2015 18:35:34 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1637</guid>
		<description><![CDATA[Learn how to redirect ColdFusion logs to stdout and stderr on Linux or OS X.  Especially useful in containerization using Docker to centralize logs.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been modernizing our development environment and started with the work by <a href="https://github.com/finalcut/docker-coldfusion10">Bill Rawlinson</a> to create a portable ColdFusion Docker image. If you&#8217;re new to Docker and the benefits of containerization, read up <a href="http://readwrite.com/2014/12/23/docker-to-dominate-in-2015">why Docker is dominating 2015</a>. We have Docker Compose running a stack with ColdFusion, Nginx, Postgres, ActiveMQ and Redis all linked together and the entire setup can be started with one command:</p>
<p><code>docker-compose up -d</code></p>
<p>I&#8217;m simultaneously moving from a Windows machine to a Mac and I&#8217;ve been really missing the console logging for watching application activity and errors.  It&#8217;s easy when installed locally to tail the coldfusion-out.log file but once containerized you don&#8217;t have that luxury (without using docker exec to log in to the running container which is a bad practice).  The issue is on Linux, ColdFusion has no option to log to stdout like on Windows.  As a result, the docker logs command can&#8217;t see the output from ColdFusion once the container is running.  </p>
<p>It turns out there is a very simple and very elegant way to force ColdFusion, or any app which wants to daemonize and write to log files, to write to stdout.  From this <a href="http://serverfault.com/questions/599103/make-a-docker-application-write-to-stdout">ServerFault thread</a> referencing the Nginx Dockerfile, you can symlink the coldfusion-out.log file to /dev/stdout:</p>
<pre><code>ln -sf /dev/stdout /opt/coldfusion10/cfusion/logs/coldfusion-out.log</code></pre>
<p>My Dockerfile for ColdFusion has these two lines:</p>
<pre><code># redirect logs so `docker logs -f &lt;container&gt;` works
RUN ln -sf /dev/stdout /opt/coldfusion10/cfusion/logs/coldfusion-out.log
RUN ln -sf /dev/stderr /opt/coldfusion10/cfusion/logs/coldfusion-err.log</code></pre>
<p>Now the logs can be collected and observed in a centralized location using <a href="https://docs.docker.com/articles/dockerfile_best-practices/">Docker best practices</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2015/07/06/redirecting-coldfusion-logs-docker-container/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Talking SaaS at dev.Objective()</title>
		<link>http://www.ghidinelli.com/2015/05/03/talking-saas-at-dev-objective</link>
		<comments>http://www.ghidinelli.com/2015/05/03/talking-saas-at-dev-objective#comments</comments>
		<pubDate>Sun, 03 May 2015 23:41:49 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1624</guid>
		<description><![CDATA[Brian returns to dev.Objective() in Minneapolis to present on Building SaaS Applications]]></description>
			<content:encoded><![CDATA[<p><strong>Update</strong> &#8211; Slides from my talk were <a href="http://www.slideshare.net/ColdFusionConference/ghidinelli-building-saasappsfinal">posted on SlideShare</a>.  Thanks to everyone who came and all the tweets!</p>
<p>I&#8217;ll be speaking at <a href="http://www.devobjective.com/">dev.Objective()</a> this year in Minneapolis on a hybrid business/programming topic titled, &#8220;<a href="http://www.devobjective.com/sessions/building-multi-tenant-saas-applications/">Building Multi-Tenant Software-As-A-Service (Saas) Applications</a>&#8221;  This will be a comprehensive review covering the hurdles I&#8217;ve crossed growing <a href="http://www.motorsportreg.com">MotorsportReg.com</a> from a one-man nights-and-weekends operation to a team that has processed more than $100,000,000 in event entry fees.  The talk will cover:</p>
<ul>
<li>Database design and tenancy model trade-offs</li>
<li>Third party services and designing for resiliency</li>
<li>E-commerce strategies for cards on file, split payments, multiple currencies and marketplace-style apps</li>
<li>Implications of going global including i18n, l10n, currency and domiciling</li>
<li>Cross-customer security and the impact of banking and legal requirements such as PCI DSS, IRS and Know-Your-Customer (KYC)</li>
<li>Code strategies for implementing customer or domain-specific functionality without a &#8220;kitchen sink&#8221; user experience problem</li>
</ul>
<p>Developers who are interested in SaaS apps or have the entrepreneurial itch themselves will walk away with a roadmap of the issues a SaaS app must solve and strategies to achieve success.  I&#8217;ll be speaking immediately after the keynote Wednesday morning, May 13, at 10:15am. </p>
<p>This is my second time attending dev.Objective() and I&#8217;m returning because I got a ton of value from it.  I hope you&#8217;ll consider attending if you&#8217;re not already signed up as it will be a positive boost for your creativity and skills.   Registration is <a href="https://www.signup4.net/public/ap.aspx?EID=CFOB19E&#038;TID=7R1b5j8%2bsw2owJ95UBUTMw%3d%3d">still available for $999</a>.</p>
<p>Connect with me on twitter ahead of the conference to keep in touch at <a href="http://twitter.com/ghidinelli">@ghidinelli</a>.  You can connect with other speakers and attendees on <a href="http://lanyrd.com/2015/devobjective/">Lanyrd</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2015/05/03/talking-saas-at-dev-objective/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CFPAYMENT now on GitHub</title>
		<link>http://www.ghidinelli.com/2013/06/05/cfpayment-now-on-github</link>
		<comments>http://www.ghidinelli.com/2013/06/05/cfpayment-now-on-github#comments</comments>
		<pubDate>Wed, 05 Jun 2013 17:05:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[cfpayment]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1557</guid>
		<description><![CDATA[CFPAYMENT, the open source payment processing library for ColdFusion, is now hosted on GitHub for your forking pleasure]]></description>
			<content:encoded><![CDATA[<p>I see people in ColdFusion land still reinventing the wheel in writing payment gateways.  Stop!  Believe me when I tell you there are 502 ways for a payment request to fail and I&#8217;ve experienced every single one of them!  The open source payment processing library, CFPAYMENT, has processed tens of millions of dollars in production applications over the past 5 years.  Either use one of our supported gateways (including the very cool <a href="http://www.stripe.com">Stripe</a>) or write a tiny amount of code to translate requests from your gateway of choice.</p>
<p>To encourage you to leverage rather than rebuild, I&#8217;ve moved the source to GitHub where you can fork and pull:</p>
<p><a href="https://github.com/ghidinelli/cfpayment">https://github.com/ghidinelli/cfpayment</a></p>
<p>There&#8217;s also a <a href="https://groups.google.com/forum/?fromgroups#!forum/cfpayment">Google group</a> where I provide support if you want to use a gateway we don&#8217;t yet include.  I&#8217;ll help you understand how to use the library and extend it so you don&#8217;t go through the pain of learning the hard way how transactions can fail in production.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2013/06/05/cfpayment-now-on-github/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Turbo Stack Traces for Tough Debugging</title>
		<link>http://www.ghidinelli.com/2013/04/02/turbo-stack-traces-for-tough-debugging</link>
		<comments>http://www.ghidinelli.com/2013/04/02/turbo-stack-traces-for-tough-debugging#comments</comments>
		<pubDate>Tue, 02 Apr 2013 21:51:09 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1547</guid>
		<description><![CDATA[Here&#8217;s a guerilla debugging tactic based upon an old post of mine, Finding Memory Leaks in Coldfusion JVM, and some inspiration from Charlie Arehart.  I&#8217;m in the process of migrating from ColdFusion 8 to 10 and am encountering some unexpected errors.  This stack trace snippet should strike fear into the heart of any [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a guerilla debugging tactic based upon an old post of mine, <a href="https://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm">Finding Memory Leaks in Coldfusion JVM</a>, and some inspiration from <a href="http://www.carehart.org/blog/client/index.cfm/2009/6/24/easier_thread_dumps">Charlie Arehart</a>.  I&#8217;m in the process of migrating from ColdFusion 8 to 10 and am encountering some unexpected errors.  This stack trace snippet should strike fear into the heart of any developer:</p>
<pre><code>ava.lang.StackOverflowError at org.apache.xerces.dom.ParentNode.item(Unknown Source) at
net.sf.saxon.dom.NodeWrapper$ChildEnumeration.skipFollowingTextNodes(NodeWrapper.java:1166) at
net.sf.saxon.dom.NodeWrapper$ChildEnumeration.next(NodeWrapper.java:1194) at
net.sf.saxon.tree.util.Navigator$EmptyTextFilter.next(Navigator.java:918) at
net.sf.saxon.tree.util.Navigator$DescendantEnumeration.advance(Navigator.java:1052) at
net.sf.saxon.tree.util.Navigator$DescendantEnumeration.advance(Navigator.java:1111) at
net.sf.saxon.tree.util.Navigator$BaseEnumeration.next(Navigator.java:949) at
net.sf.saxon.tree.util.Navigator$DescendantEnumeration.advance(Navigator.java:1043) at
net.sf.saxon.tree.util.Navigator$BaseEnumeration.next(Navigator.java:949) at
... (endless repeat)</code></pre>
<p>Something is stuck in a loop but because the stack trace fills up, you can&#8217;t see any of the lines of code being executed just before the ka-blammo.  So, what to do?  </p>
<h2>Brute Force Debugging</h2>
<p>My solution was to swipe a perl script <a href="http://unix.stackexchange.com/questions/43185/run-unix-command-precisely-at-very-short-intervals-without-accumulating-time-lag">to run commands at very short intervals</a> and dump jstack output into a series of text files.  Low-tech, but effective.  This is the timer.pl script:</p>
<pre><code>#!/usr/bin/perl

use strict;
use warnings;
use Time::HiRes qw/time sleep/;

sub launch {
    return if fork;
    exec @_;
    die "Couldn't exec";
}

$SIG{CHLD} = 'IGNORE';

my $interval = shift;
my $start = time();
while (1) {
    launch(@ARGV);
    $start += $interval;
    sleep $start - time();
}</code></pre>
<p>And a separate shell script, dump.sh, so the redirect would create a new file every time it was run.  9892 is just the process id of the ColdFusion instance:</p>
<pre><code>#!/bin/sh
sudo -u nobody /usr/java/latest/bin/jstack 9892 &gt; t_$(date '+%Y%m%d%H%M%S_%N')</code></pre>
<p>I tried running it every second, but that wasn&#8217;t enough to catch the stack overflow in the act.  I upped it to every 500ms, 100ms and finally 50ms until it caught the offending code.  Here&#8217;s the command in action:</p>
<pre><code>perl timer.pl 0.05 ./dump.sh </code></pre>
<p>That says run the dump.sh every 50ms which will output to files formatted like t_20130402171521_009840232 using the current date and time.</p>
<h2>Results</h2>
<p>Running every 50ms, it doesn&#8217;t take long to fill up a directory so I started the script on the command line and in my web browser, triggered the offending code.  Here&#8217;s what my directory looks like:</p>
<pre><code> 52 t_20130402171519_959011475
 52 t_20130402171520_009648175
 52 t_20130402171520_060316767
 52 t_20130402171520_110450371
 52 t_20130402171520_160301392
 52 t_20130402171520_210357359
 52 t_20130402171520_260432922
 52 t_20130402171520_309171913
 52 t_20130402171520_360033048
 52 t_20130402171520_409978373
 52 t_20130402171520_459903958
 52 t_20130402171520_510488116
 52 t_20130402171520_558777256
 60 t_20130402171520_610244244
 72 t_20130402171520_659494494
136 t_20130402171520_709058569
136 t_20130402171520_760286651
136 t_20130402171520_810351161
136 t_20130402171520_860382457
136 t_20130402171520_910136459
136 t_20130402171520_960370954
136 t_20130402171521_009840232
 72 t_20130402171521_059986004
136 t_20130402171521_110340195
136 t_20130402171521_160277982
136 t_20130402171521_209090149
 84 t_20130402171521_260090368
136 t_20130402171521_310428721
136 t_20130402171521_367027484
136 t_20130402171521_410303418
136 t_20130402171521_460314216
136 t_20130402171521_509053355
136 t_20130402171521_560120477
136 t_20130402171521_610417764
128 t_20130402171521_677647036
136 t_20130402171521_712667159
136 t_20130402171521_758884870
136 t_20130402171521_810562747
136 t_20130402171521_860425517
...</code></pre>
<p>That&#8217;s kilobytes in the first column, filename in the second.  You can see the steady state while I&#8217;m going to push the button in the web browser and then very quickly the stack traces get larger as code is executing.  What I wasn&#8217;t getting until I stepped down to 50ms iterations were the intermediate 72kb and 84kb stack trace which actually showed the offending lines between the stack overflows churning.</p>
<p>While this hasn&#8217;t solved the problem yet, at least I know where to go looking (and it&#8217;s at <em>you</em>, XmlSearch()) to continue the troubleshooting process.</p>
<h2>Conclusion</h2>
<p>This is a pretty hacky solution but if you&#8217;re this far into the deep end of the &#8220;what do I do?&#8221; pool, it&#8217;s a useful technique.  A line debugger would be far better but I can&#8217;t replicate this in my test environment.  So, forget the &#8220;right&#8221; way to do it and let&#8217;s just get <em>some</em>  useful information so we can make progress.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2013/04/02/turbo-stack-traces-for-tough-debugging/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Faster unit tests with ColdSpring and MXUnit</title>
		<link>http://www.ghidinelli.com/2013/03/27/faster-unit-tests-with-coldspring-and-mxunit</link>
		<comments>http://www.ghidinelli.com/2013/03/27/faster-unit-tests-with-coldspring-and-mxunit#comments</comments>
		<pubDate>Thu, 28 Mar 2013 00:07:32 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[coldspring]]></category>
		<category><![CDATA[mxunit]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1540</guid>
		<description><![CDATA[Make unit testing faster and more isolated by instructing Coldspring to only load the relevant beans for your test.]]></description>
			<content:encoded><![CDATA[<p>Nerd post today.  Most of my <a href="http://www.mxunit.org">MXUnit</a> unit tests look something like:</p>
<pre><code>&lt;cffunction name="setUp" returntype="void" access="public"&gt;
	&lt;cfscript&gt;
		variables.beanFactory = createObject("component", "coldspring.beans.DefaultXmlBeanFactory").init();
		variables.beanFactory.loadBeansFromXmlFile("/config/globalbeans.xml", true);
		variables.service = variables.beanFactory.getBean("BatchbookService");
	&lt;/cfscript&gt;

	&lt;cfset localMode = true /&gt;
&lt;/cffunction&gt;</code></pre>
<p>You can read more about my <a href="https://www.ghidinelli.com/2012/08/25/unit-testing-trick-developing-against-apis">localMode trick for testing remote APIs</a> but I&#8217;m simply loading up my Coldspring configuration file for my app which includes dozens and dozens and dozens of beans.  I have three problems with this:</p>
<ol>
<li>The unit tests depend on the configuration used to run the site which might not always be in my environment</li>
<li>It slows down my tests by generating beans that my unit test doesn&#8217;t need</li>
<li>My production and test bean config may not be the same (credentials, etc)</li>
</ol>
<p>I might be able to get around #2 by using lazy init but the principle still holds: the unit test should be as standalone as possible.  In the case I&#8217;m working on today, I have a client I&#8217;ve written (<a href="https://github.com/ghidinelli/cfpayment">and released</a>) for a third party API from <a href="http://www.batchbook.com">Batchbook</a>.  But I need to have some Batchbook-to-My-App conversions of JSON to queries and so forth.  I don&#8217;t want to bake those into my publicly-released client so what I really want in my production app is some bean config that looks like:</p>
<pre><code>&lt;bean id="BatchbookService" class="model.external.batchbook.BatchbookService"&gt;
	&lt;constructor-arg name="BatchbookClient"&gt;
		&lt;bean class="model.external.batchbook.batchbook"&gt;
	        &lt;constructor-arg name="apikey"&gt;&lt;value&gt;password&lt;/value&gt;&lt;/constructor-arg&gt;
	        &lt;constructor-arg name="endpoint"&gt;&lt;value&gt;https://somehost.batchbook.com/api/v1&lt;/value&gt;&lt;/constructor-arg&gt;
			&lt;constructor-arg name="restconsumer"&gt;&lt;ref bean="restconsumer" /&gt;&lt;/constructor-arg&gt;
			&lt;constructor-arg name="JSONUtil"&gt;&lt;ref bean="JSONUtil" /&gt;&lt;/constructor-arg&gt;
		&lt;/bean&gt;
	&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="RestConsumer" class="model.external.restconsumer" /&gt;
&lt;bean id="JSONUtil" class="model.utils.JSONUtil" /&gt;</code></pre>
<p>But if my BatchbookClient is a nested constructor-arg, how can I get it from the beanfactory to test it?  </p>
<h2>Alternative Coldspring Configurations</h2>
<p>Turns out there&#8217;s more than one way to load beans into Coldspring and passing a path to an XML configuration file is just one.  Looking over the <a href="http://www.coldspringframework.org/downloads/ColdSpring_Reference.pdf">1.0 reference guide</a>, I found two additional methods of interest:</p>
<ul>
<li>loadBeansFromXmlRaw(xmlStringConfig, true)</li>
<li>loadBeansFromXmlObj(parsedXmlConfig, true)</li>
</ul>
<p>Applying that to my current unit test, my setup method now looks like:</p>
<pre><code>&lt;cffunction name="setup"&gt;
	&lt;cfset var beanConfigs = "" /&gt;
	&lt;cfset var localMode = true /&gt;

	&lt;cfsavecontent variable="beanConfigs"&gt;
		&lt;beans&gt;
			&lt;bean id="BatchbookService" class="model.external.batchbook.BatchbookService"&gt;
				&lt;constructor-arg name="BatchbookClient"&gt;&lt;ref bean="BatchbookClient" /&gt;&lt;/constructor-arg&gt;
			&lt;/bean&gt;
			&lt;bean id="BatchbookClient" class="model.external.batchbook.batchbook"&gt;
		        &lt;constructor-arg name="apikey"&gt;&lt;value&gt;password&lt;/value&gt;&lt;/constructor-arg&gt;
		        &lt;constructor-arg name="endpoint"&gt;&lt;value&gt;https://somehost.batchbook.com/api/v1&lt;/value&gt;&lt;/constructor-arg&gt;
				&lt;constructor-arg name="restconsumer"&gt;&lt;ref bean="restconsumer" /&gt;&lt;/constructor-arg&gt;
				&lt;constructor-arg name="JSONUtil"&gt;&lt;ref bean="JSONUtil" /&gt;&lt;/constructor-arg&gt;
			&lt;/bean&gt;
			&lt;bean id="RestConsumer" class="model.external.restconsumer" /&gt;
			&lt;bean id="JSONUtil" class="model.utils.JSONUtil" /&gt;
		&lt;/beans&gt;
	&lt;/cfsavecontent&gt;

	&lt;cfscript&gt;
		variables.beanFactory = createObject("component", "coldspring.beans.DefaultXmlBeanFactory").init();
		variables.beanFactory.loadBeansFromXmlRaw(beanConfigs, true);

		variables.bb = variables.beanFactory.getBean("BatchbookClient");
		variables.svc = variables.beanFactory.getBean("BatchbookService");
	&lt;/cfscript&gt;

&lt;/cffunction&gt;</code></pre>
<p>Coldspring now instantiates much quicker and it only loads beans related to my unit test.  Plus, I have the flexibility to directly address the BatchbookClient and run it through its paces alongside the BatchbookService. </p>
<p>If you only have a few unit tests, these improvements won&#8217;t mean much but as your test suites grow (and you work towards continuous deployment&#8230;) you will find that speeding up testing is always a good thing and helps encourage you to do it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2013/03/27/faster-unit-tests-with-coldspring-and-mxunit/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit testing trick for developing against remote APIs</title>
		<link>http://www.ghidinelli.com/2012/08/25/unit-testing-trick-developing-against-apis</link>
		<comments>http://www.ghidinelli.com/2012/08/25/unit-testing-trick-developing-against-apis#comments</comments>
		<pubDate>Sat, 25 Aug 2012 15:38:44 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1476</guid>
		<description><![CDATA[One approach to conditionally using mocks in unit tests for remote/REST API library development]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing a lot of development of API libraries over the past year while integrating remote services into <a href="http://www.motorsportreg.com">MotorsportReg.com</a>.  I struggled with how to best perform unit tests to verify the code works locally as well as integration tests to know it works with the remote API which we don&#8217;t control.</p>
<p>The problem is you don&#8217;t want to (or can&#8217;t&#8230;) always send every request over the wire to the remote API.  You might develop offline, the remote API might have limits, or real requests may take a long time which is not practical for rapid testing.  Sometimes we want to use a mock response and other times we want to connect to the third party to make sure things function properly.  How do we write unit tests and integration tests without duplicating our work?  </p>
<h2>Conditionally Using Mocks</h2>
<p>A &#8220;mock&#8221; is an arbitrarily defined data structure or object that mimics behavior.  <a href="http://mxunit.org">MxUnit</a> describes mocks providing &#8220;the ability to easily and quickly define behaviors for dependencies&#8221; which allow us to test more discretely without worrying about dependent data structures, objects or behaviors.</p>
<p>Since the concept of an integration test is different for a headless client library, my approach has been to use MxUnit&#8217;s injectMethod() to conditionally override a method for mocking:</p>
<pre><code>&lt;cffunction name="offlineInjector" access="private" hint="conditionally injects a mock if we are running tests in offline mode vs. integration mode"&gt;
  &lt;cfif localMode&gt;
    &lt;cfset makePublic(arguments[1], arguments[4]) /&gt;
    &lt;cfset injectMethod(argumentCollection = arguments) /&gt;
  &lt;/cfif&gt;
&lt;/cffunction&gt;</code></pre>
<p>localMode is defined in the setup method and is a simple boolean.  I replace all usage of injectMethod() to instead use my offlineInjector():</p>
<p><code>&lt;cfset offlineInjector(clientsvc, this, "anExampleListMock", "myMethodToReplace") /&gt;</code></p>
<p>Each time the test is run, the method will be mocked only if localMode is true.  Otherwise, the client library will use connect to the remote API to execute the request.  I do most of my development with localMode = true and set it to false when I&#8217;m ready to verify everything works both locally and remotely.</p>
<p>There are probably many ways to skin this cat and this has been working well for me without duplicating test code.  I used it most recently to wrap up integration with <a href="http://www.emailcenterpro">EmailCenterPro</a> and their <a href="http://services.emailcenterpro.com/api">REST API</a> which lets us use templated emails to send service agreements and welcome new customers as part of our sales process.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2012/08/25/unit-testing-trick-developing-against-apis/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CFPAYMENT 1.0 Released!</title>
		<link>http://www.ghidinelli.com/2012/03/21/cfpayment-released</link>
		<comments>http://www.ghidinelli.com/2012/03/21/cfpayment-released#comments</comments>
		<pubDate>Thu, 22 Mar 2012 02:41:33 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[cfpayment]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1456</guid>
		<description><![CDATA[CFPAYMENT, a ColdFusion payment processing library, goes gold with a 1.0 release!]]></description>
			<content:encoded><![CDATA[<p>Payment processing is a lot of boilerplate code that isn&#8217;t much fun to write.  More importantly, when you make a mistake, it usually means a lost sale or, worse, a double charge you have to track down and refund.  </p>
<p>CFPAYMENT makes payment processing easy.  It&#8217;s a ColdFusion library modeled after Ruby&#8217;s ActiveMerchant that normalizes various payment gateways to give developers a single interface to process credit card and ACH transactions.  After years of production use and tens of millions of dollars processed, I&#8217;m proud to announce a 1.0 release is now available at <a href="http://cfpayment.riaforge.org/">cfpayment.riaforge.org</a>.</p>
<p>There&#8217;s a lot of hard work from many different folks that have made this a success.  If you&#8217;re interested in learning more, download the file and check out <em>docs/cfpayment.pdf</em> or hit up the Google group at <a href="http://groups.google.com/group/cfpayment">http://groups.google.com/group/cfpayment</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2012/03/21/cfpayment-released/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
