Tuesday, September 27, 2005

Introduction to ColdSpring AOP

Aspect Oriented Programming is a fairly new programming model that assists in handling far reaching services, like logging, security, transactions and object caching, in your model. Services like these are beginning to be referred to as ‘crosscutting concerns’, because they are applied broadly across your application. In order to add a service such as logging to an application, you typically find yourself applying very similar code all throughout your model, which when scrutinized, probably has nothing to do with the actual functionality of your components. AOP allows you to insulate these types of crosscutting concerns from the rest of you application, and apply them broadly based on certain policies that you as the developer define.

Using AOP is basically a process of looking at the types of concerns in your application and then breaking them apart into primary concerns, like your managing your shopping cart or navigating through and administering your product catalog, your application’s primary business logic, and crosscutting, generalized concerns, such as logging and security. These crosscutting concerns become what are known as ‘aspects’, and with AOP can be written singularly focused on the issues they solve, becoming more portable and reusable. These aspects are then applied to your model according to policies that you define, through a process known as ‘weaving’, which is performed by the AOP framework.

Defining policies is a matter of identifying ‘join points’ in your model, specific areas where you would like to apply the ‘advice’ of your aspects, meaning the specific action that you would like to take place at a certain time in your application. Join points are created using ‘pointcuts’ which are defined with wildcards or regular expressions to identify methods in your objects. Don’t get too worried about the terminology here; the primary concept is that you already have objects with methods in them that you want to add functionality to. You do this through advice. There are three types of advice available in ColdSpring AOP, before, after, and around advice. Before advice is run before the join point will be performed; after advice will be run after the join point. Around advice is like a combination of both. Around advice is actually quite powerful because it is given full control of the execution of the join point and it has the ability to advise errors through try/catch blocks.
The final concepts to understand in AOP are ‘target’ and ‘proxy’ objects. The target object is object in your model that you want to apply your aspects to. Through the process of weaving, the AOP framework will use the policies you defined via pointcuts to build a new proxy object containing the configured advice, which, and here’s the most important part, appears to be one in the same as the target object to the rest of your application. Now I know a lot of this is sounding confusing and a bit difficult, but it’s important to understand that most of the work is actually done for you. You will primary concern yourself with creating the advice objects themselves. Pointcuts are defined through configuration and ColdSpring AOP handles the rest. In the context of ColdSpring, the configuration is done through an xml file, and the proxy object can be swapped out for the target object with minimal effort.

I’ll post some actual examples after I get a chance to run through them at the conference and get some feedback. Hopefully I’ll get a chance to meet a few people who just may have read some of this there!

Monday, September 26, 2005

ColdSpring, AOP and the Fusebox/Frameworks Conference

This weekend was one of those crazy weekends that your eyes and wrists hurt and the end of. On top of the kids waking up at all hours so I'm not even getting any sleep, I wrote just a ridiculous amount of code, and now I'm just staring at the work I'm supposed to be doing for my day job like it's in Russian or something. But it was super worth it, because I've got some big news for everyone. First off, for a while now I've been using Dave Ross's ColdSpring CFC container in a big project I'm working on, which kind of lead me to work on ColdSpring. A lot of work was done this weekend merging code with the current version, and that was honestly an exiting experience. I've never before worked with another developer who I see completely eye to eye with, it made me think a bit about pair programming / xp, if it actually is useful. Anybody who has any experience it, please share your experiences, I'd love to hear about it. Anyway, working on ColdSpring kind of lead me into doing a whole lot of work another big side project.

While talking with Dave about the types of things that can be brought into ColdSpring, I started thinking heavily about how the aop framework is used in Spring for Java, and the type of stuff we could build into ColdSpring if we had an aop (Aspect Oriented Programming) layer. So after a hell of a lot of thinking and completely unintelligible chicken scratch notes left around the house, driving my wife nuts when I want to know what happened to the menu with all the little boxes drawn on the back of it, I am very pleased to tell you that I have a functional aop framework to be released in the very near future, hopefully at the Frameworks Conference. I'm not going to go into great detail about what aop is and how it's used right now, I have some real tutorials coming. But I will be going to the Fusebox/Frameworks conference with Dave, where I guess we'll make the official announcement. I have some great examples that I've been bustin my butt to put together, maybe I should have started an example app before this past saturday? I'm looking forward to showing these at a BOF session at the conference, so look for Dave and me there!

Wednesday, September 21, 2005

Using log4j in ColdFusion

