« Not So Teaser | Main| Part 2 - The Revolution will not be televised... »

Part 1 - The Revolution will not be televised...


...but it will be blogged.

The first part of what we're looking at today is remote event binding in Notes apps.

The concept is simple enough.  Let's say I have a very typical Notes apps with a button to create a new document.  Typically, the form of the new document has events for PostOpen, QueryRecalc, QueryModeChange and so forth defined in the form's design.

An advanced technique is to attach code to these events using a library instead.  Typically, this is done through a custom class, with On Event calls, set up when the document is first created.

When I decided I wanted to do some research on this topic, I chatted with my friend Colin Macdonald of the Clan Macdonald.  I'd mentioned to him that I thought there must be SOME way to build Lotuscript this way, because you could remotely get the UIDoc handle when you do a workspace.composeDocument.  So while I put some time in on the treadmill, Colin got to work with some experiments...

He found that he could do the following:
Dim uiDoc as NotesUiDocument
Set uiDoc = notesWorkspace.composeDocument(server, path, form, 0, 0, true)
On Event QueryRecalc From uiDoc call myRecalcCode

Where myRecalcCode was a routine defined IN THE VIEW.  The form of the new document had no knowledge of that routine, yet it was remotely triggered when the document was refreshed.  When it was, it had the SOURCE of the document, but the global inclusions of the view.  Additionally, the CONTINUE variant moved across as well, so the view could actually return a value to the event that triggered the function call.

This, of course, has an interesting implication.  It means if you can get a handle on a particular UI context in a Notes client, you can attach code to the events of that context, from your current context.  When the code executes, you get the lotuscript context of where you originally defined the routine.

Here's what it looks like in The Revolution...
remoteEvents1.png

And here's the detail showing just how simple the code is in the view...
remoteEvents2.png

I've uncovered one limitation: the remote UI object must have SOMETHING defined in that event, otherwise it's never triggered in that context.  It doesn't matter what's in there -- it can be a placeholder, as long as there's some kind of evaluated code.  So I was able in to open my personal address book and then bind code in The Revolution to the address book's NotesUIDatabase.QueryDocumentDelete event.

That means we can't totally encapsulate just ANY Notes app with a set of remote events.  The other app's design has to acknowledge those events already in some way.

However, it might be possible to mix language contexts.  I didn't really try that.  So you might be able to have a form where the QueryRecalc is @Formula or Javascript, while a view binds some Lotuscript to that same event and triggers it.  I haven't tried this yet -- though I imagine some curious reader here will give it a crack before too long.

Comments

1 - I have a shaky grasp on the concept. My brain's been a little fuzzy lately so I'm missing the blinding flash of the obvious. Could you give a real-world example of when you would use this? I don't want to be a buzz kill, I'm trying to wrap my head around the practical implications. Emoticon

2 - Charles, the most recent post has a link to a screen video demo of using remote binding to pass Lotuscript objects between UI contexts.

What could you do with it? I'm working on some example for that. Emoticon

3 - I like the breadcrumb idea. I think that is definitely a direction to pursue.

I would also like to be able to get references to objects that are global to the database. So these would be instantiated once when the database is opened and would be available for other UI elements. For example, error handling code could be instantiated once and then just invoked from almost anywhere. Not sure if agents running on the client could get a hold of that code.

Also the ability to bind code to events on remote ui elements is nice in terms of handling deletions as these now can be localized to the view that is to handle that deletion. Code becomes simpler as it only needs to deal with one case. No longer do we need to write a big case statement to differentiate the behaviour for different documents.

Now if I only knew why this actually works. I mean why does the dynamically loaded code behave the way it does. It may very well be intended behaviour, but I still find it puzzling. You seem to think that code that is Execute'd as part of one event shares the same memory space (stack) even though it may be part of different subs. Seems it must be so, until there is a different explanation.

4 - @3 - Well, you're describing the larger context of shared object references, rather than this post's simpler target of remote event bing. The shared object reference implications are pretty profound (using OpenLog or OpenAudit can get a whole lot more efficient, for instance.)

But even just remote binding is pretty cool. Class implementations can get much more localized in their encapsulation techniques. For instance, rather than having a document's PostSave event try to track down whatever view a document was in, you could have the view where the create/edit action was launched attach itself to the PostSave directly, and monitor for its own refresh cycle.

Parent/child field syncing also gets a breath of fresh air.

5 - @4 - Yes I was writing about the whole topic of shared objects across contexts of which remote binding is an enabler. I mean remote binding is cool in itself but shared objects are even better. I had an instance where I could have used it. It would have allowed me to localize the code in one place rather than duplicating my logic. I had an embedded view which managed some constraints on those documents. If the constraints were met the document was allowed to close. So it was a case of validation. But I would have preferred to have the code in one place on the form. If I was able to get a handle to the embedded view I could have hooked onto the view event of QueryOpenDocument from the form. It would have simplified my code and actually allowed me to debug it as I could inspect the QueryOpenDocument code as because it would have been handled on the form.

This way I can set up the shared code, pass a reference to the uiview and take it from there all on the form. At least in theory, as I have not gone back to refactor my code, yet.

6 - Way cool! Using a Frameset we can have in-memory persistent database wide objects to pass around. Cool Cool Cool
Emoticon stw

7 - Stephan,

It's not limited to a single NSF. You can have SESSION-wide objects to pass around.

8 - It's like you've opened a Pandora's box there Nathan. Same objects everywhere?! Madness Emoticon !

But hang on! Session wide as in you load the objects you want to be accessible in throughout the session in the desktop6.ndk database and then grab them from there in all subsequently loaded NSFs? Or maybe bookmarks.nsf? Does that make sense?

9 - @8 - Yep. If you originated your objects in bookmark.nsf, you could make them truly session-wide. It requires a modification to that template, of course.

There are limitations. You have to bind an event from the bookmark.nsf to something in another application, right? So if the user does File - Database - Open, you don't have any trigger context on the bookmarks. Nothing gets kicked off from that point.

But if you're using Bookmarks as a portal, then remotely binding the event becomes possible.

The trick is: it's not just a matter of having a place to STORE the objects. You could load 'em up into the NotesUIDatabase globals for Bookmarks pretty easily. It's making sure you can subsequently remotely bind as well.

If you look at The Revolution, you'll see that we essentially push the object reference from a starting context to a new context. I'm working now on a technique to pull it instead. I don't think it's going to be terribly difficult, but there's a quirk about execution order of bound events that MIGHT get in the way.

10 - Wow.....

---* Bill

11 - I have a dream...
Emoticon

12 - it is ok for objetcs created by script, where i get the ui context from creating the object. But how will it work with embedded objects (e.g. views in forms ) ? e.g. to get the selected documents from the view in the parent documentEmoticon

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

11 Aug 

Hire Me 

Lotus-911-Logo.jpg

Search 

Disclaimer 

Welcome to Escape Velocity!

Opinions expressed here by Nathan T. Freeman are not necessarily those of his employer. However, there's a decent chance they are, so check with them if you really want to know.

But really... do you need that kind of validation? Are the opinions expressed here in doubt?

MiscLinks