Viewing Category: ColdFusion  [clear category selection]

Adobe ColdFusion 10 ORM Secondary Caching Bugfix

If you use the ORM features (in particular, secondary caching) of Adobe ColdFusion 10 and encountered the bug that prevents application startup with an Ehcache exception including the message "Another CacheManager with same name '_ORM_...' already exists in the same VM", and you used the workaround of downgrading to Ehcache 2.4.7 from the bundled Ehcache 2.5.1 version, then you will experience troubles after applying Adobe ColdFusion 10 HotFix 11 (and subsequent, cumulative patches). The first time ormReload() is called, an exception like the following will be thrown:

java.lang.NoSuchMethodError: net.sf.ehcache.CacheManager.getCacheManager(Ljava/lang/String;)Lnet/sf/ehcache/CacheManager; at coldfusion.orm.hibernate.HibernateConfiguration.close(HibernateConfiguration.java:1423) at coldfusion.orm.hibernate.HibernateProvider.closeORMForApplication(HibernateProvider.java:171) at coldfusion.orm.hibernate.HibernateProvider._reloadORMForApp(HibernateProvider.java:228) at coldfusion.orm.hibernate.HibernateProvider.reloadORMForApplication(HibernateProvider.java:209) at coldfusion.orm.ORMUtils.reloadORM(ORMUtils.java:388) ...

Presumably, the old Adobe ColdFusion code didn't call the Ehcache manager in this way, which is now incompatible with Ehcache 2.4.7. The solution is to simply undo the downgrade and run with the version provided by Adobe ColdFusion.

The original bug exists in the Adobe BugBase as #3327626 and #3583147. The ORM secondary cache issue was addressed with changes in the significant ColdFusion 10 Update 11. In a weird sort of meta coincidence, there is a bug in the display of the list of bugs fixed that causes the page to render incompletely. It was just too delicious not to capture.

This Ehcache version incompatibility is probably old news to anybody who has kept current with patches. Adobe ColdFusion Update 11 came out 9 Jul 2013. However, I'm just now seeing the issue because I brought an internal server from update 10 to 13 this weekend. I should also mention that this problem in our environment manifested as a White Screen of Death (no exception display or debugging info). I tracked down the cause by adding the following to Application.cfc:

<cffunction name="onError" returntype="void" access="public" output="false">   <cfargument name="exception" type="any" required="true"/>   <cfargument name="eventName" type="string" required="true"/>     <cfdump var="#arguments.exception#" abort="true"/> </cffunction>

Starting the CFML app with that application error handler in place allowed me to see what was going horribly wrong. Hopefully that's helpful to someone.

Concurrent Login with ColdFusion 10

In a previous post, I wrote about how ColdFusion 10 differs in behavior to ColdFusion 9 with regard to concurrent logins using the built-in security framework. The way that ColdFusion allows the application to create an authenticated user with associated user roles is pretty handy. The application does whatever is necessary to authenticate the user; it might compare a username and password, or compute a hash with a nonce and pre-shared secret, or perhaps employ a mix of multi-factor mechanisms. The point is that the application takes care of the authentication and ColdFusion manages the instance of an authenticated user and allows the application to assign a list of user roles, such as superuser, licensedForXandYnotZ, or viewOnly. The actual user roles are arbitrary strings that can be compared elsewhere in the application using the isUserInRole() function. The application can simply run isUserLoggedIn() to determine whether the authentication has already taken place, and an instance of the authenticated user exists in ColdFusion. Very handy, indeed.

The security related tags in ColdFusion 10 are summarized on the Using ColdFusion security tags and functions page. The arguments passed to the cfloginuser tag are name, password, and roles. The actual values of these attributes are left to the application to determine, however it's typical for the application to use the real username. When the real username is used, calling getAuthUser() returns a meaningful value -- something that could be compared against a username in a database, for example. The change to ColdFusion 10 requires that only one instance of an authenticated user exists within an application with a given name attribute, thus preventing concurrent logins.

I feel that it's necessary to discuss this security policy in allowing or preventing concurrent logins. Security policies should start by defining the threat that is being addressed. In the case of concurrent logins, the threat is that an authenticated user instance could remain active for some amount of time, even after the same user is authenticated using a different session. An attacker could hijack the first session and impersonate the user without knowing the user's credentials. Of course, this policy does nothing to prevent malicious activity if the attacker does know the user's credentials. The only side effect of preventing concurrent login when an attacker authenticates to the application with compromised user credentials is that the valid user's authenticated instance may be destroyed if the valid user happens to be logged in at the time.

