Login

Stateless Sitemap in Seaside

Originally I generated the sitemap for onsmalltalk as a file on disk and let Apache serve it up. There's nothing wrong with this approach but it'd be cooler if I had Seaside generate and render it on demand and serve as a good excuse to talk about serving up content statelessly in Seaside.

Seaside is a session based web framework, but there's nothing really session specific about a sitemap and I really don't want a new session created when a request for a sitemap is made. There's a lot of overhead in doing that and sometimes you just want to serve up stuff statelessly. When a request comes in, the application mounted on the base URL handles the request by plucking the session id out of the cookie or the URL and either creates a new session or finds the existing one needed to handle the current request. Once found, the request is pumped through the current session which runs through a similar procedure looking for a continuation to invoke.

Since I want to avoid all that and just handle the request at the application level I'll override #handleRequest: in my custom WAApplication subclass, check the URL of the current request and either render the sitemap and end the request by immediately returning a response, or allow processing to continue normally into the session lookup done by the call to super.

handleRequest: aRequest 
    (aRequest url endsWith: '/sitemap.xml') ifTrue: 
        [ ^WAResponse new
              beXML;
              cacheFor: 1 hour;
              contents: (self siteMapFrom: aRequest) asString readStream;
              yourself ]
    ^super handleRequest: aRequest

siteMapFrom: aRequest 
    ^ (SBSiteMapGenerator blogRoot: ('http://{1}/' format: {  (aRequest host)  })) 
        generateFromItems: {  (SBPost new)  } , (SBBlog onSmalltalk publicPosts) , SBTag findAll.

If you have things in your application that can be done statelessly, this is a good place to hook into the framework and take care of that stuff at the application level. Sometimes you don't need all that fancy Seaside stuff and you just want to work directly with HTTP requests and responses.

Two small methods and the sitemap is now generated dynamically, and statelessly directly from Seaside, removing the need to manually invoke the sitemap generation as I had previously been doing to the file system.

Oh, one small extension that I've put on WAResponse and use occasionally...

cacheFor: aDuration 
    self headerAt: 'Expires' put: (TimeStamp now + aDuration) httpFormat

Comments (automatically disabled after 1 year)

Cédrick 5735 days ago

cacheFor: is present in seaside 2.9.

Maybe you should put the version of seaside next to the tag... so you'll have "seaside 2.8" "seaside 2.9" and as it's turtle all the way down ;), you can even have a super tag "seaside" that'll collect all versions...

I hope you'll try 2.9 soon. I find there are plenty of improvments and I'd love to hear from you on them. Not sure but I think in 2.9, one should use WADocumentHandler to manage sitemaps.

Cheers

Ramon Leon 5734 days ago

Interesting, didn't know that was in 2.9, but cool. I probably won't get into 2.9 until it's closer to release, I just don't have the time since my production apps are on 2.8 and the travel season is ramping up.

I'll probably spend most of the summer tweaking the shit out of my app in 2.8 to handle the load which it'll get that'll be quadruple what it had last year at a minimum.

Mike Stramba 5732 days ago

Hi Ramon,

way off topic, but re: your 'blog in 15 minutes' post.

I just watched it and created the blog.

When I add a comment, the comment author name is not captured. The comment setup looks to me to be just about the same as the blog title / body code.

I don't see in the code where the individual form fields get stored to the ordered collection.

Is it something that Magritte does internally ?

Mike

Ramon Leon 5732 days ago

What ordered collection? If I recall that editor is bound to a biz object directly so the form updates the objects instance variables.

Mike Stramba 5732 days ago

Never mind, I found the error, a simple typo on my part ;)

But you did use an ordered collection ... :) (watch your video :)

Mike

Ramon Leon 5732 days ago

I used an OrderedCollection to hold the posts, sure, I knew that, but you implied I used one to hold the individual form fields which is what I was questioning.

about me|good books|popular posts|atom|rss