|
My blogger code: B6 d++ t++ k s u-- f i++ o+ x- e+ l+ c-- (decode it!) |
Viewing by Category: Tardis / Main
November 8, 2007
Tardis Hotfix: Curse of the getPageContext.forward()
Came across a bug in Tardis today in how getPageContext.forward() responds (or doesn't respond) to a multipart-type form. For some reason the forward wouldn't happen and wouldn't throw an error when the form type was set to accept uploads. I also discovered that if you did a page refresh after a form submission and forward() it would do a double submit. Ouch. Obviously this is an undesirable situation, and I'm surprised that I didn't catch it a long time ago.
The solution was to remove the dispatchView() call at the end of the manager and instead just setServiceMessage() with the status of the action. I then added a new method to the frontcontroller.cfc (dispatchViewMP()) which uses a cflocation instead of a getPageContext.forward(). Next was modifiying index.cfm to getServiceMessage() and do a dispatchViewMP() for form submissions. The last change was to add several new view definitions to the viewManager section of controller-config.xml and change the pathing of the userManager section entries to refer to those new view definitions.
The crux of the change is that after a form has been submitted and done something it does a cflocation to the path defined in the controller config file, which is index.cfm with a view state. Then it does a getPageContext.forward() to get the view requested. So it turns out to be a double redirect, first a client side redirect, then a server side redirect. A little bit less than desirable, but solves both of the issues and performance impact is negligible. I'll continue to look for a different solution.
If you are already using Tardis, these changes will require attention because the dispatching change will make apps behave in an unexpected manner. Making the retrofit for your apps should be quite simple and painless. Drop in the latest copy of the framework code, the updated index.cfm from the sample app, and modify your pathing in the controller-config.xml (as demonstrated in the sample configs).
Changes to the framework and sample app.
Framework:Modified frontcontroller.cfc - added dispatchViewMP() method
Sample app:Changed userManager.cfc to setServiceMessage for all calls instead of doing dispatchView at the end of manager run Changed index.cfm to getServiceMessage() for form submissions return status and call dispatchViewMP() Changed controller-config.xml to reflect updated pathing for manager success pages
Caveat Emptor: This code is still in testing. Please let me know if you run across any issues
The solution was to remove the dispatchView() call at the end of the manager and instead just setServiceMessage() with the status of the action. I then added a new method to the frontcontroller.cfc (dispatchViewMP()) which uses a cflocation instead of a getPageContext.forward(). Next was modifiying index.cfm to getServiceMessage() and do a dispatchViewMP() for form submissions. The last change was to add several new view definitions to the viewManager section of controller-config.xml and change the pathing of the userManager section entries to refer to those new view definitions.
The crux of the change is that after a form has been submitted and done something it does a cflocation to the path defined in the controller config file, which is index.cfm with a view state. Then it does a getPageContext.forward() to get the view requested. So it turns out to be a double redirect, first a client side redirect, then a server side redirect. A little bit less than desirable, but solves both of the issues and performance impact is negligible. I'll continue to look for a different solution.
If you are already using Tardis, these changes will require attention because the dispatching change will make apps behave in an unexpected manner. Making the retrofit for your apps should be quite simple and painless. Drop in the latest copy of the framework code, the updated index.cfm from the sample app, and modify your pathing in the controller-config.xml (as demonstrated in the sample configs).
Changes to the framework and sample app.
Framework:
Sample app:
Caveat Emptor: This code is still in testing. Please let me know if you run across any issues
May 23, 2007
Tardis Update: Path & Scope Changes
Made some more changes to Tardis today to remedy some things that had been bugging me. First, I shortened the pathing to the framework pieces and updated the sample to reflect that. Second, I changed the sample app to instantiate the framework pieces into the application scope instead of the session. I had to modify the datastore.cfc from the framework to support this change.
If you are already using Tardis, these changes will require attention because the pathing change will break existing apps. Making the retrofit for your apps should be quite simple and painless.
The instantiation changes will allow you to put the framework pieces in either the session, or the application (application would be preferable).
Changes to the framework and sample app.
Framework:Modified pathing (shortened path to components) Modified datastore so that it could be instantiated in application scope
Sample app:Changed sample to reflect pathing changes Changed instantiation of framework components from session to application
Caveat Emptor: This code is still in testing.
If you are already using Tardis, these changes will require attention because the pathing change will break existing apps. Making the retrofit for your apps should be quite simple and painless.
The instantiation changes will allow you to put the framework pieces in either the session, or the application (application would be preferable).
Changes to the framework and sample app.
Framework:
Sample app:
Caveat Emptor: This code is still in testing.
May 22, 2007
Tardis: Sum of the parts?
Something I haven't really mentioned about Tardis is that you don't have to use the whole thing. Most of the pieces would easily stand on their own, as I've been careful not to create dependencies within them on other pieces (loose coupling).
For example, if you liked the security, validation or logging components you can use them without the rest of the framework. So if the Tardis method of control isn't your cup of tea, and perhaps Mach-ii or Model-Glue are, you can use aspects from Tardis without using the whole thing.
For example, if you liked the security, validation or logging components you can use them without the rest of the framework. So if the Tardis method of control isn't your cup of tea, and perhaps Mach-ii or Model-Glue are, you can use aspects from Tardis without using the whole thing.
May 22, 2007
Tardis Update: Declarative Logging/Notification
Tardis has been pretty static for awhile, but I'd been mulling around adding a logging/notification component for awhile.
It might not be readily apparent why a component like this might be useful (why not just use cflog?), but what you get out of it is the ability to send email notifications when a log threshold is met (fatal errors) that is configurable, and the ability to extend the logger to do more than write to a cflog file (things like a centralized logging service). That way you can change the entire logging behavior without touching code all over the place.
I haven't updated the documentation, but will soon.
Changes to the framework and sample app.
Framework:Created logger.cfc to include declarative logging/notification
Sample app:Changed sample to demonstrate use of logger component
Caveat Emptor: This code is still in testing.
It might not be readily apparent why a component like this might be useful (why not just use cflog?), but what you get out of it is the ability to send email notifications when a log threshold is met (fatal errors) that is configurable, and the ability to extend the logger to do more than write to a cflog file (things like a centralized logging service). That way you can change the entire logging behavior without touching code all over the place.
I haven't updated the documentation, but will soon.
Changes to the framework and sample app.
Framework:
Sample app:
Caveat Emptor: This code is still in testing.
May 8, 2006
Tardis Update: Updated Sample App
Made some changes to the Tardis sample application to make it a bit more meaningful and give some better ideas about model implementation. First, I added a simple (MS Access) database so that the data access examples were more realistic. Second I changed the model to use Data Access Objects (DAO) and Value Objects (VO's). Other names for a VO are Transfer Objects (newer name used by Sun) or Beans (what some in the CF community call them). When I learned the J2EE patterns they were called VO's, so that's what I still refer to them as. Call them what you like, they'll still work the same way. You can get the updated code from the updated link in my "LINKS" pod.
April 11, 2006
Tardis Updates: Documentation
Got around to making an initial stab at documenting Tardis. Between the docs and the reference application (tardis_sampleapp), a developer should be able to start using the framework. I plan on doing updates to the docs, but really wanted to get something out here in case someone needed help getting started.
Once again, any feedback would be greatly appreciated.
Developer Presentation
Documentation (in-progress)
Framework Code
Sample Implementation
Base Doc
Controller Doc
Datastore Doc
Security Doc
Validation Doc
Logger Doc
Once again, any feedback would be greatly appreciated.
Developer Presentation
Documentation (in-progress)
Framework Code
Sample Implementation
Base Doc
Controller Doc
Datastore Doc
Security Doc
Validation Doc
Logger Doc
March 30, 2006
Tardis Updates: Tardis 1.0
After a month or so of development and several months of tesing and app building, Tardis is mature enough to go 1.0. I've written two full applications in it without having to modify any base code, so it is quite stable. So now the only caveat is that I haven't documented everything (other than the reference sample application). The docs are on my long to-do list. Feel free to download Tardis and pass back any comments or ideas that you might have.
January 31, 2006
Tardis Updates: Declarative Input Validation Updates
Haven't had any updates in awhile with the holidays, travel and other things, so it was due time. I'd had some enhancement ideas bouncing around in my head for quite some time and here they are. I'm still lacking in full documentation and testers, but that will come in time...
Modified base.cfc to parse deeper xml files Updated validation.cfc to include declarative input validation fields
Sample app:Changed sample to demonstrate declarative input field validation
Caveat Emptor: This code is still in testing.
Changes to the framework and sample app.
Framework:
Sample app:
Caveat Emptor: This code is still in testing.
November 16, 2005
Tardis Updates: Declarative Input Validation
Changes to the framework and sample app.
Framework:Created base.cfc which all other framework CFC's extend containing base methods Modified all framework CFC's to extend base.cfc Updated datastore.cfc to include declarative input validation methods
Sample app:Changed sample to demonstrate automatic input validation
Caveat Emptor: This code is still in testing.
Framework:
Sample app:
Caveat Emptor: This code is still in testing.
November 10, 2005
Tardis Updates: Sample App - App-specific Framework Extensions
Made a quick change to the sample application to demonstrate application specific extension of the security and validation CFC's through inheiritance.
Caveat Emptor: This code is still in testing.
November 3, 2005
Tardis Updates
Made some updates to the framework pieces and sample apps, mainly commenting and documentation, but a few subtle changes to code as well. Change the init methods in all components to return the instance, allowing for inline instantiation and intialization using CreateObject rather than using then following with an init call. Have also generated the component Javadoc. Formal documentation and a full presentation will be available soon. I'm waiting for the code to be almost 100% stable before writing all of the formalized documentation.
Caveat Emptor: This code is still in testing.
October 28, 2005
Tardis Update: Declarative Validation
Added a new feature to Tardis today, declarative validation. This allows for adding and changing validation algorithms without changing code. The algorithms are stored as regex in an XML file and applied at runtime.
Caveat Emptor: This code is still in testing.
Caveat Emptor: This code is still in testing.
Now that you can learn so much about computer science online teaching yourself how to program keeps getting easier.
October 25, 2005
Tardis Update: FlexProxy
After attending MAX and getting excited about Flex, I've made updates to the Tardis sample application to include an example of how to use the framework with a Flex application using a FlexProxy component.
Caveat Emptor: This code is still in testing.
Caveat Emptor: This code is still in testing.
October 14, 2005
MVCF-CF Reloaded -> Tardis
Shortly after the first release of CFMX (6.0) in 2002 I developed a reusable CF component-based (CFC) MVC Framework called MVCF-CF. At the time there were no CFC-based frameworks of any kind available. Those were still the days of Fusebox, when most CF developers might have thought MVC was a dubbed Japanese game show on SpikeTV;)
Once it was fully tested and refined, it became the basis of all my development and I started putting together documentation suitable for public consumption. Putting your code & ideas out for public critique or ridicule is kind of scary (especially the first time you do it, kind of like blogging), so it took me until August of 2004 to take the leap (grow some balls). By that time there were a couple of other MVC frameworks out there (Mach-II, etc), but I was far enough down my own path that it wasn't worth looking into a course change. Since the code was stable there didn't seem to be much reason to mess with something which worked, so there were no features added (1 bugfix) since then.
MVCF-CF was originally inspired by Struts (and the ideas of Benoit Hediard), but I'd never actually used that code, nor trained on it, so it was more conceptual inspiration rather than functional. Since the 2004 release I attended some classes on JSP & Servlet (with Struts) and EJB, which gave me some ideas for a feature-add release to the framework. I filed away those ideas for a day when I actually had time to work on them.
That day has finally come... welcome Tardis.
About the name change...
Why not MVCF-CF 2? Now that there were some other frameworks out there (Mach-II, Tartan, model-glue, ColdSpring) I needed to come up with a different name for a couple of reasons. First, MVCF-CF is not really an accurate description of the framework since there are no functional model (M) or view (V) components, it was actually just a controller (C) layer (like Struts). There were ideas of how to implement the model (M) and view (V), but they weren't codified. I left it up to the end developer to either follow my ideas or use another framework for the model. Since there are such great model frameworks out there, I have not changed my approach. Second, MVCF-CF is a quite boring name that people wouldn't be inclined to remember, nor invoke any kind of symbolic ideas. So after time and thought I picked Tardis. For those that aren't sci-fi dorks (like me), Tardis is the vehicle of Dr. Who from the BBC program. Without getting too far into the geeky details, Dr. Who is a Time Lord who uses the Tardis (Time And Relative Dimensions In Space) to run around time and the universe helping those in need. Since frameworks are supposed to save development time, I thought Tardis worked.
About the new features...
First, one of the (only) complaints that I got about MVCF-CF was that each application had a copy of the framework code. That meant for later releases (or bugfixes) you had to move it out to multiple locations, creating a maintenance headaches. With Tardis there is one copy of the code per server. Applications will instantiate the framework from base code CFC's.
Second, I tried (and am still working on) to make the code comply with the Macromedia style guides for syntax and have removed all CFSCRIPT blocks, opting for tag syntax instead. I think that CFSCRIPT was added to placate developers from other languages who didn't like tags. As a former C/C++ developer (and now Java) I've always considered tags to be somewhat inelegant, but over time have come to appreciate them. Tag syntax represents what CF was originally about (simplicity, RAD), so I decided to go back to old-school CFML code-foo.
Third, I have added declarative (XML file-based) security for the views and controller gestures. Declarative security allows for you to configure permission to views and actions outside of your application code (like EJB's). So if you decide that a certain view or gesture needs to have more or less permissions, you just change an XML file without touching code.
Fourth, in addition to the controller handling form submissions (methods) it how handles view dispatch. All URL's in the application point to index.cfm (not dissimilar to FuseBox) with the action you want to take. The difference is that rather than a huge switch-case it relies on the controller component to dispatch the requested view.
Fifth, the datastore which transforms/holds form and error data has been modified. From seeing how others (and myself) implemented the framework I found that the error storage and retrieval wasn't being used like I originally intended. My hope is that these changes will make it more useful (and used).
Finally, all CFLOCATION's have been replaced with getPageContext().forward(). I've never been a fan of CFLOCATION as it is a client-side redirect which goes to a visible url. getPageContext().forward() is a real server-side redirect.
Feel free to download the code and forward any comments or ideas. I have not finished commenting the code, nor started revising the documentation, so feel free to pop me any questions before then. When I've shaken things out, commented the code and revised the documentation I'll update the files and make it a full release.
Caveat Emptor: This code is still in testing.
Once it was fully tested and refined, it became the basis of all my development and I started putting together documentation suitable for public consumption. Putting your code & ideas out for public critique or ridicule is kind of scary (especially the first time you do it, kind of like blogging), so it took me until August of 2004 to take the leap (grow some balls). By that time there were a couple of other MVC frameworks out there (Mach-II, etc), but I was far enough down my own path that it wasn't worth looking into a course change. Since the code was stable there didn't seem to be much reason to mess with something which worked, so there were no features added (1 bugfix) since then.
MVCF-CF was originally inspired by Struts (and the ideas of Benoit Hediard), but I'd never actually used that code, nor trained on it, so it was more conceptual inspiration rather than functional. Since the 2004 release I attended some classes on JSP & Servlet (with Struts) and EJB, which gave me some ideas for a feature-add release to the framework. I filed away those ideas for a day when I actually had time to work on them.
That day has finally come... welcome Tardis.
About the name change...
Why not MVCF-CF 2? Now that there were some other frameworks out there (Mach-II, Tartan, model-glue, ColdSpring) I needed to come up with a different name for a couple of reasons. First, MVCF-CF is not really an accurate description of the framework since there are no functional model (M) or view (V) components, it was actually just a controller (C) layer (like Struts). There were ideas of how to implement the model (M) and view (V), but they weren't codified. I left it up to the end developer to either follow my ideas or use another framework for the model. Since there are such great model frameworks out there, I have not changed my approach. Second, MVCF-CF is a quite boring name that people wouldn't be inclined to remember, nor invoke any kind of symbolic ideas. So after time and thought I picked Tardis. For those that aren't sci-fi dorks (like me), Tardis is the vehicle of Dr. Who from the BBC program. Without getting too far into the geeky details, Dr. Who is a Time Lord who uses the Tardis (Time And Relative Dimensions In Space) to run around time and the universe helping those in need. Since frameworks are supposed to save development time, I thought Tardis worked.
About the new features...
First, one of the (only) complaints that I got about MVCF-CF was that each application had a copy of the framework code. That meant for later releases (or bugfixes) you had to move it out to multiple locations, creating a maintenance headaches. With Tardis there is one copy of the code per server. Applications will instantiate the framework from base code CFC's.
Second, I tried (and am still working on) to make the code comply with the Macromedia style guides for syntax and have removed all CFSCRIPT blocks, opting for tag syntax instead. I think that CFSCRIPT was added to placate developers from other languages who didn't like tags. As a former C/C++ developer (and now Java) I've always considered tags to be somewhat inelegant, but over time have come to appreciate them. Tag syntax represents what CF was originally about (simplicity, RAD), so I decided to go back to old-school CFML code-foo.
Third, I have added declarative (XML file-based) security for the views and controller gestures. Declarative security allows for you to configure permission to views and actions outside of your application code (like EJB's). So if you decide that a certain view or gesture needs to have more or less permissions, you just change an XML file without touching code.
Fourth, in addition to the controller handling form submissions (methods) it how handles view dispatch. All URL's in the application point to index.cfm (not dissimilar to FuseBox) with the action you want to take. The difference is that rather than a huge switch-case it relies on the controller component to dispatch the requested view.
Fifth, the datastore which transforms/holds form and error data has been modified. From seeing how others (and myself) implemented the framework I found that the error storage and retrieval wasn't being used like I originally intended. My hope is that these changes will make it more useful (and used).
Finally, all CFLOCATION's have been replaced with getPageContext().forward(). I've never been a fan of CFLOCATION as it is a client-side redirect which goes to a visible url. getPageContext().forward() is a real server-side redirect.
Feel free to download the code and forward any comments or ideas. I have not finished commenting the code, nor started revising the documentation, so feel free to pop me any questions before then. When I've shaken things out, commented the code and revised the documentation I'll update the files and make it a full release.
Caveat Emptor: This code is still in testing.


















BTW, I could have sent this by email but since I don't see any other comments in all your blog entries, I thought I'd do this to help confirm that the comments are indeed working. Would be a shame if people have been trying to send feedback and you've not gotten it for some reason.
(If you read the flashpaper document above, you'll see the last slide offers "how do I get started". I'd like to share a couple more points for those steps.)
First, if you drop the sample application into your server (or try to use it as a base for new ones), there are a couple more steps than are listed on that page.
Unless you happen to drop the app into a directory called d:/apps/cfapps/, you'll need to modify the 2 files that refer to that: Application.cfc and system/config/application-config.xml. (So if you're deploying it into your c:\inetpub\wwwroot, you'll have a couple of places where you'd change from d:/apps/cfapps/tardis_sampleapp to c:\inetpub\wwwroot\tardis_sampleapp\, and so on).
Of course, in the Application.cfc, that could be changed to be dynamically self-referencing by changing it to use the ExpandPath function. The XML file, however, does need to be hard-coded.
Second: the application-config.xml file has a reference to <virtualpath>/tardis/</virtualpath> (or if these comments would fail to recognize tags, how about <code><virtualpath>/tardis/</virtualpath></code>?). That should be changed, for running the example as /tardis_sampleapp, to /tardis_sampleapp. Same for the system/config/controller-config.xml.
And unfortunately, since many of these settings are set into the application or session scopes (as loaded from the config files), so if you don't realize this until after you've started running the app, you'll need to cause the session or application to be reloaded. You may be able to resolve this by manually running the onsessionstart or onapplicationstart methods, or if on a development box, it may just be more expedient to just restart your CF server.
Third, with the 1.1 version, folks should note that they need to define a datasource (tardis_sampleapp) pointing to the tardis_sampleapp\db\tardis_sampleDB.mdb
Finally, if one happens to read this blog entry, don't use the link here for the sample app (version 1.0), but rather get the sample app as linked on the left (currently version 1.1). All the info above applies to either version, but after getting the 1.0 sample running, its interface just isn't too obvious. Shawn updated that in his May 8 2006 entry.