Let me reframe the issue a bit. If the concern is that an attacker could hijack a session with a stale authenticated user instance, then the same concern should be applied to an attacker hijacking a session with an active authenticated user instance created by a valid user. If a session can be compromised, the attacker need only focus on the active session. It could be argued that the attack surface or window of opportunity is decreased if only one session contains an active authenticated user instance. I would counter that if a session hijack is possible, it doesn't matter whether concurrent login is prevented.

What's the argument for allowing concurrent login? Why not choose the security policy that reduces exposure? Well, it means that user's much use only one client device at a time -- one browser/app on one phone/tablet/computer. It means that agents running autonomously must each be issued a unique name or care must be taken to ensure that only one agent (think scheduled task or API consumer) access the application at a time. My biggest complaint about preventing concurrent login is that load testing with a single user account cannot run in parallel.

So, where does that leave us? It's possible to enable concurrent login in ColdFusion 10 if the value of the name attribute to the cfloginuser tag is unique. The sessionId could be appended to the username, but then calls to getAuthUser() must be updated to expect that the value returned is not literally a username. A user defined function could be created to translate values returned by getAuthUser(), but that seems kind of hacky. The concurrent login issue could present a significant barrier to upgrading servers with applications running with versions prior to ColdFusion 10. My hope is that ColdFusion 10 is patched to support an application property to allow concurrent login when needed.

ColdFusion 10 User Roles

I've been working on documenting an issue in ColdFusion 10 that prevents the same user account from being authenticated using the built-in user role mechanism in two different sessions. I added it to the Adobe Bugbase on Friday night. The legacy app that uses this mechanism for storing user roles needs that feature working correctly; there are more than a thousand calls to isUserInRole() in the code. Forbidding concurrent user sessions is severely limiting to function and load tests that use a single user account for many test cases running in parallel.

Just to see what's in there, I base64 decoded the content of the CFAUTHENTICATION_APPTOKEN cookie content. The format is of four fields separated by line breaks: 1) username, 2) application token, 3) milliseconds since epoch, and 4) eight bytes of hex values. I'm not sure what the last field represents and why it's so short. Like this:

username MyAppName 1349119692752 36E72868346C43C1

While looking through the new docs to see if the behavior is documented, I saw the section on storing ColdFusion's built-in login information in the session, instead of a cookie. It just takes setting loginStorage="session" in the application configuration. I had never considered this, as I've always managed user roles by hand, as it were. I can't think of a reason one wouldn't want to use the session for that data.

Updating ColdFusion 10

After trying over several days for as long as my patience would last, I finally found a way to install the ColdFusion 10 HotFix 2 patch. Hopefully the following information will be helpful to someone.

The target server is Windows 2003 with Tomcat installed to C:\tomcat\myAwesomeApp with ColdFusion deployed as an expanded WAR to C:\tomcat\myAwesomeApp\webapps\cfusion. While Tomcat was running as a Windows service, I used the ColdFusion Administrator to view the available updates and download. Because this is a JEE configuration, the update cannot be applied automatically -- it must be installed by running the InstallAnywhere JAR file. The downloaded file was saved to C:\tomcat\myAwesomeApp\webapps\cfusion\WEB-INF\cfusion\hf-updates.

The Adobe ColdFusion 10 documentation has instructions for various configurations. I attempted to run in GUI mode by executing the following:

cd C:\tomcat\myAwesomeApp\webapps\cfusion\WEB-INF\cfusion\hf-updates java -jar hotfix_002.jar

The InstallAnywhere dialog window appears. After accepting the license agreement, it prompts for the path to the instance. Neither typing it in directly or browsing to it passes the applications validation. The log file it generates doesn't mention the reason for the failure.

I attempted to install using the silent mode by creating a properties file named install.properties like the sample below:

INSTALLER_UI=SILENT #For the following, specify the folder that contains META-INF folder which contains application.xml USER_INSTALL_DIR=<ColdFusion_Deployment_Root_Path>

The documentation specifies that the JAR should be executed with the following arguments:

java -jar hotfix_002.jar -i silent -f install.properties