I went to an interview last Thursday and in the course of it the lead developer and I (my job had apparently been filled!) got into a two hour discussion about caching cfcs with oscache, working with coldspring, aop, and using log4j in coldfusion. Although the interview part didn’t lead to much, I did leave thinking about a lot of cool things, especially pressing being incorporating log4j into a side project that I’m getting pretty heavily involved in. I’ve worked with log4j in java, and it’s super simple, very fast, easy to configure, and I’ve been thinking of using it in cf, but basically haven’t tried. Although I think cflog is just a wrapper around log4j anyway, by using it directly you gain the benefit of setting the max size of the log file created, along with configuration of backup files, the level of logging to output (debug, info, warn, error, fatal), and formatting of the messages. Also, most importantly, it’s really easy to turn on and off, and since log4j is built to be extremely fast the cost of log statements in your code is marginal. So if I’ve peeked you interest, here’s a little rundown of how to get log4j running, with some extra links at the end of the post, including a link to an excellent tutorial on ColdFusion Developer’s Journal, which to be honest, much of this is a paraphrasing anyhow. So on to the code…

The first thing to know is ColdFusion comes with an older version of log4j which uses the now depreciated concept of categories, now known as loggers, but for simplicity’s sake, these are the same thing. An instance of one of these represents a logging space which you are free to name and configure at will. It’s advisable to use package naming conventions with loggers, sorry categories, as this is the norm in java. Also worth noting is that loggers are hierarchical, meaning that a logger named ‘myco.foo’ inherits configuration properties from the logger ‘myco’, if it exists. You perform logging through one of the printing methods debug, info, warn, error, fatal. These are directly related to the standard logging levels DEBUG < INFO < WARN < ERROR < FATAL, meaning the level is ascending. A logging method is considered enabled if it is equal to or grater that the current logging level. So if the logging level is set to WARN, myLogger.error(‘Uh oh, big problem occurred’), will output to your log file, but myLogger.info(‘ran method x()’) will not. The last 2 components to logging are patterns, which I’m going to completely skip, and just give you the logging pattern that you’re pretty much gonna use anyway, and appenders, which you output your logging to. Appenders can be a console, file, a socket server, JMS, NT Event Log, and the Unix System Log, you can start to see the incredible flexibility here. All that’s left is to create a config file and start logging!

I like to use a properties file, the format I mentioned when discussing classloaders, but you can also use an xml file. Here’s a sample properties file called logger.properties:

# create a category called myco.foo, set it’s level to INFO, and set the appender to myAppen (you can name this anything, but keep it simple)
log4j.category.myco.foo=INFO, myAppen
# myAppen is set to be a FileAppender.
log4j.appender.myAppen =org.apache.log4j.RollingFileAppender
# we’ll use a standard layout
log4j.appender.myAppen.layout.ConversionPattern=%-4r [%t] %-5p %c - %m%n
# and set the filesize limit and backup file

