Thursday, June 19, 2003

Iterating over an Enumeration with CFMX

I tried writing some CFML code to iterate over a java.util.Enumeration, a fairly common thing to do in java, but was plagued with java.lang.IllegalAccessException's.

IllegalAccess exceptions usually occurr when you try to call a method using reflection (which CFMX does) that doesn't exist. However I'm quite sure that hasMoreElements() is a method of java.util.Enumeration. In fact if I cfdump the propNames variable the hasMoreElements method shows up! Here's the code I'm using:

<cfset system = CreateObject("java", "java.lang.System")>
<!--- properties is a java.util.Properties object --->
<cfset properties = system.getProperties()>

<!--- propNames is a java.util.Enumeration --->
<cfset propNames = properties.propertyNames()>

<cfoutput>
 <cfloop condition="propNames.hasMoreElements()">
	<cfset propName = propNames.nextElement()>
	#propName# = #system.getProperty(propName)#<br />
 </cfloop>
</cfoutput>

I suspect the problem has something to do with CFMX not realizing that propNames is an Enumeration, I wish that JavaCast accepted more types besides the primitives.

Here's the stack trace I'm receiving, I'm using CFMX U3:

java.lang.IllegalAccessException
	at java.lang.reflect.Method.invoke(Native Method)
	at coldfusion.runtime.StructBean.invoke(Unknown Source)
	at coldfusion.runtime.CfJspPage._invoke(Unknown Source)
	at Statement12.evaluate(Unknown Source)
	at coldfusion.runtime.CFPage.evaluateCondition(Unknown Source)
	at cftesta2ecfm779424527.runPage(C:\web\testa.cfm:19)
	at coldfusion.runtime.CfJspPage.invoke(Unknown Source)
	at coldfusion.tagext.lang.IncludeTag.doStartTag(Unknown Source)
	at coldfusion.filter.CfincludeFilter.invoke(Unknown Source)
	at coldfusion.filter.ApplicationFilter.invoke(Unknown Source)
	at coldfusion.filter.PathFilter.invoke(Unknown Source)
	at coldfusion.filter.LicenseFilter.invoke(Unknown Source)
	at coldfusion.filter.ExceptionFilter.invoke(Unknown Source)
	at coldfusion.filter.BrowserDebugFilter.invoke(Unknown Source)
	at coldfusion.filter.ClientScopePersistenceFilter.invoke(Unknown Source)
	at coldfusion.filter.BrowserFilter.invoke(Unknown Source)
	at coldfusion.filter.GlobalsFilter.invoke(Unknown Source)
	at coldfusion.filter.DatasourceFilter.invoke(Unknown Source)
	at coldfusion.CfmServlet.service(Unknown Source)
	at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
	at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
	at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:226)
	at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:527)
	at jrun.servlet.http.WebService.invokeRunnable(WebService.java:172)
	at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:348)
	at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:451)
	at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:294)
	at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

I may end up reporting this one to Macromedia as a bug, unless I'm missing something here.

GetTempDirectory() returns a different path in MX

I noticed today that GetTempDirectory() returns a different path than it did in CF5 and prior versions. In CFMX it returns cfusionmx/runtime/servers/default/SERVER-INF/temp/wwwroot-tmp.

I'm not quite sure why this is, because the java System property java.io.tmpdir = C:\WINNT\TEMP\ on my machine. I would have thought they would use that value as CF5 does.

Anyways I thought it should be pointed out since it is not in the release notes. I'm not going to report it as a bug, because I don't think it makes much difference what directory GetTempDirectory() returns as long as its a temp dir.

Wednesday, June 18, 2003

Query of Queries with maxrows bug

I found a bug today in CFMX, CF5 executes the code as you would expect.

Essentially if you do a query of query with maxrows, and then do another q of q on that result, the resulting q of q is using the wrong query and returns the wrong number of rows.

<!--- make a query --->
<cfset q = QueryNew("a,b")>
<cfset r = QueryAddRow(q)>
<cfset QuerySetCell(q, "a", "a1", r)>
<cfset QuerySetCell(q, "b", "b2", r)>
<cfset r = QueryAddRow(q)>
<cfset QuerySetCell(q, "a", "a2", r)>
<cfset QuerySetCell(q, "b", "b3", r)>
<cfset r = QueryAddRow(q)>
<cfset QuerySetCell(q, "a", "a3", r)>
<cfset QuerySetCell(q, "b", "b1", r)>

<!--- dump it, 3 rows --->
<cfdump var="#q#">

<!--- select max rows of 2, 2 rows --->
<cfquery dbtype="query" name="result" maxrows="2">
	SELECT * FROM q
	ORDER BY a DESC
</cfquery>

<cfdump var="#result#">

<!--- select everything from the 2 row query returns 3 rows? --->
<cfquery dbtype="query" name="result2">
	SELECT * FROM result
	ORDER BY b DESC
</cfquery>

<cfdump var="#result2#" label="this should only have 2 rows, but it has 3">

I reported this to Macromedia, and they verified it as a bug.

Tuesday, June 17, 2003

Using UUID's for CFTOKEN and Database client storage

Just a heads up if your using UUID's for CFTOKEN values with database client storage when upgrading to CFMX, be sure to change the size of the cfid field in the CDATA and CGLOBAL tables. The cfid field stores both the cfid and cftoken value as follows cfid:cftoken. The cfid is usually around 7 characters, and the cftoken when using a UUID is a 35 character UUID plus a 17 character prefix. Just to be safe I changed the size to 64 characters, and changed it to a varchar type.

Below is the error message generated:

Operation failed on the data source named "yourdatasource". 

Reason of failure "[Macromedia][SQLServer JDBC Driver][SQLServer]String or 
  binary data would be truncated."
 
Stack Trace:

coldfusion.runtime.ClientScopeDBException: 
        Operation failed on the data source named "datasourcename".
        at coldfusion.runtime.JDBCHelper.Store(Unknown Source)
        at coldfusion.runtime.ClientScopeServiceImpl.PersistClientVariables(Unknown Source)
        at coldfusion.runtime.ClientScope.commitChanges(Unknown Source)
        at coldfusion.filter.ClientScopePersistenceFilter.invoke(Unknown Source)
        at coldfusion.filter.BrowserFilter.invoke(Unknown Source)
        at coldfusion.filter.GlobalsFilter.invoke(Unknown Source)
        at coldfusion.filter.DatasourceFilter.invoke(Unknown Source)
        at coldfusion.CfmServlet.service(Unknown Source)
        at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
        at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
        at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:226)
        at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:527)
        at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:198)
        at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:348)
        at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:451)
        at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:294)
        at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

Tuesday, June 10, 2003

Patterns Central

This web site: Patterns Central was pointed out to me today by a coworker. It has articles, and forums about design patterns.

Wednesday, June 04, 2003

Compiling the CFMX Apache Module from source code

I put up a howto on cfdev for installing the ColdFusion MX Apache module from source on linux, as well as a howto for installing Apache 2.0.46 from source, and a howto get php working on Apache2. To compile the apache module you need to install Apache from source, the RPM installation I had didn't include the apxs tool which compiles the module.