It is curious that the silent install property/argument must be specified in two places, but let's no dwell on that right now. I ran the command and watched as one CPU was pegged for a couple minutes with no console output. I gave up waiting and killed it. When looking for the log file written to the same directory as bb5126fa139e0497659.details, I was surprised to discover that it was 877 Mb in length; 21,384,978 lines of the same error messages. First, it read my Windows Registry for an install location (okay, not necessary) then created a file C:\Program Files\cfhotfix.txt (again, not necessary). The following are the log messages repeated millions of times:

Custom Action: com.adobe.ia.customrule.DocRootValidate Status: SUCCESSFUL Install Action: Jump To: Next Validate_CF_Directory -- Prev: NO JUMP Status: ERROR Additional Notes: ERROR - java.lang.StackOverflowError

It turns out, the problem was with backslash escaping in the properties file. It should have been created like the following:

INSTALLER_UI=SILENT USER_INSTALL_DIR=C:\\tomcat\\myAwesomeApp\\webapps\\cfusion

It ran after making that change. In ColdFusion Administrator, the update information appears. It seems to have worked, but this whole mess could be avoided if they just distributed a patch ZIP that is downloaded and installed automatically on the next start of the JEE server. See: Railo

JRun failed to start because its side-by-side configuration is incorrect

After a Windows Update to a Windows Server 2008 64-bit R2 machine a couple months ago, a few services stopped working properly. Specifically, the JRun service launcher (%JRUN_HOME%\bin\jrunsvc.exe) and the version of Apache Solr packaged with ColdFusion 9. The specific error follows:

D:\JRun4\bin>jrun -config myjvm.config -start myinstance The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

I did some experimenting to day and found that uninstalling/reinstalling the Microsoft Visual C++ 2008 Redistributable (download) solved the problem. I'm not sure if this issue exists with the 32-bit versions of Windows, but I suspect not.

ColdFusion File Uploads and Content-Type

I only today stopped to think about the content type members of the structure returned from a CFFILE[@action="upload"] tag. ColdFusion splits the value into two elements, contentType and contentSubType. Consider the following:

<cffile action="upload" destination="#getTempDirectory()#" filefield="file" nameconflict="makeunique" result="res"/> <cfoutput>Upload Content-Type: #res.contentType#/#res.contentSubType#</cfoutput>

If you use an ordinary web browser to upload a file to a page with the code above, the content type of the file will be displayed. For example, image/jpeg or text/plain. You might not realize that ColdFusion looks only to the reported content type from the file portion of the multipart data. Consider this raw HTTP request where I uploaded my TPS Report to the server:

POST /upload.cfm HTTP/1.1 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.19) Gecko/20110707 Firefox/3.6.19 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Content-Type: multipart/form-data; boundary=---------------------------fluffyfluffybooboo Content-Length: 4972631 -----------------------------fluffyfluffybooboo Content-Disposition: form-data; name="file"; filename="TPS-Report.pdf" Content-Type: application/pdf %PDF-1.4 {a mess of binary data} %%EOF -----------------------------fluffyfluffybooboo

The ColdFusion output would be "Upload Content-Type: application/pdf" as expected. However, if I tamper with that HTTP POST and replay it in using Charles Proxy, changing the content type from "application/pdf" to "kuasehf/gaiurgh" (hat tip), ColdFusion will pass through the value unscrutinized. The result is output of "Upload Content-Type: kuasehf/gaiurgh". So, it doesn't matter what the name of the file is. I kind of hoped that it would use the Java equivalent of MIME-Magic. Oh, interestingly enough, there's a library to provide MIME inspection to Java, called Java Mime Magic. Neat.

Mocking ColdFusion ORM Entities

Consider that I have a service, say ProjectService, that is my component under test (CUT). It has a method called getProjectsByUser(), which expects an instance of model.user.User to be provided as the argument. The User is a ColdFusion ORM entity and as such, has accessor/mutator methods generated by the ColdFusion engine for each of the defined properties.

So far, so good. The User component works properly and I'm writing a MX Unit test for the service. Within a test case, I instantiate the ProjectService and prepare a mock User object to pass to its getProjectsByUser() method. The mock object is prepared like so:

