Bob Balaban's Blog


    Bob Balaban


    Geek-o-Terica 8: LotusScript, To Delete, or Not to Delete?

    Bob Balaban  June 15 2009 10:41:32 PM
    Greetings, Geeks!

    I have written at length recently about garbage collection in both LotusScript and Java (see Geek-o-Tericas 3, 5, and 6 especially). I went on (and on...) about how and why you need to use the "recycle()" call in the Java classes for Notes, and why that call doesn't really exist in LotusScript, which has a more robust and automated gc mechanism integrated with the Notes classes.

    But, I neglected to mention the built-in LotusScript "delete" function, and since I've received 1 or 2 questions about it, I decided to do another (not so long, I hope) post on that topic.

    "Delete" in LotusScript is very close in function to recycle() in Java: it destroys an object instance, and causes it to be garbage-collected immediately. If the object you delete is a Notes back-end (OR front-end) class object, then all of the memory associated with that object is freed.

    Ok, that was easy! But the question remains: why would you ever need (or want) to use delete, when the LotusScript gc mechanism is invoked after every statement anyway?

    I have only ever needed it in one particular situation, having to do with (wait for it...) NotesAgent.Run() and NotesAgent.RunOnServer(). Why? Because there's a cute trick you can use to pass "parameters" to agents that you invoke from LotusScript, and, which you can also use to get back complex results from an agent. BUT, you need delete.

    So, let's say you have an agent that you want to invoke from a pice of LotusScript code. Maybe the agent is local, or maybe it lives on a server somewhere. The first thing you need to do is "navigate" your way to the agent. Typically you'd do that by using NotesSession.GetDatabase() to get the database containing the agent, then NotesDatabase.GetAgent() to get an instance of NotesAgent.

    If you want the agent code to execute on the same machine as the code that invokes it, you will be using NotesAgent.Run(). If the target agent lives on a server, you can use NotesAgent.RunOnServer() to have the agent code run on that server (your calling program waits for the agent to finish before resuming in both cases). For both methods, as of Notes v5.02, you may optionally supply the NOTEID of a "parameter" document. This comes in handy when you want to be able to pass runtime info to the executing agent to tell it specifically what to do. You just create a document instance (NotesDatabase.CreateDocument) -- locally for the Run() method, on the target server for the RunOnServer() method. You can put any data you want into the new document, obviously you have to know what the target agent is expecting.

    Then, you have to Save() the document object to disk. Why? Becuase you need a NOTEID (NotesDocument.NoteID) to pass to the agent, and a document object does not acquire a NOTEID until you've saved it. So then you can pass your newlly minted NOTEID to Run() or RunOnServer().

    The target agent is set up and invoked. That agent can find out what NOTEID was passed to it as follows:

       Dim s as New NotesSession
       Dim db as NotesDatabase
       Dim currentagent as NotesAgent
       Dim noteid as String
       Dim parameters as NotesDocument
       set currentagent = s.CurrentAgent
       noteid = currentagent.ParameterDocID
       set db = s.CurrentDatabase
       set parameters = db.GetDocumentByID(noteid)

    And off you go. Pretty convenient, huh? But we haven't even got to the REALLY cool part yet!

    What if your agent runs, and wants to pass a bunch of results BACK to the calling agent? You can! Just use the existing parameters document you already have. Your target agent can fill it up with whatever data you want to "pass back", and (of course) you have to call Save() on it again to get those changes committed to disk. Then, in your original calling agent, you have to get the modified version of that document back. You can't just use the NotesDocument instance you created to store your invocation parameters, because that document object still exists in memory,and it does not have your target agent's result data in it.

    THAT is why you need delete! Your calling agent has to delete the original parameter document, then re-fetch it with a NotesDatabase.GetDocumentByID() call (it will still have the same NOTEID it had before). Cool, huh?

    Does it work in Java? YES, with only one small difference: you don't get the "current agent" from the Session in Java, you get it from the AgentContext, which you get from the Session. Otherwise, this mechanism works the same in Java as in LotusScript.

    So, there's the one situation I've come across personally that requires "delete" (thanks to Daniel Lehtihet for suggesting this as a topic).

    Geek ya later!

    (Need expert application development architecture/coding help? Contact me at: bbalaban,
    Follow me on Twitter @LooseleafLLC
    This article ┬ęCopyright 2009 by Looseleaf Software LLC, all rights reserved. You may link to this page, but may not copy without prior approval.