Sunday, January 21, 2007

Notify database responsible person about new documents using Sametime

Imagine that you are responsible for a Domino application where users can register themselves and you want to get notified about about new registrations as soon as possible.

Screenshot of the demo application:
reg db demo

This can be done by sending an email message in WebQuerySave event or SMS message, but it has its disadvantages. Sending by email can give several minutes of delay, and receiving 20 SMS per hour can be annoying. Using Sametime messages for notification is not as disturbing as beeping SMS messages and also ensures instant delivery.

One more way to see the latest registrations is to use a Sametime bot to get a quick overview of the latest registrations without opening the database in Notes client.

Let's see how you can use tools provided by Botstation Technologies (all available as free trial) to accomplish these tasks.
1) Immediate notification when user saves his registration
2) Course administrator gets latest results by asking Sametime bot

Immediate notification
To immediately notify the responsible person about new registration, all you need to do is add a couple of code lines into your WebQuerySave agent. The code uses STAgent script library, which contains the most popular functions for working with Sametime. You can easily send a Sametime message to the specified person:
Here is an example:
Dim STAgent as New STAgent()
Call STAgent.login("stserver.company.com", "Notification Agent", "password")
Call STAgent.sendMessage("Admin Doe", "New registration: "+doc.CourseDate(0)+" / "+doc.CreatedBy(0)+" / "+doc.Subject(0))
Call STAgent.logout()

The recipient immediately gets a Sametime message showing registration details and can take an appropriate action if needed.

If you have several responsible persons and want to send the notification message only to one of them, you can send the message only to the first person whos Sametime online availability status is set to Active. You can query the online status with this code line:
onlinestatus=STAgent.getOnlineStatus("Admin Doe") 'Active, Away, Offline

You can download an evaluation version of the STAgent and try by yourself in your own agents.


Notification on demand
Instead of sending a Sametime message immediately after each registration, you can query Sametime Bot to get the new registrations since last the query time. Sametime Bot from our company Botstation Technologies is able to run ordinary LotusScript agents, which makes it possible to accomplish this task in just 5 minutes. Same solution can be re-used later in similar applications. You can also restrict access to this particular bot functionality to only certain persons.

"Access properties" screenshot:

Sametime bot security

To ask bot for new registrations, you simply choose bot from your buddy list and type "registrations" to him. Bot receives your message and immediately answers with a list of last registrations.
To make this work, all you need to do is to create a LotusScript agent which searches for documents created after agent's last run time and then create a Question mapping in the bot's configuration database.
To create a bot question which triggers an agent, you specify keywords (e.g. "registrations", "bookings") and choose an agent from a list of available agents. See the picture below.

Sub Initialize
Dim s As New NotesSession
Dim agent As NotesAgent
Set agent = s.CurrentAgent
Dim db As NotesDatabase
Dim doc As NotesDocument
Set db = s.CurrentDatabase
Set doc = db.GetDocumentByID(agent.ParameterDocID)
tmp= AgentMain(doc)
doc.AgentResult=tmp
doc.savedbyagent="Yes"
Call doc.Save(True,False)
End Sub

Function AgentMain(doc As notesdocument) As String
Dim session As New NotesSession
Dim db As NotesDatabase
Dim coursedb As notesdatabase
Dim coll As NotesDocumentCollection
Dim coursedoc As NotesDocument
Dim agent As NotesAgent
Set db=doc.ParentDatabase
Set coursedb=New NotesDatabase(db.server, "coursereg.nsf")
Set agent=session.CurrentAgent
Set dateTime = New NotesDateTime(agent.LastRun )
Set col=coursedb.search(|Form="Document"|, dateTime, 0)
Set coursedoc=col.GetFirstDocument
tmp="No new registrations found since "+Cstr(agent.LastRun)
If col.count>0 Then tmp="Found "+Cstr(col.count)+" new registrations since"+Cstr(agent.LastRun)+"<br>"

While Not coursedoc Is Nothing
tmp=tmp+coursedoc.CourseDate(0)+" / "+coursedoc.CreatedBy(0)+" / "+coursedoc.CourseName(0)+"<br>"
Set coursedoc=col.GetNextDocument(coursedoc)
Wend

AgentMain=tmp
End Function


I've created a live demonstration of this functionality using the code above, you can try it here: live demo of Sametime bot reading the registration database

To emulate the real application, the bot in the demo application adds a random number of new documents (1-5) after each run. So every time you issue "registrations" command to bot, you will get some unique results.

Screenshot:
Sametime bot answers