// Using MightyMock var user = mock("model.user.User", "typeSafe"); user.getUserID().returns(1001); // or user.onMissingMethod("getUserID", {}).returns(1001);   // Using MockBox var mockbox = createObject("component", "coldbox.system.testing.MockBox").init(); var user = mockbox.createMock("model.user.User"); user.$(method="getUserID", returns=1001); // or user.$property(propertyName="userID", mock=1001);

When using MightyMock, the ColdFusion generated accessor for getUserID() is not overridden and the return is undefined/uninitialized. Using MockBox in the first manner does create a mock that returns the proper value. It might be more correct to use the second method, allowing ColdFusion ORM to manage the lifecycle of the internal property with its own accessors/mutators. I guess it depends on the desired behavior of the mock object.

Incidentally, I'm using the in-memory filesystem generation path that I previously recommended to store the generated mock components, and I still think it's a great idea.

MockBox Generation Path

When using the MockBox ColdFusion Mocking Framework to generate mock objects dynamically, it requires that the ColdFusion server have write access to a filesystem location to save the CFC files. By default, this path is /[mockbox|coldbox]/system/testing/stubs, depending on whether MockBox is used standalone, or within ColdBox. When I was getting started with MockBox, I created that directory with mode 0777 on the disk, which always makes me feel uneasy. There's a better way to handle this situation: create a per-application mapping to a location in a in-memory filesystem. For example, consider the following chunk of an Application.cfc:

<cfset this.name = "MyApp"/> <cfset this.mappings = structNew()/> <cfset this.mappings["/coldbox/system/testing/stubs"] = "ram://MyApp/mockbox/stubs/"/>   <cfif not directoryExists("ram://MyApp/mockbox/stubs/")>   <cfset directoryCreate("ram://MyApp/mockbox/stubs/")/> </cfif>

When the MockGenerator now writes out files, it will be placing them in memory briefly. It works a treat. Of course, the in-memory filesystems are supported in relatively recent CFML engines. If I remember correctly, Railo had this feature first, and I don't know when it was added to Open BlueDragon. Adobe ColdFusion 9 has it, and can be toggled on/off in the ColdFusion Administrator interface.

I whipped up a little test application that can be used to verify that in-memory filesystem mappings are working correctly in your environment: in-memory-filesystem-mapping.zip

Mach-II Environment and CGI.SERVER_NAME

I'm running an instance of ColdFusion in a container that doesn't provide the original request hostname in the CGI.SERVER_NAME variable. That's a problem because I'm also using the Mach-II EnvironmentProperty, which rocks pretty hard, to match environment properties to the name of the server running the application. In my case, the server name is set in an HTTP header from the upstream Nginx server. So, what to do?

First, I created a drop dead simple component called EnvironmentHelperProperty that looks like this:

<cfcomponent extends="MachII.framework.Property" output="false">   <cffunction name="configure" returntype="void" access="public" output="false">     <cfset var serverPropertyName = getParameter("serverPropertyName", "serverName")/>     <cfset setProperty(serverPropertyName, getHttpRequestData().headers["X-Forwarding-ServerName"])/>   </cffunction> </cfcomponent>

Then I added the property to my Mach-II configuration before the existing EnvironmentProperty:

<property name="environmentHelperProperty" type="properties.EnvironmentHelperProperty">   <parameters>     <parameter name="serverPropertyName" value="serverName"/>   </parameters> </property> <property name="environment" type="MachII.properties.EnvironmentProperty">   <parameters>     <parameter name="defaultEnvironmentName" value="production"/>     <parameter name="serverPropertyName" value="serverName"/>     <!-- All the other stuff -->   </parameters> </property>

Finally, I made a tiny hack to the Mach-II EnvironmentProperty to honor an existing value in the serverName property, EnvironmentProperty.cfc.diff

IIS 7 and HTTP status codes from ColdFusion

First, some background. I am configuring a machine with Windows “Server” 2008 R2 running IIS 7 to be the host of a CFML application, written in ColdBox and making use of RESTful URL patterns. The application serves an API to gain access to services and information; all successful responses are in a data structure like this:

{status="success", message="", data={objects={name=value}}}

Errors look something like this:

{status="failure", message="Missing required such and such.", data=""}

The HTTP responses containing failure conditions make use of the HTTP status codes to give the API client immediate feedback on the success or failure of the request. A success will return with the typical “200 OK” response, while errors have something like “400 Error in request format” or “403 Invalid API credentials.”

