PreviousNext…

Coding a ‘What’s new’ agent for Domino

Editor’s note

My first guest column! Chris is a top bloke — you can see his bio by clicking on the link at the end of this article — and you should find this code useful. So many sites have a "What’s new" kind of a link, and I’d say that this is one of the more elegant solutions out there. Sure, you can just show the five most recent documents or whatever, but this example is more intelligent than that, and can be seen on Chris’ very own site at christophermolloy.com. Handy for your regular visitors!

Coding the algorithm

  1. Build a collection of Notes documents using NotesDatabase.Search and a date that is ‘( today - x days )’.
  2. Loop through this collection and build a list of <a href="[url]">[text]</a>-type strings.
  3. Output a web page with this list in it somewhere (see note below)

Code all of the above into a Notes agent, call it with an http://[host]/[database]/[agent]?OpenAgent -type URL and, “hey presto” you have an auto-generated “What’s New” page.

So far, so good.But there are some bells-and-whistles that can refine the algorithm above. The two I’m going to talk more about are: what if there aren’t any documents that have been modified in the last ‘x days’?; and how do I ensure that browser caching doesn’t disturb this process?

What if there aren’t any documents that have been modified in the last ‘x days’?
For a "What’s New" page to be an effective resource it needs to find a good balance between too much and too little information. In order to ensure you don’t get too many results (which will put off all but the most dedicated user) you can use a small value for ‘x days’ and use the third parameter of the NotesDatabase.Search call to set a hard limit - easy. But what if your small value for ‘x days’ causes nothing to be returned sometimes - this will also put users off as it will look like you don’t have anything that’s "new". Hmmm.

Here’s what I did…

I set up three constants:

  • Const constAdjust = -10: This is how many days in the past to restrict your search by. It is also used to ‘walk back’ your search date until some results are found.
  • Const constAdjustCutOff = -100: This is the maximum number of days to ‘walk back’ before conceding that there hasn’t been anything new for a long, long time.
  • Const constResultLimit = 10: The hard limit that is passed in to your NotesDatabase.Search call.

The algorithm above is now augmented to initialise your search date to be (today + constAdjust) and to continue to adjust your search date by ‘constAdjust’ until some results are returned (or until we’ve regressed by ‘constAdjustCutOff’ days). If you keep a track of how many days your search has regressed then you can even display this number on your results page e.g.:

<title>What’s new @ mysite.com (in the last x days)</title>").

How do I ensure that browser caching doesn’t disturb this process?

Your "What’s New" page will be next to useless if it is cached by the user’s browser, but how do you control this? The classic answer is to use the <meta http-equiv="Pragma" content="no-cache"> meta-tag in your page. Unfortunately not all browsers behave quite as you’d expect when they encounter this meta-tag.

Internet Explorer treats the meta-tag as an immediate command, i.e. it flushes its cache when it hits the meta-tag and then continues to load the rest of the page into its cache. Thus, if your meta-tag is at the top of your page (as is normal — meta-tags sit in your <head> section, after all), your page still gets cached. Doh! The work around from Uncle Bill says to add a second <head> section to the end of your page (after your </body> tag but before your </html> tag) that holds a second version of your ‘no-cache’ meta-tag. Nice one, Bill. Also IE5.0+ has a further issue that requires you to also use the ‘page expiry’ meta-tag (in addition to the ‘no-cache’ meta-tag) to ensure no caching occurs. To be on the safe side you should probably stick this in both of your <head> sections, too. Thus your agent’s HTML output will look something like this:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>What's new @ mysite.com</title>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
</head>
<body>
…
</body>
<head>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
</head>
</html>

Now before you Netscape users begin to sneer too loudly, I’m afraid you guys have an issue also. It only manifests itself when using SSL, so I’m not going to go into it here (see http://home.netscape.com/security/notes/nocache.html, if you’re interested), but it does look like even more of a pain to work around.

And there you have it …

…a "What’s New" page that strikes just the right balance between too much and too little information and that isn’t cached by an overly helpful browser. Nice.

To get an agent to output a web page simply ‘Print’ each line of HTML. Don’t forget to add ‘Content-Type’ flags to the top of your output to ensure Domino doesn’t wrap your output in its own page code, i.e.:

Print {Content-Type:text/plain}
Print {Content-Type:text/html}
Print {<html xmlns="http://www.w3.org/1999/xhtml">}
Print {<head>}
Print {<title>What's new @ mysite.com</title>}

Further reading

Comments

  1. I wanted to pre-emptively answer the question of "why not just show the last x new/modified documents (e.g. first x documents in a view sorted by date, descending)?" 1. The view described does not have much use outside of the purpose mentioned above. If I don't need it for anything else, I don't want to have the overhead of maintaining the view and its associated index. 2. The technique I described in my article can span multiple databases with ease. OK - this can also be achieved by other, more complex, methods, but why bother? The key is the 'with ease' bit of that first sentence. Cheers.Chris Molloy#
  2. Cool stuff -- esp. with the double fix for IE sticky cache problem. I have an agent that outputs tab-delimited Excel data from Domino. It starts with:

    Print "Content-type:application/vnd.ms-excel;
    Pragma: no-cache;
    Cache-Control: no-cache;
    expires:-1"

    I reference the agent with the url: server/db/agent and/or server/db/agent?openAgent&a=a.. This works perfectly in Mozilla when I've tested it. Unfortunately it doesn't fix the sticky cache of IE -- and even changing the params after the & doesn't fix the problem on subsequent calls. I have to "delete temporary internet files" from the IE menu to allow a refresh when a change is made to the agent code or the data -- for the excel document to change at all. any ideas how I can stop IE's caching in this instance (because I can't use html and meta tags -- as you did!!)

    Thanks! Good stuff,
    nw

    nw#

Comments on this post are now closed.

About

I’m a software architect / developer / general IT wrangler specialising in web, mobile web and middleware using things like node.js, Java, C#, PHP, HTML5 and more.

Best described as a simpleton, but kindly. You can read more here.

";