Tags:

Sunday, January 14, 2007

Sametime-related error messages at console after removing Sametime server

If you uninstalled Sametime server from Domino server, or manually removed Sametime task, you can sometimes get following error messages in Domino console:

FAILURE - lRes:2 hKey:0
hRoot:-2147483646 szKey:[SOFTWARE\Lotus\Sametime\STDiagViewer\STDiag1\]

FAILURE - lRes:2 hKey:0
hRoot:-2147483646 szKey:[SOFTWARE\Lotus\Sametime\STDiagViewer\STDiag1\UTIL Configuration API]

These messages are show during the startup of the server. They are not logged in the log.nsf database and can only be seen on console.

In my particular case the Sametime was "removed" by deleting all Sametime-related entries in notes.ini, deleting sametime entry in Windows registry and deleting STADDIN task from the list of tasks in notes.ini.

After searching the Internet, I could not find any solutions to get rid of the irritating console error messages, so I had to investigate it myself. It took a couple of hours to eliminate possible causes and at last I found the solution:
Remove "scs" parameter from servlets.startup= row in servlets.properties file and the error messages will dissapear.
While you are editing servlets.properties file, delete other Sametime-related parameters which IBM masqueraded as important Domino tasks to fool the unsuspecting admins:
auth admin mmapi stcal fileupload rapfile

Usually there are only Sametime-related entries in servlets.properties, so you can probably just delete everything you can see in the file.

If you are getting mentioned error messages even after the startup, this means that users are still trying to access the sametime server using Java Connect client. Delete stsrc.nsf database (which contains the HTML form for launching the Connect client) and the messages will dissapear.


Read more about Sametime servlets here: http://www-128.ibm.com/developerworks/lotus/library/ls-STservlets/index.html


Tags:

Friday, January 12, 2007

Callback functionality for COM/ActiveX objects in LotusScript

Unfortunately there is no such callback functionality in Lotus Notes. The only type of callback which developers can use are for Notes native objects.

The only solution I found is to periodically poll a variable from COM object and when the variable's value is changed from the previous poll value, it means something happened and you can take an appropriate action in LotusScript.

For example, you have an ActiveX with function which returns statuses "Busy", "Idle", "In progress", "Finished" for a telephony application. You can not make callback when status changes to immediately notify LotusScript, but you can poll status every 1 second using LotusScript:

Dim status as String
Set MyPhone=CreateObject("PhoneApp")
Call MyPhone.MakeCall("+1818222333444")
status=MyPhone.GetStatus()
While status<>"Finished" And status<>"Idle"
status=MyPhone.GetStatus()
if status="In Progress" then
Print "Call is in progress, continue looping."
end if
if status="Busy" then
Print "Phone is busy, status will change to Finished automatically soon."
end if
Sleep 1
DoEvents
Wend
Call LogCall(StartTime, EndTime, PhoneNumber)


This solution works pretty well in most cases. Make sure you have Sleep and Doevents in your code, otherwise Notes client will hang until the loop is finished.
To avoid locking Notes client while code is running, set agent's property "Run in background client thread" and user will be able to continue working with Notes client even if the agent is still running.

A similar solution was described in my article in The View magazine for working with Skype API.

To make a shorter delay time than 1 second, you can use Sleep 0.5

Another work-around is to use Visual Basic as a wrapper to the COM object.
Visual Basic supports all callbacks, so compiling a Visual Basic project into ActiveX component and exposing variables which are populated from the callback functions inside VB code makes it possible to have access to callbacks which are not accessible with the technique described above.

Tags:

Sametime bot finds zip code with @DBLookup

Based on Thomas Adrian's Swedish postcodes database, I've created a function for our company's Sametime bot which returns the post codes(zip codes) for a specified city or the city name by specified zip code. All you need to implement this functionality in the free evaluation version of Botstatiuon Bot is to create a "pattern answer" with @formula which makes lookup to the database. Similar formula can be used for any database lookup from bot. Later I will add bot function to lookup for phone area codes for cities in USA and Sweden.
With Sametime Widget (STWidget) AJAX-based tool you can make a live test of the function.
Commands you can type to bot:
postcode 18200
postcode Danderyd
zip 14700
zip tumba

And of course the most popular "joke" command which shows you a random joke every time you type it :)

TRY HERE: http://www.botstation.com/products/stweb/stwidget_zip.html


-------------------------------------
city:=@ReplaceSubstring(@Trim(@Right(@RequestText;" "));" ";"-");