The problem when loading this application on a web server running IIS is that responses of status code 400 did not contain the response body that the application created. Instead, it had the simple string “Bad Request” as pictured below.

A request that returned a 401 response would cause IIS to display its error template for a permission failure.

In working on this problem, I created a simple CFML file called generr.cfm that would simulate the success and failure responses of the API. If an error code is specified in the query string, the response will contain an HTTP status code to match. I started in IIS Manager looking for a way to disable the built-in error templates. I didn't see a way, so I thought I'd just delete all of the registered templates in the Error Pages feature. Doing so caused IIS to write out a new web.config file in the root of the virtual web site containing the following:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <httpErrors existingResponse="PassThrough" /> </system.webServer> </configuration>

Suddenly, every request for a CFML file started to fail. I didn't realize that when the Adobe ColdFusion Web Server Configuration Tool is executed to install the ISAPI Jrun connector, it too uses the web.config file. I ran wsconfig again, opened the new web.config file and added the single httpErrors element to it. Now it works properly. The following shows a successful response:

And this is the HTTP response I wanted when I started this wild goosechase:

ColdFusion ORM and Simple Lookup Tables

While working with ColdFusion ORM, I encountered a quandry: should simple lookup tables have their own entities (ColdFusion Components) or is that Objected Oriented Overkill? To illustrate, I created a test application with two entities, Person and Rating. The rating is just a string, and it seems silly to create a CFC with just one property, which would be accessed like person.getRating().getRating(). One way to create the entity CFCs is like so:

<!--- /contacts/model/Person.cfc ---> <cfcomponent persistent="true" table="person">   <cfproperty name="id" fieldtype="id" generator="native"/>   <cfproperty name="name"/>   <cfproperty name="sortId" column="sort_id"/>   <cfproperty name="rating" cfc="model.Rating" fieldtype="many-to-one" fkcolumn="rating_id"/> </cfcomponent> <!--- /contacts/model/Rating.cfc ---> <cfcomponent persistent="true" table="rating">   <cfproperty name="id" fieldtype="id" generator="native"/>   <cfproperty name="rating"/> </cfcomponent>

The simplified entity would use a computed property that fetches the rating with a formula:

<!--- /contacts/model/Person.cfc ---> <cfcomponent persistent="true" table="person">   <cfproperty name="id" fieldtype="id" generator="native"/>   <cfproperty name="name"/>   <cfproperty name="ratingId" column="rating_id"/>   <cfproperty name="rating" formula="SELECT r.rating FROM rating AS r WHERE r.id = rating_id"/> </cfcomponent>

Here's a chunk of SQL that would create the tables backing up the entities, and some example data:

CREATE TABLE person (   id SERIAL PRIMARY KEY,   name VARCHAR(100) NOT NULL,   rating_id INTEGER ); CREATE TABLE rating (   id SERIAL PRIMARY KEY,   sort_id SMALLINT NOT NULL DEFAULT (0),   rating VARCHAR(100) NOT NULL ); INSERT INTO person (name, rating_id) VALUES ('Rachel Maddow', 2); INSERT INTO person (name, rating_id) VALUES ('Jon Stewart', 1); INSERT INTO person (name, rating_id) VALUES ('Glenn Beck', 4); INSERT INTO person (name, rating_id) VALUES ('Bill O''Reilly', 3); INSERT INTO person (name, rating_id) VALUES ('Rush Limbaugh', 5); INSERT INTO rating (rating, sort_id) VALUES ('Crazy Awesome', 1); INSERT INTO rating (rating, sort_id) VALUES ('Cool', 2); INSERT INTO rating (rating, sort_id) VALUES ('Meh', 3); INSERT INTO rating (rating, sort_id) VALUES ('Assclown', 4); INSERT INTO rating (rating, sort_id) VALUES ('Dead to Me', 5);

When entityLoad("Person") is executed with a proper relationship to the lookup entity, the following is constructed:

The simple entity with the calculated property looks like this:

One of the benefits of going to the effort of creating the Rating entity is that all of them can be fetched (say, for a drop-down list in a form) using a simple entityLoad("Rating", {}, "sortId asc") as shown here:

