Tuesday, September 29, 2009

CFCatch me if you can

One thing that really annoys me with the cfcatch struct/object (or whatever its pretending to be) is trying to use one of the keys and have it not exist. There have been a few times where I simply want to log cfcatch.detail and it's undefined, throwing a hard error. To me, if it's documented that it is going to be available, it should at least be available as an empty string. I set out this morning looking for a clean way of param'ing some of the keys in cfcatch. Since it doesn't seem to be a true struct, you can't simply do:
<cfparam name="cfcatch.detail" default="" />
That would be way too easy. I found a couple places that suggested using duplicate() to make it act like a struct. I tried that too, and you still can't do a cfparam on it. The key simply won't exist.

After much googling, I came across this post by Isaac Dealey. So using that idea, I created the following function:
<cffunction name="structifyCatch" returntype="struct">
<cfargument name="catch" type="any" required="true"/>

<cfset var err = structnew() />
<cfset structappend(err,arguments.catch,true) />

<cfreturn err />

</cffunction>
then to implement it, you call the following:
<cftry>
... some code ...
<cfcatch>
<cfset cfcatch = structifyCatch(cfcatch) />
<cfparam name="cfcatch.message" default=""/>
<cfparam name="cfcatch.detail" default=""/>
<cflog text="There was an error in somecode().
Message: #cfcatch.message# Detail: #cfcatch.Detail#"
application="yes">
</cfcatch>
</cftry>
Hopefully this will save you a little bit of angst.
There are some interesting behaviors documented here too:
cfcatch was born a struct, then it wasn’t but now it’s back

Blessings,
Terry

Wednesday, September 23, 2009

Straight talk with ActiveMQ

I found that filling an ActiveMQ queue through a cfml gateway was extremely inefficient when sending a large number of messages at once. Here is the code to send messages directly to the queue via java. This was a little difficult to find this documented anywhere. I had to pull in bits an pieces from different code examples.
<cfset mess = structnew() />

<cfquery name="rs" datasource="dsn">
select id from mytable
</cfquery>

<cfscript>
connectionFactory = createobject(
'java'
,'org.apache.activemq.ActiveMQConnectionFactory'
).init('','', 'tcp://#amqServer#:#amqPort#?jms.useAsyncSend=true');

connection = connectionFactory.createConnection();
connection.start();
// createSession(transacted, session.auto_acknowledge)
javasession = connection.createSession(false, 1);
destination = javasession.createQueue("queuename");
producer = javasession.createProducer(destination);
</cfscript>

<cfloop query="rs">
<cfset mess.agentid = rs.id />
<cfwddx action="cfml2wddx" input="#mess#" output="strMess">

<!--- Send message to activeMQ through our opened channel --->
<cfscript>
message = javasession.createTextMessage(strMess);
producer.send(destination,message);
</cfscript>
</cfloop>

<!--- close up connections with activeMQ now that we are done with the channel --->
<cfscript>
producer.close();
javasession.close();
connection.close();
</cfscript>
Blessings,
Terry

Lost in translation: The Encoding Experience

I had written an undelivr folder viewer about a month back. We started testing some special chars through our mailing app recently and found that Programów was becoming Programów. We figured it had something to do with encoding. I checked the cfadmin setting for the default mail encoding and it was UTF-8. That should have been ok. I tried hardcoding charset="UTF-8" in the cfmail tag to see if that would help. Same results.

So then I switched gears to my local dev server and wrote up this quick script.
<cfset str ="Programów"/>
<cfmail from="a@b.com" to="a@c.com" subject="1.0" charset="utf-8">
#str#
</cfmail>

This works perfectly fine in my local dev. When I threw this script on the server it still got mangled. So now we're dealing with an environment issue. I'm running Ubuntu locally and we are running windows on the server. So I started digging into the settings in cfadmin. I took the settings summary from both servers and threw it into Kompare. One of the differences I saw right away was the Java File Encoding. On the server it was set to cp1252 and on my Linux it was UTF-8. After much searching, I was able to track down how to change the JVM's default file encoding here: Java's file.encoding property on Windows platform. After adding -Dfile.encoding=UTF-8 to the jvm's server.args (typically found in jrun4/bin/jvm.conf), I restarted the instance and re-ran the test. Bingo, the special chars were preserved.

There must be an issue with some special chars moving from UTF-8 to cp1252 or vice versa. I just ran a test and this does affect all emails if you are spooling to disk. My assumption is that under the covers, java is writing the file using the default JVM file encoding, not the default coding set for the cfmail tag. This makes the cfmail default setting a little misleading. At any rate, setting the JVM encoding to UTF-8 did the trick.

Blessings,
Terry

Thursday, September 10, 2009

Hot under the hotfix..

We ran into an error today on one of our dev servers.
coldfusion.runtime.J2eeSessionScopeStub cannot
be cast to coldfusion.runtime.J2eeSessionScopeStub

We had recently patched that server with "Cumulative Hot Fix 3 for ColdFusion 8.0.1" That was really the only thing that changed with the server before getting the error. I went into JRun4\servers\{instancename}\cfusion.ear\cfusion.war\WEB-INF\cfusion\lib\updates and removed chf8010003.jar. After restarting the instance, things came up normal. I thought that maybe the file we downloaded was corrupt so I grabbed a fresh copy. That file didn't work either. The head scratcher in this is that we installed the patch on other instances with no problems. Not sure what is so unique with this instance, but it just doesn't jive with the new hotfix.

here is the stack:
18840 java.lang.ClassCastException: coldfusion.runtime.J2eeSessionScopeStub cannot be cast to coldfusion.runtime.J2eeSessionScopeStub
18841 at coldfusion.runtime.SessionTracker.getSession(SessionTracker.java:76)
18842 at coldfusion.runtime.AppHelper.setupJ2eeSessionScope(AppHelper.java:528)
18843 at coldfusion.runtime.AppHelper.setupSessionScope(AppHelper.java:592)
18844 at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:235)
18845 at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
18846 at coldfusion.filter.PathFilter.invoke(PathFilter.java:86)
18847 at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)
18848 at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:74)
18849 at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
18850 at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
18851 at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)
18852 at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
18853 at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
18854 at coldfusion.CfmServlet.service(CfmServlet.java:175)
18855 at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
18856 at jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
18857 at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
18858 at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
18859 at jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
18860 at jrun.servlet.FilterChain.service(FilterChain.java:101)
18861 at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
18862 at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
18863 at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
18864 at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
18865 at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
18866 at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
18867 at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

Tuesday, September 8, 2009

Keepass Conundrum

I'm running Keepass on Kubuntu 8.10. Somewhere along the way Keepass stopped working for me. I could open the program and log in successfully. I could even see the groups on the left hand side of the window. What I could NOT see were the entries with their logins and passwords on the right. All I would get was a blank gray pane on the right. I tried a bunch of things including upgrading to KeepassX 0.4.0. Nothing worked. Fortunately there is a very simple solution to this. If you are experiencing the same thing, look very closely at the bottom of the right hand pane. You will see three little dots. Click that and drag upwards. Voila! There are all of your entries that you missed so dearly. Not sure if this was a bug with KDE and Keepass or what, but I sure was glad to find the fix on a blog somewhere. Thought I'd share the love here too.

Blessings,
Teeps