tmp:=@DbLookup("":"NoCache";@Subset(@DBName;1):"bot\\pnr.nsf"; "By city";city;2);
@If(@IsError(tmp); @If(@Length(city)!=5;@Return("Postnumber not found for city "+city);"");@Return("Zip code(s) for "+city+": "+@Implode(@Sort(@Unique(tmp));", ")+"<br>--------------<br>You can also try reversed command:
postnumber "+@Subset(tmp;1)));

tmp1:=@DbLookup("":"NoCache";@Subset(@DBName;1):"bot\\pnr.nsf"; "By number";city;2);
@If(@IsError(tmp1);"City for postnumber "+city+" not found"; "City for postcode "+city+": "+@Implode(tmp1;", ")+"<br>--------------<br>You can also try reversed command:<br>postnumber "+@Subset(tmp1;1))

-------------------------------------

@RequestText function above is translated by Bot into the incoming command text, for example "zip 12345".

Screenshot of Bot's answer configuration page:
Sametime bot formula

An alternative way to find zip code is to make call to a Web Service, which is also possible with Botstation Sametime Bot, I'll show how to accomplish it in some of the posts later this month.


Related posts:
Sametime bot shows a random Bible quote
Merry Christmas from Sametime Bot




Tags:

Monday, January 01, 2007

Beginning new year with a new blog design

Today I have updated the design of this blog to the new "Google-style" design. It looks similar to the old design, except for some small details. The option to upgrade the blog to a new design was available there for several months, and a new year is a good time to begin with a new design.


After update, an additional RSS link has been added ( http://dominounlimited.blogspot.com/feeds/posts/default ) , but luckily the old Atom RSS link (http://dominounlimited.blogspot.com/atom.xml ) seems to be still valid.


So far I found a couple of small disadvantages with the new design.
One of them is that links to configure the sections in the navigation panel are always shown for all visitors and when a visitor clicks on them, a popup with login screen is shown. Those links are for blog's owner only and has no use for other people. I would prefer not to have those links at all and do all design modifications from the blog's maintenance page. Maybe I've just missed some setting to hide those links.
One more irretating thing is that HTML editor for richtext (in blog posts) adds many unneccessary DIV tags.

Old posts for the last month were of course automatically re-saved during the update and are shown in the RSS readers as new posts.


The biggest maintenance difference to the old blog is probably a new way to manage the right-side navigation pane. With the new design, it's possible to manage the sections without having to write HTML code, which was the only way in the original Blogger template. See the picture below:




Using a customisable HTML section, I've added STWidget chat widget below the "About me" section in the right navigation panel.

Maybe one day I'll update to a Domino-based blog to be able to make advanced customisations and add cool functions, but so far I am satisfied with the Blogger blog :)

Should you update your old Blogger blog to the new Google design? Well, if you want a larger control over the right navigation panel you might consider doing it, otherwise there are no huge advantages with it.

Friday, December 29, 2006

hide-when formula in Richtext fields

Richtext item inherits and keeps it's hide-when formula from the form's design when the document is saved for the first time. So if you set hide-when formula of the paragraph containing richtext field to "status=1" and create a new document, the richtext will also got "status=1" formula. When you later in the design of the form change the hide-when formula of the field's paragraph to "status=2", the richtext will still have the old "status=1" formula. To change the formula in the richtext field, you would need to open each document and manually change the formula to the new one.

You can prevent this problem from happening by putting the richtext field into a subform without any hide-when formula and then include the subform as a Computed Subform into the form. By changing Computed Subform's formula you can deside whether subform containing your richtext is shown or not. The formula for the computed subform will be: @If(status="1"; "MySubform";""). So instead of hiding the paragraph containing the richtext field, you simply do not show the subform containing the richtext field.

In case you already have many documents which must have their old hide-when formulas changed to a new formula and you do not want to do it manually:
a) You can use DXL LotusScript/Java classes to export documents to XML format, then locate and modify the hide-when formula and import the document back to the database. See below for a short example of export result.
b) You can also change hide-when using Midas Rich Text LSX tool (commercial). Check here: http://www.geniisoft.com/MidasHelp.nsf/FIND/559CAE5AF9EFF6CE85256A0900548706?OpenDocument I haven't try the hide-when functionality of the tool yet, but other richtext functionality I earlier used was easy to call in LotusScript.


Here is an example of richtext export to DXL:

<item name='Body'><richtext>
<pardef id='2'><code event='hidewhen'><formula>status="1"</formula></code></pardef>
<par def='2'>text line 1</par>
<par/>
<pardef id='3'><code event='hidewhen'><formula>status="2"</formula></code></pardef>
<par def='3'>text line 2</par>
</richtext></item>


If you have 3 lines of text in richtext field, and all 3 lines are hidden with same hide-when formula, and you then decide to set another hide formula on line 2, the second line of the text will get it's own hide-when tag in XMl as expected, but the third line of the text will not get it's own hide-when formula in DXL code, but will instead inherit the original hide-when formula by using same "pardef" id reference as the original text had:
<item name='Body'><richtext>
<pardef id='2'><code event='hidewhen'><formula>status="1"</formula></code></pardef>
<par def='2'>text line 1</par>
<par/>
<pardef id='3'><code event='hidewhen'><formula>status="2"</formula></code></pardef>
<par def='3'>text line 2</par>
<par def='2'>text line 3</par>
</richtext></item>

I am currently creating a LotusScript library with various DXL features for working with inline images and attachments, and I am considering to include the functionality to remove all hide-when formulas from a richtext field. Should be rather easy to accomplish to locate the node containing the hide-when reference and then simply remove that node.

Monday, December 25, 2006

Sametime bot shows a random Bible quote

To celebrate Christmas holidays, I've re-enabled "biblerandom" command for Sametime bot. This command shows a random verse from the Bible (both Old and New Testaments).

The Notes database which bot uses for finding answers was created from a Microsoft Access database and contains all books from King James's version of the Bible. The search function is implemented using LotusScript agent triggered from the bot.

Click HERE to try the Sametime bot command. After you logged in to chat application using any name, type "biblerandom" or "bible" without quotes and click the "Say" button. You can send this command many times, each time you will get a new Bible verse.

Screenshot:

Bible Bot


Tags:

Funny video about history of Ctrl+Alt+Delete

An old video, but still funny:
http://www.youtube.com/watch?v=WdGQsBDSEpk

Saturday, December 23, 2006

An interesting advice for LotusScript developers to avoid memory leaks

In the technote GetProfileDocument Method Appears to Leak Memory; Error "...LookupHandle: Handle Not Allocated", an interesting solution is given for avoiding memory leaks in certain LotusScript operations.

We all have at some time seen that some objects (usually documents in loops) are not properly removed by Notes after they have been processed and we had to call Delete method on the object to free the memory. Well, I think not many of us tried to free even Database object in each loop iteration. But according to the technote, assigning and deleting database object in each loop iteration can make a big difference. It would be interesting to test how this solution affects performance, as I suppose it would take time to reset database object 6000 times.

Excerpt:
The memory usage can be reduced by deleting the object handle to the profile document, but if you delete the object handle to the NotesDatabase object, then the memory usage is greatly reduced.

For example, based on the agent example above, the code would be altered to the following:

Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim i As Integer
-
For i = 1 To 6000
Print Cstr(i)
Set db = new NotesDatabase("server", "database.nsf")
Set doc = db.GetProfileDocument("ProfileDoc", Cstr(i))
Delete doc
Delete db
Next

Making Internet password changes work faster

IBM has recently published a technote on how to speed up Domino server recognition of a recently changed Internet password.
Technote: New Internet password is not immediately usable
Looks like solutions described in the technote should work with other similar caching problems. Hopefully it can help against problems with cached group members when users who were added to a group still can not access databases containing that group in the ACL.

Merry Christmas from Sametime Bot

Follow this link to see Christmas greeting from our Sametime bot Max: http://www.botstation.com/merrychristmas/index.html
And turn on sound on your computer :)




On the same page you can try out AJAX-based Sametime chat interface to bot.


Tags:

Wednesday, December 06, 2006

Lotus Roadshow 2006 in Stockholm

On the November 30th there was a half-day seminar at IBM about the new release of Domino and features of Sametime 7.5.
A little strange that roadshow in Stockholm was whole 23 days after the seminar in Gothenburg. Stockholm was the last city out of 12.
All seats in the conferance room were taken by more than 200 visitors (customers and business partners).
IBM's presenters showed how the new Lotus Notes 8 client looks like and some of the new features not available in earlier versions.

A funny thing happened when the presenter would show the integration of Notes client with SAP. He asked if there were any people in the audience who used SAP at their company. Noone raised their hand.




Here are presentations from the Road show: http://www-5.ibm.com/se/news/events/lotusroadshow/
And here are presentations available for online reading, converted by Thomas Adrian to Flash format: http://www.notessidan.se/A55B53/blogg.nsf/plink/TADN-6WGVR3