An argument could be made that since the value of ratingId submitted by a form would be the actual foreign key needed to save in the person table, there's no need to instantiate a Rating, just to use it in person.setRating(rating) on the following line. It would be much easier to do person.setRatingId(form.ratingId).

The code I used when fiddling around on this topic is available: coldfusion-orm-lookups.zip

Perl one-liner for ColdFusion XML configuration file

I wrote a Perl one-liner to modify ColdFusion's adminconfig.xml file to enable the migration wizard using ColdFusion 8 settings. It's somewhat silly, since it's probably every bit as easy to make the change with an editor by hand. However, if you're automating the upgrade of many servers, it could be useful.

ACTION=on for SETTING in runmigrationwizard migratecf8; do perl -p -i -e 'BEGIN{$s=$ENV{"SETTING"}; $a=$ENV{"ACTION"}; %tf=(0,"false",1,"true"); $vs=($a = ~/^on/)?0:1; $vf=($vs eq 0)?1:0; $m="(<$s>)".$tf{$vs}."(</$s>)";} s/$m/\1$tf{$vf}\2/i' adminconfig.xml done

I tried to make it as concise as possible, and there is definitely a shorter way to make the change. However, I wanted to support flipping the values in either direction (on/off). This would conceivable work on any XML file that places simple true/false values in the text node of simple elements. Yes, both of those files! Heh.

PS: I'm posting this on my own blog (which I so rarely do anymore) because I know that Posting all those special characters would have been a complete nightmare on my Posterous blog.

ColdFusion/JRun + Apache Commons Logging

I recently encountered a problem I'd never seen before when taking advantage of powerful Java libraries within CFML components. Since this is really specific to Adobe ColdFusion and Macromedia JRun, it won't be an issue with other configurations. Specifically, here are the details:

  • Microsoft Windows “Server” 2003 Standard Edition
  • Adobe ColdFusion 8.01 Enterprise as MultiServer
  • JavaLoader 1.0 beta
  • jXLS 0.9.9-SNAPSHOT
  • Apache POI 3.5-FINAL
  • Apache Commons BeanUtils 1.8.0
  • Apache Commons BeanUtils Collections 1.8.0
  • Apache Commons BeanUtils Core 1.8.0
  • Apache Commons Collections 3.2.1
  • Apache Commons Digester 1.8
  • Apache Commons JEXL 1.1
  • Apache Commons Logging 1.1.1

The project uses the jXLS XLSTransformer utility class to parse an Excel file and to push information into cells containing syntax like ${bean.prop}. It worked fine on my workstation, but when running on the staging servers, it threw an exception with the following message: User-specified log class 'jrunx.axis.Logging' cannot be found or is not useable.

After many hours of investigation, I tracked the problem down to the so-called discovery process that org.apache.commons.logging.LogFactory uses to provide logger implementations. It was my assumption that when using Mark Mandel's JavaLoader to create instances of classes from the JAR files added to its ClassLoader, they would be isolated from the rest of the JVM. That's not exactly how it works, even if configured not to use ColdFusion's ClassLoader as the parent. To force the LogFactory not to use jrunx.axis.Logging, I tried rebuilding the jXLS library with a commons-logging.properties file to specify which logger implementation to use; I tried adding the properties file to the lib directory. Neither solved the problem.

The solution is pretty simple. After configuring JavaLoader, and before having it instantiate the needed XLSTransformer, just set the desired logger programmatically. Here is the chunk of XML that ColdSpring uses to fill JavaLoader with all the JAR files required.

<bean id="jxlsClassPath" class="model.io.FileEnumerator"> <property name="pathList"> <value>/jxls/lib</value> </property> <property name="patternList"> <value>*.jar</value> </property> </bean> <bean id="jxlsFactory" class="jxls.Factory"> <property name="javaloader"> <bean class="javaloader.JavaLoader"> <constructor-arg name="loadPaths"> <bean factory-bean="jxlsClassPath" factory-method="getFileArray"/> </constructor-arg> </bean> </property> </bean>

The code inside the CFC that does the work of creating the XLSTransformer then explicitly sets the logger:

