All posts by ajohnson

More on ColdFusion & HttpSessionListener interface

Update on yesterday’s post. Here’s a sample listener that implements the HttpSessionListener interface:

****************************************************
package com.mindseye;

import javax.servlet.http.*;
import javax.servlet.http.HttpSessionListener;

/**
* @author Aaron Johnson
* ajohnson@mindseye.com
*
* CFMXHttpSessionListener: An object that implements the HttpSessionListener
* interface, allowing CFMX developers to use session_OnStart and session_OnEnd
* events. This class can only retrieve the J2EE session ID when “Use J2EE
* session variables” is checked in CFIDE –> Administrator –> Memory
* Variables.
*/

public class CFMXHttpSessionListener implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent se) {

// get the session just created
HttpSession newSession = se.getSession();

// do something with the new session (ie: log to db, write to a file, email to a friend
System.err.println(“A new session was created: session = ” + newSession.toString());
System.err.println(“Creation:” + newSession.getCreationTime());

}

public void sessionDestroyed(HttpSessionEvent se) {

// get the session just created
HttpSession newSession = se.getSession();

/* do stuff upon session end, (ie: delete items from this users shopping cart
if you’re persisting items to a db..)
*/
System.err.println(“A session was destroyed: session = ” + newSession.toString());
System.err.println(“Creation:” + newSession.getCreationTime());

}
}

****************************************************
And then to get this class to run, you must add

<listener>
  <listener-class>
    com.mindseye.CFMXHttpSessionListener
  </listener-class>
</listener>

to CFMX\wwwroot\WEB-INF\web.xml and you must copy the compiled class to the CFMX\wwwroot\WEB-INF\classes\com\mindseye\ folder. Additionally, it appears that (and this makes sense) the session we’re getting information about is the J2EE session ID, not the CFID & CFTOKEN. This means that you must have “Use J2EE session variables” checked in CFIDE –> Administrator –> Memory Variables. Restart CFMX and then you can see the results in cfusionmx\runtime\logs\default-err.log

This class would probably be way more useful if it actually did something… like log the start and end times, the id and maybe the servlet context to a database, but each developer will probably want to do something different, so I’ll leave that unfinished. I’m *not* seeing the session_OnEnd fired in my testing… anyone wanna take a guess?

Here’s a sample application_OnStart for CFMX:

****************************************************
package com.mindseye;

import javax.servlet.*;
import javax.servlet.ServletContextListener;

/**
* @author Aaron Johnson
* ajohnson@mindseye.com
*
* CFMXServletContextListener: An object that implements the ServletContextListener
* interface, allowing CFMX developers to use application_OnStart and
* application_OnEnd events.
*/
public class CFMXServletContextListener implements ServletContextListener {

public void contextDestroyed(ServletContextEvent sce) {

ServletContext sc = sce.getServletContext();

// do something on destroy()
System.err.println(“The application ‘” + sc.getServletContextName() + “‘ was destroyed”);

}

public void contextInitialized(ServletContextEvent sce) {

ServletContext sc = sce.getServletContext();

// do something on destroy()
System.err.println(“The application ‘” + sc.getServletContextName() + “‘ was started”);
}
}
****************************************************

Again, same thing, you must copy the compiled class files to cfusion\wwwroot\WEB-INF\classes\com\mindseye\, add a <listener> element to web.xml and restart CFMX. You’ll see the results in cfusion\runtime\logs\default-err.log.

I’d love to hear from Macromedia (or any other Java geeks) as to why I don’t get an results from sessionDestroyed().

ColdFusion & HttpSessionListener interface

Couple weeks ago some guys from Macromedia stopped by to yack with us about what we thought could be improved and/or added to the next version of CFMX. One of the things that came up a couple times was that it would be nice to have session OnStart and OnEnd functionality as well as application OnStart and OnEnd. Reading this month’s Java Developer’s Journal, it has an article on the HttpSession object (I’d link to it, but they charge for their content… too bad, I bet they’d be getting alot more traffic and readers if they’d provide their content for free), which provides multiple listener objects, HttpSessionListener, HttpSessionBindingListener, HttpSessionAttributeListener, and HttpSessionActivationListener. I don’t have CFMX here at home, but it seems like it would be possible to write a class that implements those either of those interfaces (probably the sessionCreated() and sessionDestroyed methods of the HttpSessionListener object), register that class in the web.xml of WEB-INF for your application like this:

<listener>
  <listener-class>
    com.yourApp.yourSessionListener
  </listener-class>
</listener>

Turns out you could do the same type of thing w/ javax.servlet.ServletContextListener [contextDestroyed() and contextInitialized()] and then register:

<listener>
  <listener-class>
    com.yourApp.yourApplicationListener
  </listener-class>
</listener>

in your web.xml and then… hypothetically, you’d have session OnStart, session OnEnd, application OnStart and application OnEnd just like ASP.

I’ll try it out tomorrow, unless you beat me to it.

Content Synchronization Using Rsync

So months ago we were discussing ways of synchronizing files between two servers (for instance the images on a content staging and multiple production servers). My boss kinda put together a list of links for rsync, an open source utility used mainly for quickly transferring files. That email sat in my inbox for the last couple months and only until today did I start trying to get rsync to work. There aren’t any Windows binaries available on the site, which wasn’t a big deal because they gave directions for compiling it here. In order to compile, you need cgywin, so I downloaded and installed that, but the download/install I did for some reason didn’t include make which is required in order to compile rsync. So I went back and re-installed cygwin, this time exploding the options looking for make, only to find that cgywin includes rsync as an option! No need to compile for Windows, just download cygwin and specify that you want the rsync package installed!

