logo

Quick Domino Tip: Dual-Purpose Agents

When developing I always try to use as few design elements as possible. It's a thing of mine, although surely not uncommon?

Last week I needed to do some server-side validation. First I wanted to validate in "real time" using Ajax to give the user feedback as they filled out the form and then, second, I wanted to validate again when the form was submitted (you should always validate on save).

I did something I'd never done before and which saved adding two new elements to do the same job; I used an Agent that works out whether it's being called directly via a URL call or whether it's being ran as part of the form's WQS event.

Here's How

It works in Java or LotusScript, but here's the concept as seen in Java:

import java.io.PrintWriter;
import lotus.domino.*;

public class JavaAgent extends AgentBase {

    public void NotesMain() {

        try {
            Session session = getSession();
            AgentContext agentContext = session.getAgentContext();
            Document docContext = agentContext.getDocumentContext();
            PrintWriter out = getAgentOutput();

            //Run code common to both agent calls here. 
            
            if (docContext.getItemValueString("Query_String").toLowerCase().indexOf("openagent")==0){
                //Run code specific to Ajax calls (and return some JSON)
                out.println("content-type: text/plain");
                out.println("{\"valid\":true}");
            } else { 
                //Run code only needed for WQS
                docContext.replaceItemValue("Valid", "1");
            }


        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

As you can see it works out if it's an Ajax call or not based on the Query String. Yes, even agents ran directly via the URL have a document context!

As it's a WQS agent it needs to be set to run on no documents and from the agent list. You can have your Ajax call the agent directly using the bracketed notation like this:

http://www.codestore.net/user.nsf/(ValidateCellNumber)?OpenAgent

You can also run the same agent in the Form's WQS:

image

One less Agent to maintain!

At some point I'll include this trick in a working Cell Phone Validator demo I plan on building in to Dext.

Gotcha

It's not perfect, as it relies on the agent being called with it's full formal URL of ?OpenAgent and not just a simple ?Open. But hey, that's a trade-off I'm willing to make.

Comments

    • avatar
    • Brian Miller
    • Wed 8 Aug 2012 07:45 AM

    Why can't you also test for "?Open"? Is there a case when you'll run into that where you're not directly calling the agent?

    When I would call for a form or document, I try to do it in such a way that a query string command isn't even needed.

      • avatar
      • Jake Howlett
      • Wed 8 Aug 2012 07:51 AM

      There's a chance that the Query_String for the agent when acting as a WQS could be ?Open&seq=1 if the form was also opened using just the ?Open URL command.

  1. If you're using jQuery for the AJAX requests you can also look at the "HTTP_X_REQUESTED_WITH" header. It'll contain "XMLHttpRequest" for AJAX requests. So there won't be a need for URL parameters. I don't have experience with other JS frameworks, so YMMV.

      • avatar
      • Jake Howlett
      • Wed 8 Aug 2012 09:01 AM

      Good point. I hadn't thought of that. My Ajax was Dojo-driven, which looks like you can specify custom headers like so:

      dojo.xhrGet({

      url: 'agent?openagent',

      headers: {'X-Ajax': 'yes'}

      });

      But. How do you get a handle on the headers from the Java (or lotusscript for that matter) code?

  2. Hi Jake,

    you can use NotesSession.documentContext. It gives you access to the request document. The request document contains Notes items for everything in the header. As Thimo pointed out there is an item HTTP_X_REQUESTED_WITH and in your example there would be a HTTP_X_AJAX Notes item (and a HTTP_BLAH item when you add a 'bla' : 'blub' to your headers in the request.

    In a nutshell: HTTP headers turn into notes items with a HTTP_ prefix when you do ?OpenAgent

      • avatar
      • Jake Howlett
      • Thu 9 Aug 2012 05:59 AM

      Interesting. Never knew that. Thanks Stephan!!

      Hide the rest of this thread

      1. I wasn't sure either, so I whipped up my favorite web agent:

        Option Public

        Option Declare

        Sub Initialize

        Dim s As New NotesSession

        Dim doc As NotesDocument

        Dim item As NotesItem

        Set doc = s.Documentcontext

        Print |<style type="text/css">|

        Print |table {width : 100%; border : 0}|

        Print |.itemname {background-color : #FFFFCC}|

        Print |.itemvalue {background-color : #CCFFFF}|

        Print |</style>|

        Print |<table>|

        Forall curIt In doc.Items

        Set item = curIt

        Print |<tr>|

        Print |<td class="itemname">|

        Print item.Name

        Print |</td><td class="itemvalue">|

        Print item.Text

        Print |</td></tr>|

        End ForAll

        Print |</table>|

        End Sub

        :-)

  3. forgot to point out: 'X-Ajax' turns into 'HTTP_X_AJAX'. So it is capitalized and the dash turns into an underscore.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Wed 8 Aug 2012

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content