<cfscript> var javaLoader = getJavaLoader(); var logFactory = "null"; var transformer = createObject("component", "jxls.Transformer").init(); logFactory = javaLoader.create("org.apache.commons.logging.LogFactory").getFactory(); logFactory.setAttribute("org.apache.commons.logging.LogFactory", "org.apache.commons.logging.impl.LogFactoryImpl"); logFactory.setAttribute("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); transformer.setXLSTransformer(getJavaLoader().create("net.sf.jxls.transformer.XLSTransformer")); return transformer; </cfscript>

There was much celebration when this worked, I assure you.

Listening Programs in Windows

While trying to get the line debugger in ColdFusion Builder to work with an installation of ColdFusion 9, I wanted to verify which processes were listening for TCP connections on my Windows XP workstation. I started by using the netstat utility in C:\WINDOWS\system32\ to show the IP and port of each connected endpoint, and the local process identifier. This is useful, but somewhat cumbersome to translate into recognizable application names. Here's a sample of its output:

Proto Local Address Foreign Address State PID TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 3772 TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 1988 TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 TCP 127.0.0.1:1117 127.0.0.1:4331 ESTABLISHED 3980 TCP 127.0.0.1:1130 0.0.0.0:0 LISTENING 1264 TCP 127.0.0.1:1208 127.0.0.1:20345 ESTABLISHED 640 TCP 127.0.0.1:1217 127.0.0.1:20345 ESTABLISHED 3000 TCP 127.0.0.1:4331 0.0.0.0:0 LISTENING 504

Using the process utility from Cygwin, it's possible to list all of the running processes. It has some quirks when showing Windows information, but it works. Here's a sample of that information:

PID TTY STIME COMMAND 4 ? Apr 22 *** unknown *** 1412 ? 09:03:14 \SystemRoot\System32\smss.exe 1528 ? 09:03:17 \??\C:\WINDOWS\system32\csrss.exe 1552 ? 09:03:22 \??\C:\WINDOWS\system32\winlogon.exe 1600 ? 09:03:24 C:\WINDOWS\system32\services.exe 1612 ? 09:03:24 C:\WINDOWS\system32\lsass.exe 1812 ? 09:03:25 C:\WINDOWS\system32\nvsvc32.exe 1152 ? 09:03:28 C:\Program Files\Symantec\Symantec Endpoint Protection\Smc.exe 1908 ? 09:03:32 C:\Program Files\Common Files\Symantec Shared\ccSvcHst.exe 752 ? 09:03:33 C:\WINDOWS\system32\spoolsv.exe 1860 ? 09:03:42 C:\WINDOWS\system32\svchost.exe 1320 ? 09:03:43 C:\Program Files\Google\Google Desktop Search\GoogleDesktop.exe

I needed to merge the two sources of information together. I started in the shell by chaining a few tools together, but it became awkward and inefficient. I switched to Perl, and hacked together a script that produces output like this:

Connections: 25 3772: 0.0.0.0:80 0.0.0.0:0 C:\Program Files\Apache Software Foundation\Apache2.2\bin\httpd.exe 1988: 0.0.0.0:135 0.0.0.0:0 C:\WINDOWS\system32\svchost.exe 4: 0.0.0.0:445 0.0.0.0:0 Windows System Process 3748: 10.0.1.169:1402 74.125.19.147:80 C:\Program Files\Google\Google Desktop Search\GoogleDesktop.exe 3464: 10.0.1.169:1520 204.2.160.49:80 c:\Program Files\Microsoft IntelliType Pro\dpupdchk.exe 3316: 10.0.1.169:1538 10.0.1.2:1025 C:\Program Files\Microsoft Office\OFFICE11\OUTLOOK.EXE 652: 10.0.1.169:1828 205.188.1.113:5190 C:\Program Files\Pidgin\pidgin.exe

Don't overlook how beautifully the IP and port are aligned. :) The source is available in my Subversion repository as listening.pl.

Installing FusionReactor 3 in ColdFusion 8 on CentOS 5

I document changes to web application cluster nodes to make the procedure repeatable, and for future reference. Recently I installed FusionReactor on CentOS 5 servers using the manual installation instructions. I couldn't use the installer program because these boxes don't run X11, and I prefer to do the installation from the command line anyway. I used the instructions from FusionReactor Installation Guide on the first attempt to install the software. After troubleshooting a few problems, I made explicit instructions for the installation.

Locate the current release of FusionReactor 3 for Linux in an RPM package; see FusionReactor Manual Installation section on the downloads page. Grab the URL for the download, and perform the following:

# Download the RPM and verify wget http://www.fusion-reactor.com/fr/FusionReactor-Download-Link md5sum FusionReactor.rpm rpm -Uvh FusionReactor.rpm # Stop Apache and ColdFusion service httpd stop service coldfusion_8 stop # Modify FusionReactor permissions chown nobody $FR_HOME chown -R nobody $FR_HOME/html chown -R nobody $FR_HOME/etc chown -R nobody $FR_HOME/instance # Configuration for defaults CF8_HOME=/opt/coldfusion8 FR_NATIVE_LIBS=$CF8_HOME/lib FR_JAVA_LIBS=$CF8_HOME/runtime/servers/coldfusion/SERVER-INF/lib FR_HOME=/opt/fusionreactor FR_PREFS=com/intergral JAVA_SYSTEM_PREFS=/etc/.java/.systemPrefs # Copy Java and native files if [ ! -d $FR_JAVA_LIBS ]; then mkdir $FR_JAVA_LIBS fi cp $FR_HOME/etc/lib/fusionreactor.jar $FR_JAVA_LIBS cp $FR_HOME/etc/lib/libFusionReactor.so $FR_NATIVE_LIBS # System Java prefs if [ ! -d $JAVA_SYSTEM_PREFS/$FR_PREFS ]; then mkdir -pm 777 $JAVA_SYSTEM_PREFS/$FR_PREFS fi chmod 777 $JAVA_SYSTEM_PREFS

The next part of the installation requires copying a chunk of XML from the FusionReactor source into the ColdFusion server configuration:

# Copy the <filter/> and <filter-mapping/> vim $FR_HOME/etc/conf/fusionreactor-web.xml $CF8_HOME/runtime/servers/coldfusion/SERVER-INF/default-web.xml

The firewall must be updated to allow HTTP access to the FusionReactor interface. That making the change, Apache and ColdFusion can be brought up.

# Update firewall # -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 8088 -j ACCEPT vim /etc/sysconfig/iptables service iptables restart # Start Apache and ColdFusion service coldfusion_8 start service httpd start

Immediately login to the FusionReactor and change the password for the Administrator account; disable the Manager and Observer accounts. Viola! Please let me know if this is useful to you.

ColdFusion Stale Class Files

While performing a deploy of my Job Scheduler application last night, I encountered a weird problem with ColdFusion not picking up new versions of CFC files. The environment is a network of CentOS 5 servers. The load balancer directs HTTP requests to a suitable web server. Both web servers run Apache HTTP 2.2 and ColdFusion 8.01; they automount (NFS) each user's home directory within which are web root directories containing CFML files. When updating files in a user's home directory, I login as the user from the administration system and make changes to the appropriate web root -- again, over NFS. Typically, this all works perfectly.

The issue last night was that a new version of Transfer was not being compiled by the ColdFusion services. I could see that /opt/coldfusion8/wwwroot/WEB-INF/cfclasses/cfConfiguration2ecfcXXX.class was not being replaced when a new version of /home/user/wwwroot/transfer/com/config/Configuration.cfc was in place. The old version was Transfer 0.6.3; the new version is Transfer 1.1. I had moved the old version to /transfer-0.6.3 and unzipped the new version as /transfer. There is another application in the user's web root that uses Transfer. Perhaps it had a copy of the CFC in its application scope, and that caused ColdFusion to disregard the updated file. Restarting ColdFusion didn't solve the problem. I shut down the web server “B” so all requests made through the load balancer would arrive at web server “A”. I made a few test CFML pages to verify that some files would be compiled by ColdFusion -- that worked fine.

Unable to update Transfer to the new version, I created a mapping in the Application.cfc for the Job Scheduler:

this.webRoot = getDirectoryFromPath(expandPath("/")); this.appPath = getDirectoryFromPath(getMetaData(this).path); this.appRoot = replace(this.appPath, this.webRoot, ""); this.mappings = structNew(); this.mappings["/"] = this.webRoot; this.mappings["/transfer"] = this.webRoot & "/transfer_1_1";

That workaround enabled the deployment to proceed, but I'm still not completely satisfied.

Update:
I should have mentioned that the “Trusted cache” and “Save class files” options were disabled and it didn't affect the problem. I also deleted cfConfiguration2ecfc*.class manually to force ColdFusion to recreated them. It did -- but the wrong version again.