Lately I've been working on a project that uses ColdSpring to generate Remote Proxies on one web server, and some code to consume them as web services from a remote machine. Last night I got an AXIS error that looks pretty common when developing web services:
AXIS error
Sorry, something seems to have gone wrong... here are the details:
Fault - Error attempting to create Java skeleton for CFC web service.; nested exception is:
coldfusion.xml.rpc.CFCInvocationException: [coldfusion.xml.rpc.SkeletonClassLoader$UnresolvedCFCDataTypeException : Cannot resolve CFC datatype: Datasource.]`
Googling seemed most frequently to indicate that there was an issue with a ColdFusion Mapping for "/", which we don't have. My next thought was an issue with the cached web service stub; so I had my admin clear the stubs folder and restart the services, but that didn't fix it either.
Next we looked at the displayName attribute of the generated proxies, as this can sometimes cause problems with web services. We didn't change anything with the displayName, because while we were looking at it, we realized that the CFC datatype mentioned in the error actually was a piece of useful information (usually with this error, it is not). In our case, the component being proxied extends another component, and re-implements some, but not all, of its methods.
While adding more methods to the web service, I got tired of adding them one by one to the ColdSpring config remoteMethodNames property, so I switched to using a star and planned to go back and lock it down when I was done. I didn't realize it at the time because multiple changes took place at once, but this is ultimately what caused the problem.
The parent class of the component being proxied contained an init method, which until the remoteMethodNames property was set to "*" was not being exposed. Once it was being exposed, AXIS attempted to resolve the data types of all of the methods to build the WSDL, and a relative-path, "Datasource" was being used as an argument type. Since my CFC lives in a totally separate folder, the relative path doesn't resolve correctly and Datasource.cfc can't be found; hence the error.
There are a couple of ways to fix this:
Get rid of the "*" and go back to listing each method to expose individually.
Update the parent code to use the fully absolute path instead of relative paths.
Subclass the init() method and provide the absolute path of the data type being expected.2.
Option 2 sounds like a good idea, until you realize that it means making multiple changes all throughout the application (switching relative paths to absolute) for consistency, and then testing all of the applications that make use of this code, which is not an insignificant task.
Option 3 is easy and lazy, which is how we tested our hypothesis, but not good or clean code. I would cringe if I had to maintain someone else's code and found this, so I won't leave it behind for my successor either.
That just leaves option 1. I guess I don't get to be lazy today.
I had some information ready to be posted here when I submitted my entry into Ray's Best of CF9 contest, but he covers it pretty well in his review post; and he was kind enough to host the video on his S3 account. I've also posted the video on my Vimeo account, so here it is again for reference:
You can download the source code here. Unfortunately, I haven't found any more time to continue working on this; and I have to admit that as cool as the CFaaS feature is, I'm not terribly motivated to go further with this mail client because I know it will eventually get canned. Why write a mail client when you use Outlook every day?
So it was a fun way to play with Flex 4, the latest Swiz build at the time, AIR, and CFaaS; but I don't think I'll bother continuing to mess with it.
I'm betting that Sean Corfield doesn't need me to evangelize his software to garner attention for it. I'm a relative nobody -- standing in his shadow, so to speak. But it's good, so I feel compelled to share my experience with you.
Disclaimer
I should start by saying that I am generally pro-framework. They aren't a silver bullet, and each tries to solve some set of common problems in varying ways, so each has its place; but for larger projects, or projects written collaboratively by a larger team, or projects that plan on having a long life-span requiring some level of maintenance, I've found front controller frameworks to be quite useful. Not only that, but specialty frameworks like ColdSpring and Swiz have been incredibly useful and eye-opening to me. I suspect that Transfer would be on that list too, if I'd had time to learn it yet.
So, if you're anti-framework, you may not agree with my reasoning. Or, for that matter, depending on your reasons for being anti-framework, you may really agree with me a lot.
Introduction
FW/1 is a front controller framework whose primary strength, in my opinion, is its simplicity. Too often, framework authors (or authoring teams) get swept up in features that only a percentage of the framework users will use, causing needless bloat for the remaining users. FW/1 seeks to obliterate bloat, and I think it succeeds masterfully.
Why I Love It
I won't drone on and on about how it works. Some documentation is available (and getting better all the time), and the framework itself is only 626 lines of code as of this morning's release -- most of it well commented -- so if nothing else, you can look at the source to figure things out. But what I will tell you is why I love it.
Due to feature bloat, many other frameworks load lots of extra objects (CFC's) and we have to face facts: Although leaps and bounds have been made in improving object instantiation time with ColdFusion 8 and again with ColdFusion 9, it's still a noticeable detriment to the page load time for the user that spins up the application for the first time since it timed out; and that time scales up with the size and complexity of your application. More events means more config, which means more load time -- even if it's spread throughout the application life cycle with lazy loading. To put it bluntly: things are getting better, but they're just not quite there yet. (I'm told Railo has excellent object instantiation times, but don't have any experience to draw on.)
Server.cfc, added in ColdFusion 9, will give us a way to spin up the application before the first user accesses a page, but what it doesn't do is keep the application from timing out. That may not be a problem for a site with hundreds of thousands of users, but for a start-up company, or even just a simple blog application that makes use of a framework, that load time after application timeout can be so freaking annoying. Even though I consider myself pro-framework, that load time is what I would consider my number one complaint about the front controller frameworks I've worked with. On nice hardware with lots of memory and a fast CPU, it may not matter much, but for an independent developer on shared hosting it can be a nightmare. In the past I've written scheduled jobs from two different servers to ping each other and keep the applications from timing out, but that is far from ideal.
All of this griping has just been to make the point of how awesome FW/1's simplicity is. It's 1 object: Application.cfc. For cleanliness and separation purposes, it's written as a base class from which you extend your application's Application.cfc, but for all intents and purposes, you could rename Framework.cfc to Application.cfc and run your application along side it with a few lines of configuration. That's it. When my application starts, it just starts.
Speed is a feature, and FW/1 nails it. In addition, I'm in love with its simplicity. If something's not working quite right -- or as is more often the case, if I've misunderstood the order that things run -- I can dive right into the code of the framework and figure out why I'm getting an error within a few minutes. There are no sprawling api methods to keep track of; only one data construct: "rc" (request context) which passes form, url, and service-result data between the controller and the view.
No XML. None. Nada. Zilch. I had at one point entertained the idea of writing a Model-Glue plugin, or fork, that would allow configuration to be specified as CFML or as JSON, but I never got around to trying it. Now, with FW/1, I don't have to write any XML.
I've yet to explore the layouts feature, but I know I will, and I'll be happy to have it. I know it can optionally integrate with ColdSpring, and I'm happy about that. And, with a few minor exceptions, that's about all it does. And I'm thrilled about that.
Congratulations to Chris Scott -- manager of the Philadelphia CFUG, and project lead for ColdSpring -- and the rest of the ColdSpring team. Looks like a job well done!