Archive for November, 2005

CF on J2EE: Accessing Java

Being able to access the properties of the underlying JVM is one of the most basic, and useful, benefits of running ColdFusion on a J2EE system. However, I’ve responded to many people who are new to this deployment about how to access them.

It couldn’t be simpler. Let’s start off with seeing everything that’s available in the java.lang.System structure. Put this code in a blank CFM page.

<cfscript>
j2eeSystem = createobject("java", "java.lang.System");
</cfscript>
<cfdump var="#j2eeSystem#">

Now you’ll see a large dump to your browser with structure key names like Err, In, Out, Properties and others. The most useful of these is the Properties structure. You’ll see as you browser the keys of Properties that some keys are basic JVM keys such as java.class.path and java.runtime.version. So to access a specific value of the Properties structure, your code would be…

<cfscript>
j2eeSystem = createobject("java", "java.lang.System");
javaVendor = sys.Properties['java.specification.vendor'];
</cfscript>
<cfdump var="#javaVendor#">

You can get all kinds of information about the current state of the JVM by accessing these keys. Here’s a fun bit of code. Granted, these values are readily available in the CGI scope of ColdFusion, but it gives you an idea of how to access values from the underlying J2EE system.

<cfscript>
writeOutput("Request URI: " &
   GetPageContext().getFusionContext().request.getRequestURI());
writeOutput("<br/>Request URL: " &
   GetPageContext().getFusionContext().request.getRequestURL());
writeOutput("<br/>Request Context Path :" &
   GetPageContext().getFusionContext().request.getContextPath());
writeOutput("<br/>Request getQueryString :" &
   GetPageContext().getFusionContext().request.getQueryString());
writeOutput("<br/>Request getRemoteAddr :" &
   GetPageContext().getFusionContext().request.getRemoteAddr());
writeOutput("<br/>Request LocalName :" &
   GetPageContext().getFusionContext().request.getLocalName());
writeOutput("<p>COOKIES</p> ");
cookies = arraynew(1);
cookies = GetPageContext().getFusionContext().request.getCookies();
for (i=1; i lt arraylen(cookies); i=i+1)
{
   name = cookies[i].getName();
   value = cookies[i].getValue();
   writeOutput("#name# = #value#<br/>");
}
</cfscript>

Ruby On Rails for ColdFusion


The folks over at Cube6 Media have started a port of Ruby on Rails to ColdFusion. ColdFusion on Wheels “…brings all the benefits of an MVC architecture to ColdFusion without having to write the underlying framework from scratch every time.”

A truly noble goal and I, for one, will be following this one closely.

Preventing 404 Errors with Servlets

I ran into a very strange problem, and have been unable to determine the cause of this behavior. This is not a surprise seeing how closely Microsoft guards the innards of their software.

On a J2EE (Tomcat) ColdFusion site that uses 404 error redirection, any browser that I tested shows two connections with Tomcat (see below) and the proper redirection is performed.

[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] servletPath=/index.cfm, pathInfo=null, queryString=site=lost, name=null
[org.apache.catalina.core.ApplicationDispatcher] Path Based Forward
[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] Disabling the response for futher output
[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] servletPath=/index.cfm, pathInfo=null, queryString=site=lost, name=null
[org.apache.catalina.core.ApplicationDispatcher] Path Based Forward
[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] Disabling the response for futher output
[org.jboss.web.localhost.Engine] org.apache.catalina.core.StandardHostValve@1df3d59: Exception Processing ErrorPage[errorCode=404, location=/index.cfm?site=lost]
ClientAbortException: java.net.SocketException: Software caused connection abort: socket write error
at org.apache.coyote.tomcat5.OutputBuffer.realWriteBytes(OutputBuffer.java:373)
etc…

However, when I create and use a link in Microsoft Word to the same URL, here’s the log entry for that connection…

[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] servletPath=/index.cfm, pathInfo=null, queryString=site=lost, name=null
[org.apache.catalina.core.ApplicationDispatcher] Path Based Forward
[org.apache.catalina.core.StandardWrapper] Returning non-STM instance
[org.apache.catalina.core.ApplicationDispatcher] Disabling the response for futher output

You can see that the connection is terminated after the first 404 response. Microsoft Word then throws up an alert: “The Internet site reports that the item you requested could not be found. (HTTP/1.0 404)”

Wonder of wonders, this does not happen when hitting a site running IIS and using error handlers. So I’m assuming that Word is looking for a specific header response when a 404 is encountered and if it does not see it, terminates the connection with the server immediately.

I’ve been able to find no information on the Internet regarding how Word handles connections with servers, so finding a way around this might be futile.

Thanks to some feedback from Nathan Derksen, this slightly humorous posting on Peeve Farm shows me what’s going on. Microsoft Word must still be using the protocol that existed in IE5 (it may still exist!) and then simply quits when the server has the nerve to not immediately send back the requested content.

Every Microsoft product that I tried this from had the same result. The page would not load and the application reported that the page did not exist. I had to write a servlet filter that reformatted the request based on my 404 redirection rules.

Here’s a truncated look at the code in my filter class.

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        Pattern pattern;
        Matcher matcher;
        String serverName = "";
        StringBuffer requestURL;
        String validSiteName = "";
        HttpServletRequest httpRequest = (HttpServletRequest)request;
        HttpServletResponse httpResponse = (HttpServletResponse)response;

        requestURL = httpRequest.getRequestURL();
        serverName = httpRequest.getHeader("serverName");

        pattern = Pattern.compile("^http://[A-Za-z0-9.-]*/([A-Za-z0-9]*)$");
        matcher = pattern.matcher(requestURL);

        if ( matcher.find() )
        {
            validSiteName = matcher.group(1);
            log.info("Branded site URL pattern (" + requestURL + ") match: " + validSiteName);
        }

        if (validSiteName != "")
        {
            httpResponse.setStatus(200);
            log.info("Redirecting to /index.cfm?where=" + validSiteName);
            httpResponse.sendRedirect("/index.cfm?where=" + validSiteName);
            return;
        } else {
            chain.doFilter(request, response);
        }
    }