I haven’t gotten there yet, but I plan to get rsync running as a service under Windows 2000 on a couple boxes (following these directions). You can find further directions and examples here. I’ll update later on how it works syncing up a couple websites.

On object-oriented design

On object-oriented design: “… Should I derive the class Polyline from the class Point? This has fairly obvious answer. A Polyline is clearly not a kind of point, so it is not logical to derive the class Polyline from the Point class. This is an elementary demonstration of what is often referred to as the ‘is a‘ test. If you can say that one kind of object ‘is a’ specialized form of another kind of object you may have a good case for a derived class…. The complement to the ‘is a’ test is a ‘has a‘ test. If one object ‘has a’ component that is an object of another class, you have a case for a class member. A House object ‘has a’ door, so a Door variable is likely to be a member of the class House.” [pg 254 of Beginning Java 2]

Use of the Class object

On the subject of the use of the Class object:

“… Reassuringly, instanceof and isInstance( ) produce exactly the same results, as do equals( ) and ==. But the tests themselves draw different conclusions. In keeping with the concept of type, instanceof says “are you this class, or a class derived from this class?” On the other hand, if you compare the actual Class objects using ==, (or getClass()) there is no concern with inheritance—it’s either the exact type or it isn’t.” [ezdefinition]

JSP Precompilation

More from the JSP Spec:

“A request to a JSP page that has a request parameter with name “jsp_precompile” is a precompilation request . The “jsp_precompile” parameter may have no value, or may have values “true” or “false”. In all cases, the request should not be delivered to the JSP page. The intention of the precompilation request is that of a suggestion to the JSP container to precompile the JSP page into its JSP page implementation class. The suggestion is conveyed by giving the parameter the value “true” or no value, but note that the request can be ignored.

For example:
1. ?jsp_precompile
2. ?jsp_precompile=”true”
3. ?jsp_precompile=”false”
4. ?foobar=”foobaz”&jsp_precompile=”true”
5. ?foobar=”foobaz”&jsp_precompile=”false”

1, 2 and 4 are legal; the request will not be delivered to the page. 3 and 5 are legal; the request will not be delivered to the page.

6. ?jsp_precompile=”foo”

This is illegal and will generate an HTTP error; 500 (Server error).”

So does anyone have utilities for automating this upon deployment of an application? Nice… apparently Ant has a task built in to do this very thing.

WEB-INF

So today at work a question came up about were you’re supposed to store your tld file for your JSP tags… in the webroot (ie: wwwroot/mytags.tld) or in the WEB-INF directory. From my work with with JSP and Servlets, I knew that mytags.tld was supposed to go in the WEB-INF directory, but I didn’t know why. So, why is it that way?

JSR-000053 JavaTM Servlet 2.3, page 61 of 257:

“A special directory exists within the application hierarchy named “WEB-INF”. This directory contains all things related to the application that aren’t in the document root of the application. The WEB-INF node is not part of the public document tree of the application. No file contained in the WEB-INF directory may be served directly to a client by the container. However, the contents of the WEB-INF directory are visible to servlet code using the getResource and getResourceAsStream method calls on the ServletContext. Hence, if the Application Developer needs access, from servlet code, to application specific configuration information that he does not wish to be exposed to the web client, he may place it under this directory. Since requests are matched to resource mappings case-sensitively, client requests for ‘/WEB-INF/foo’, ‘/WEb-iNf/foo’, for example, should not result in contents of the web application located under /WEB-INF being returned, nor any form of directory listing thereof.”

Still no mention of the TLD (tag library descriptor), although we now know that the WEB-INF directory is meant to be a secure place for application developers to place code without worrying about it being exposed to client requests.

So then you have to download JavaServer PagesTM 1.2 Specifications, page 112 of 268 says:

“Tag library descriptor files have names that use the extension “.tld”, and the extension indicates a tag library descriptor file. When deployed inside a JAR file, the tag library descriptor files must be in the META-INF directory, or a subdirectory of it. When deployed directly into a web application, the tag library descriptor files must always be in the WEB-INF directory, or some subdirectory of it.”

Ah, so according to the JSP Spec, we have to deploy the .tld file inside WEB-INF. But how are we supposed to reference the taglib once we have it deployed? Page 116 answers that:

“The explicit web.xml map provides a explicit description of the tag libraries that are being used in a web application. The implicit map from TLDs means that a JAR file implementing a tag library can be dropped in and used immediatedly through its stable URIs. The use of relative URI specifications in the taglib map enables very short names in the taglib directive. For example, if the map is:

<taglib>
  <taglib-uri>/myPRlibrary</taglib-uri>
  <taglib-location>/WEB-INF/tlds/PRlibrary_1_4.tld</taglib-location>
</taglib>

then it can be used as:

<%@ taglib uri=”/myPRlibrary” prefix=”x” %>

Finally, the fallback rule allows a taglib directive to refer directly to the TLD. This arrangement is very convenient for quick development at the expense of less flexibility and accountability. For example, in the case above, it enables:

<%@ taglib uri=”/WEB-INF/tlds/PRlibrary_1_4.tld” prefix=”x” %>”

Fun for the whole family! Let’s all go and try to use our taglibs now!

Exploring the Factory Design Pattern

Exploring the Factory Design Pattern: “Since most object-oriented languages and runtimes provide object instantiation (e.g. new, newobj, etc.) and initialization (e.g. constructors) mechanisms, there may be a tendency to simply use these facilities directly without forethought to future consequences. The overuse of this functionality often introduces a great deal of the inflexibility in the system, as the direct use of a language/run-time object instantiation function creates an explicit association between the creator and created classes. While associations are a necessary type of relationship in an object-oriented system, the coupling introduced between classes is extremely difficult to overcome should requirements change (as they always do).”