Now to get log4j running you just need to load this config file. The best place for this is probably in Application.cfm, as apposed to somewhere buried in your code. One thing to note, though. Once log4j is configured, it’s going to be running until you’re cf server/instance is restarted, so if you want to stop logging, you’ll need to remove the configuration code and restart cf. So here’s my Application.cfc:

   if (NOT IsDefined("application.loggerInit")) {
       configurator = CreateObject("java", "org.apache.log4j.PropertyConfigurator");
       application.loggerInit = true;

Just a few things to note. I’m checking to see if if I’ve already initialized log4j, I created a ‘logs’ inside my sampleApps app folder, which contains my logger.properties config file and the samle.log file which will be created, and I’m using absolute path names in Application.cfm and in my config file. You could work around this, but… So now, you’re ready to begin logging! Let’s log a cfc being created. First I’ll retrieve the logger I created from an org.apache.log4j.Category instance and store it so other methods can use it, then use the ‘info’ method to do the logging:

<cfcomponent name="myCFC">
   <cffunction name="init" returntype="myCFC">
       <cfset var category = CreateObject("java", "org.apache.log4j.Category") />
       <cfset variables.logger = category.getInstance('myco.foo') />
       <cfset variables.logger.info('myCfc created") />
       <cfreturn this />

And that’s all there is to it! Sorry about the length of the post, hopefully it’s not too much to consume, but has given you some ideas to get rolling. Happy logging!

introduction to log4j: http://logging.apache.org/log4j/docs/manual.html
log4j PatternLayout Class: http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
ColdFusion Developer's Journal article on log4j: http://cfdj.sys-con.com/read/42122.htm

Friday, September 16, 2005

Replicating Java’s Object.toString() method in CF

Here’s a little trick that may come in handy sooner or later. It’s something I desperately needed today, and was getting frustrated without it. In java if you call toString() on an object it returns the class name and the hex of its memory address. It’s quite handy for debugging things like making sure you're working with a singleton or a new object. But you can’t call toString() on a cfc. So here’s how you can get the same output in cf:

<cfset myObject = CreateObject('component','com.myco.MyObject') />
<cfset system = CreateObject('java','java.lang.System') />
<cfset objString = getMetaData(myObject).name & "@"& FormatBaseN(system.identityHashCode(myObject), 16) />

<cfdump var="#objString#" />

This will output something along the lines of 'com.myco.MyObject@fe029d42'. Just for a little teaser of what’s to come, I really wanted this for logging the creation of new cfcs with log4j. A little tutorial on using log4j with coldfusion is coming next…

Thursday, September 08, 2005

I’ll make the first one a good one!

I said I would write some cool stuff about ColdFusion, right? Well how about I make my first post a good one. I'm currently working with Dave Ross on a really cool project that does some interesting things concerning Mach-ii properties and external configuration files (more on that later). I’m a big mac guy, Dave’s not, so we got into an issue with filepaths, and I suggested maybe loading the config file from the classpath, since the file was really external to the application anyway.

So after I remembered that I was working in coldfusion instead of java, I came up with a cool solution, with ended up using a bit of java. A little backround info is needed to understand how this is done. Whenever you write a cfc or cfm file (or udf), cf compiles the code into a type of java class file, which is basically a normal java object. Since it is a java object you can actually use methods from the base java objects, Object and Class When you run your app, that class is loaded into the jvm that coldfusion is using through a ClassLoader, which you can obtain from the cfc, through base java objects. Before I get too far, here’s a simple example of calling a method from a cfc’s base java objects to show the type of object it is:

<cfcomponent name="test2.cfc">
   <cffunction name="dumpStuff" access="public" returntype="any">
       <cfdump var="#getClass().getName()#" />

Kind of cool, because getClass() is a method of java’s Object class and getName() is from the Class (that’s its name) that it returns. So going back loading files, Class has a method getClassLoader() which will return the ClassLoader I mentioned that was used to load that object into the JVM. Why do you want this? Well a ClassLoader can be used to load more that just classes, and the cool thing is it searches through a classpath to find what it’s looking for, which is configured from outside of your application, through CFAdministrator, or Jrun Admin, or through Tomcat, or a .profile file or whatever. And that makes it a very portable way to load things!

Ok, I have a feeling your still wondering why you would want to do this. Remember how I said that Dave was loading things into Mach-ii properties from a config file? Well here’s how and then maybe a little why later. This relies on another Java class, java.util.Properties, that reads a plain text file as key/value pairs and loads them into a similar construct as a cf struct, and even though this sounds like a lot of work, it’s surprisingly easy. We’ll do this in a plugin and have it happen as soon as the app starts up, so first a properties file, I’ll call it ‘myprops.properties’, it looks like this:


Now the plugin, with some comments:

<cfcomponent extends="MachII.framework.plugin">

<cffunction name="configure">

   <!--- Java Properties object --->
   <cfset var props = createObject("java","java.util.Properties")/>
   <cfset var propNames = 0/>
   <cfset var prop = 0 />
   <cfset var p = 0 />

   <!--- You would probably want this set elsewhere! --->
   <cfset var propFileName = “myprops.properties “ />
   <cfset var classPathResource = 0 />

   <!--- here we’ll use use a method of ClassLoader to open an InputStream on the property file and tell the Properties object to load it --->

   <cfset classPathResource = getClass().getClassLoader().getResourceAsStream(propFileName)/>

   <cfset props.load(classPathResource)/>

   <!--- now we just use methods from the Properties object to read the values and put them in the Mach-ii property manager using the key names --->

   <cfset propNames = props.keySet().toArray()/>

   <cfloop from="1" to="#arraylen(propNames)#" index="p">
       <cfset prop = propNames[p] />
       <cfset setProperty(prop,props.get(prop))/>



Since this happens as soon as the plugin is loaded, you have those properties available at application startup, and you now have application properties that are configurable from outside of the Mach-ii conf file! Cool, huh? More stuff to come soon…

Testing 1,2,3...

Is this thing on? I just flew in from Philly and boy are my arms tired! No really, but...

I've got a lot of things to tell you but I'm running short on time. I promise to write a whole lot about Cold Fusion, Java, and Flash, and probably some senseless information about raisin my kids, driving my bike, and I don't know, brewing beer or something. Check back, you'll see...