Playing with Stub Pages
Page.Title = "History";
Page.Name = "history";
Page.SectionName="About Us";
Page.SectionName="about-us";
Page.FilePath = "about-us/history";
Page.Feature = "PageDisplay";
etc. . . .
<cfscript>
<cfinclude template="/index.cfm">
Originally, page stubs were just a way to avoid problems I was having getting URL rewriting to work on IIS back in 2001/2002, but now as I revisit them, I see them as a potentially interesting way of decoupling the process of generating URLs from the process of consuming them . . .
When you just want one page for each record in your database, there is no real reason to use page stubs (other than as a backup if you can't get ISAPIRewrite to work!). Just use URL rewriting to turn /a/b/c.html into index.cfm?filepath=a/b/c and then Page = PageService.getPagebyFilePath(filepath).
However, what happens if you want your catalog feature to be able to generate URLs for each category and product or your events feature to be able to create URLs for every event? As you end up with n-features - potentially written by a number of different developers, getting the URL rewriting to map a URL to the appropriate resource could get pretty hairy and you'd have to have some kind of lookup for each object supporting filepath based access. You could use a RESTful approach, but that is a technical convention that doesn't always meet the needs of users to have the new product available at /new-category/special-subcategory/new-product.name.html rather than at just products/new-product-name.html.
By using page stubs, all you do is write a page stub generator for each feature that requires one (if it has multiple pages that each need to appear like a different html file - if you only need query string parameters to access a resource in that feature then this is not relevant). They all extend a core stub generator so general conventions like the file extension and the properties and formatting of a page stub is controlled in a single place (BasePageStubPublisher) making it easy to modify as the properties describing a page change over time. You define a page in such a way to support the setting of certain properties if they haven't been set via URL or form (so you can pass a Catalog feature a product ID and a screen type to use, for example) so that many URLs can easily call the same feature but with different default properties (so /new-category/special-subcategory/new-product.name.html becomes equivalent to index.cfm?page=catalog&action=productdetail&CategoryID=12&ProductID=712).
There are definitely downsides to this approach, but I have a bunch of sites using the basic principle (I think I started doing this about five years ago) and I think this is powerful enough to be worth spending an hour or two writing some simple generators for core pages and the catalog feature to see how well it works out.
Thoughts?



What do you think? Good or bad :->
From my experiments and understandings this type of url index.cfm?page=catalog&action=productdetail&CategoryID=12&ProductID=712 gets hated on by search engines. Plus it is just plain ugly.
Actually, URL rewriting and a big URI lookup table would actually be kind of cool. I would then be able to get the various feature publishers to publish to a database containing all of the possible URIs, although for large, highly trafficked sites, the page stubs would probably perform better.
Hmmmm. I think I'll start with page stub generator and eventually could provide both as options . . .
I guess I see performance and caching as a secondary strategy. I'd rather have a very flexible front controller that can do anything and then add a bunch of caching optimizations (whether to disk or to memory - whether on the same server or to offload static requests) as a layer on top. Once I can do anything, it is fairly easy to do a subset of those things more efficiently.
It is a good point though. Initially the core of this is really just a way to provide a lot of flexibility in terms of URLs (which are the external, unchanging interface to the apps that are built). There is no question that I could provide different versions of the system with higher levels of static file caching. In fact that is a really good point. I'll look at this as the start of a static caching system that could be extended rather than seeing it as fundamentally limited to just setting some properties.
Really good point - many thanks (as always) for the input!
Coooool!
I have actually used this method very recently for a client who wanted search engine friendly URLs. Having an include makes it so much easier come maintenance time.
Many thanks for the comment!
I'm probably actually about to embark on a massive URL inventory of the site to remove as many explicit fuseaction calls as possible and replace them with named pages that simply set that fuseaction. I'm hoping this will cut down on some of the URL redundancy that we've been noticing as search engines crawl our site (i.e. /collections/index.cfm/fuseaction/Items.ViewImages vs /collections/digitalcollections/searchimages/index.cfm/fuseaction/Items.ViewImages).
As far as Joshua's comments go, am I wrong in thinking that he's suggesting you generate the whole page (content and all) when you generate the stub? For us, this is out of the question, as we would constantly have to regenerate the stubs as functionality changed. An include is a massively intuitive way to call your controller once you've set the basic parameters of what your page is supposed to do.
In our case, all the stub file sets is the ID of the page. That way, the title, heading, section information, etc. can all be pulled as needed from the database. The page ID itself doesn't change, but the other information can, so we don't need to regenerate the stub every time the page is edited. This probably adds a little bit of overhead, but with a little query caching, the site runs relatively fast. A caveat -- if you visit now, it will have less than stellar speed, because we're still trying to optimize the image database. I
Thanks for the comment! Sounds like you do almost exactly what we do. For more details on how I'm re-implementing this for LightBase, check out http://www.pbell.com/index.cfm/2007/2/22/URIs-in-L...
I'm also only putting ID's (actually filepaths so it wouldn't change much if we went to URL rewriting instead of page stubs) plus a little more info if necessary such as category and page ID's to jump "deep" into a page. I also am OK with performance hit of having to look up the rest of the page data - at least for first time around.
I get where Joshua is coming from and may look at overwriting my page stubs with static files for cases where there isn't anything dynamic on those pages, but usually I have a lot of dynamic stuff happening, so that's for version 1.5!
Nice to hear other people doing the same things!
Stub pages are safe and effective in all page-based languages such as ASP, JSP and PHP. Because they're cheap to compile, they can support very high performance, particularly in non-db or db-optional architectures.