IBM®
Skip to main content
    Country/region select      Terms of use
 
 
   
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks  >  Lotus  >  Forums & community  >  Best Practice Makes Perfect

Best Practice Makes Perfect

A collaboration with Domino developers about how to do it and how to get it right in Domino

I may be stating the obvious, but I wasn't the only one on my team caught out by this, so I thought I'd best mention it.

I recently discovered the hard way that there's a problem with using < script > elements in XPages. Always use < xp:scriptBlock > instead. Why, you ask? Either seems to work fine!

The problem comes up if your application is translated. The code that decides what parts of your page are translatable doesn't know anything about the < script > element, so your JavaScript code is marked as a localizable string. It's very rarely the case that you would actually want that translated. Using < xp:scriptBlock > is a best practice that avoids trouble down the road, even if you're only working in one language now.

BTW if you're thinking the translators will be smart enough to recognize source code when they see it and leave it alone, (1) not a good thing to count on, and (2) the other-language property files will mess up the functionality even before translation starts, because they tag the to-be-translated strings with, e.g. "[zh_TW" at the beginning, which won't still be executable code.

Andre Guirard | 15 May 2013 01:10:57 PM ET | | Comments (0) | Permanent Link

An issue recently came to my attention that (based on my informal poll) has been a thorn in the side for Domino administrators for quite a while. I've been trying to figure out how it is that it's never been fixed.

I'm referring to the fact that end users, when they create or rename a folder, are allowed to use various characters that have special meanings in design element names -- backslash, vertical bar, underscore, forward slash (which causes problems in mobile) and enclosing the name in parens (which makes the folder hidden in the UI). It's a nuisance for administrators, because recovering the "corrupted" folders is hard to do without writing code.

For a long time, we didn't have a bug report for this -- I finally wrote one, SPR # AGUD8USQ68. We didn't have a bug report because nobody ever called it in to Support. We have a system for prioritizing bugs. Recent regressions are at the top of the list. Problems that have been in the product for one release or more, are a distinctly lower priority, unless someone complains about them. By which I don't mean bitching about it in IdeaJam or even asking about it at IBM Connect. The most effective way to boost the priority of an issue, is to call IBM Support and open a PMR. An SPR with one customer report is approximately 100 times more likely to be addressed than one with no reports (especially because the SPR with no reports generally doesn't even exist). An issue with two reports is twice as likely to be addressed as an issue with only one. Reports from development count for approximately nothing. It's all about the customers and partners.

So when a business partner wrote to me recently to complain about this issue, I told him if he really wanted it fixed, he should call it in to support. I personally would love to see a lot of these annoying issues given priority, but people generally only call in to Support when they're blocked -- not when merely annoyed and inconvenienced.  So we now have one (1) report about this issue. That's almost certainly not enough to get it fixed in a quarterly release, though it might get into the next major release.

So, if there are issues on your personal list, things about the Notes client, the mail template, or Domino that are an occasional problem, that you feel might be damaging end-user confidence in the products, impairing productivity, or just generally causing annoyance, and you want the annoyance to stop, then call IBM Support and open a PMR. And then call your Domino buddies and encourage them to do the same.

EDIT: You can also weigh in on this specific issue on IdeaJam. Thanks, Mathieu Pape, for posting this.

Andre Guirard | 13 May 2013 10:23:11 AM ET | | Comments (5) | Permanent Link

I while back I wrote a post containing code to clean up empty folders from user mail files. Yesterday, someone pointed out to me that it doesn't take into account the fact that folders that contain subfolders can be technically empty, in the sense of containing no documents, but we don't want to delete them if they have subfolders which are non-empty -- or if they have subfolders we don't also want to delete. So I came up with a new version of the code that deals with those situations.

As background, there actually is no such thing as a folder that contains another folder. Folders can contain documents. The apparent containment of folders in folders comes from the way the mail application's navigation pane organizes its outline. Folders whose names contain a backslash are displayed as subfolders in the outline, so for instance "Customers\Yoyodyne" appears in the UI as follows:

Image:Delete empty folders, take 2

It's not necessary for there to even be a folder named "Customers" for the subfolder to exist and be displayed in this way. From the end user's perspective, though, this is a detail we would like to hide. So the goal for this tool is to act as if folders contained other folders, even though this is not technically the case.

So the behavior reflected by the code attached below is:

  • We'll show the user a list of empty folders and let them select which ones to delete.
  • A folder is considered empty if it contains no documents and all its subfolders (if any) are also empty.
  • The list of empty folders will not include any subfolder if its parent is also listed. So in the above example, if Customers contains no documents and Customers\Yoyodyne is also empty, we would only list Customers as a candidate for deletion.
  • Selecting a parent folder for deletion also deletes its subfolders (same as if a folder is deleted from the mail navigator).

Andre Guirard | 10 April 2013 10:36:59 AM ET | | Comments (1) | Permanent Link

In case it makes a difference for your application, here's how to tell whether you're running in the Notes browser plugin. So far, the only difference that's mattered to me is that the [FileExit] command doesn't work in NBP, causing an error dialog if you try it.

%REM
       Function IsNotesBrowserPlugin

       Description: Return TRUE if we're running in the Notes browser plugin.

%END REM

Function
IsNotesBrowserPlugin As Boolean
       
Dim session As New NotesSession
       
If session.Notesversion >= 400 Then
               
Dim tmp
               tmp =
Evaluate({@IsNotesBrowserPlugin})
               IsNotesBrowserPlugin = tmp(
0) <> 0
       
End If
End
Function

Andre Guirard | 19 March 2013 03:17:15 PM ET | | Comments (0) | Permanent Link

It's been an ordeal. I have an Android smartphone and use Gmail's calendar. My wife has an iPhone. You'd think it would be simple to have a shared calendar -- this is, after all, the future. As it turns out, it is possible, but the arduous process has made me wonder whether Apple considers it a form of apostasy for their customers to associate with someone who doesn't use their products.

We had two alternatives to start with: we could create our shared calendar in Gmail or iCloud. No preference, so long as we could both create entries and edit any existing entry. But Gmail is an open system -- anyone can create an account and make full use of the features, without owning any particular hardware. Apple, we found, limits access to iCloud to owners of Apple hardware. So we created a Google calendar.

Really, if Apple makes it difficult to share a calendar with people not using their hardware, any group who wants a shared calendar on the cloud, will have to create it in Gmail, since not every member will be an Apple user.

It isn't hard to synchronize a shared Google calendar onto the iPhone, but the sync is buggy. Two bugs in particular caused problems:

  • If a calendar entry wasn't created on that iPhone, or if it has since been edited elsewhere, iPhone won't let the user edit it. The same user has no problem editing the entry in the Google Calendar web interface, with Android, nor, I understand, with Windows smartphones. I'm not certain whether this is a case of everybody misinterpreting the CalDAV spec except Apple, or whether Apple is the one with the error (but I have my suspicions). I read that this is a new problem with iOS 6.0.1, an apparent regression caused by Apple's attempt to fix a problem with accepting invitations, so I'm inclined to think that this is Apple's problem to fix. Every tech in the local Apple store knew of this, none of them had a workaround, and they said there was no official notice of the issue from Apple nor any planned date to fix it.
  • On the iPhone, my wife has a default event notification of one hour before. On one event in the shared calendar, my wife wanted a two-hour notification, so she changed the notification time. When the entry synchronized with Google, a second notification was added at the default one hour before, so now the event had two notifications -- two hours and one hour.
Neither of these problems were acceptable. It looked like an iCloud shared calendar was our only option. But as I said, iCloud doesn't allow access unless you've set up an Apple device with your iCloud ID. By this time we were both tired of dealing with this issue, which we felt should have been drop-dead simple. My wife suggested I just get an iPhone. I have no intrinsic objection to buying Apple gear, but on principle, I refused to reward Apple for having a buggy sync and a closed system.

By the way, it's amusing how when you share an Apple calendar with an email not already in Apple's system, it sends them an "invitation" to join iCloud, then if they accept the invitation it's, "Oh by the way, did we forget to mention we expect everyone with an email address to also own an iPhone?"

Fortunately, a tech we talked to at the Apple store told us that iCloud.com doesn't require that the device originally registered to get access to the site, remain registered to the same ID. So we deleted my wife's account from the iPhone and set mine up instead, logged me in to iCloud, then switched it back to hers. Apple, if this is in violation of your TOS or something, sorry, but you left us no choice. I'd be happy to discuss this with any representative of your company who can also answer why no public notice has been taken of no-edit issue, which thousands of people have been complaining about all over the internet for months. I'd gladly switch back to the Google shared calendar if it worked

So great, we have a shared calendar in iCloud and I can access it via a web browser. Now, how do I get it onto my phone, and how can I have an offline copy in my preferred mail reader, Thunderbird (with Lightning calendar add-on)*? For that, you need a CalDAV URL to sync with (or iCalendar if you prefer, but I understand that's read-only). You would think that, in the spirit of interoperability and customer convenience, Apple would make it simple to determine what the URL is.

Well, no. They didn't get that memo. Not only does the iCloud UI not make this information available†, Apple's lawyers come after you with long sharp knives and gleaming teeth if you provide people a tool to tell them what the URLs are. Daniel Mühlbachler has written such a tool, and apparently can get away with making it available if he makes it impossible for anyone but developers to use, by only providing Java and PHP source code. To be fair, this does make it harder for someone to steal people's IDs, since you can read the source to check whether it's sending your login information off somewhere. But it makes the functionality unavailable to the average user. Fortunately, I know these programming environments, so I was able to compile the tool and use it to find the URL I needed. But why does Apple make this so hard?

Now for my Android phone. By this point it came as no surprise to me that there was nothing already on my phone to do this, and I wasn't too shocked that Apple didn't offer a free app for it. But fortunately, an enterprising third party has made this capability available for the low low price of $2.81. Who knows whether it will continue to work... Apple or Google might make some change that breaks it. But anyway, we're set for now -- provisionally!

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

* My preferred mail reader is Lotus IBM Notes 9.0, but among free, open-source software such as I can put on my netbook without being obligated to pay anything to anyone, I think Thunderbird is best. Or at least, Lightning is a little buggy, but I don't see enough benefit in looking for something better.

† It's possible to get the URL of a private calendar if you read a lot of Apple forums to find out how, and copy and paste long hex IDs from URL they do provide, into a template CalDav URL. But private calendars are read-only for the people you share them with, and the same technique doesn't work for a shared calendar.

Andre Guirard | 21 January 2013 12:42:22 PM ET | | Comments (1) | Permanent Link

Often, entries in this blog are in reaction to questions I get, or someone else's code I've run across. One of the reasons things have been so quiet here is that my job has changed so that's not happening as often. But every now and them I'm reminded that there are things I know that it hadn't occurred to me weren't obvious, until I run across another developer who didn't know it.

That's the case with this tip. Someone mentioned that it was taking their code a long time to scan mail files to see whether there were any design elements that were protected from design refresh/replace (aside from personal folders, where this is expected). I didn't know what they meant by "a long time," so I wrote a few lines of code to scan my mail file, and wrote back that when accessing the file on a server, I couldn't see how to do the search faster than about one or two seconds, and what was their target?

As it turned out, 2 seconds was a considerable improvement over the 220 seconds average they'd been experiencing. The difference was caused by their opening each design note and checking the $Flags and $Class items in it, whereas my code just handed the server a selection formula and let the server do the heavy lifting. Here's my code (using LotusScript because it's my favorite, but it's simple to translate to Java if you're so inclined):

Dim tt As Single

tt = Timer
Dim db As New NotesDatabase("server", "filepath")
Dim nnc As NotesNoteCollection
Set nnc = db.CreateNoteCollection(False)
nnc.SelectAllDesignElements True
nnc.SelectionFormula = { @If(@Contains($Flags; "P") | $Class != ""; $Flags != "3PFY"; @False) }
nnc.BuildCollection
Print nnc.Count & " found - " & (Timer - tt) & " seconds."

(Of course, if any protected design elements were found, it would take extra time if you wanted to generate a list of their names and types, but just confirming a mail file is "clean" -- that nnc.Count = 0 -- is that fast).

The reason for the difference is the same as the reason it's faster to search for documents using the built-in search functions than to iterate through all the documents in a database; when the server searches, it can use indexes and summary fields, plus it has access to all the documents locally rather than through network transactions. An NSF file also contains an internal index of design elements, very similar to a view, which helps in conducting design element searches (I'm not certain whether that was a factor in this case). If you open a design element using a NotesDocument object, the entire design element has to be fetched from the server. If you use the selection formula, the only information sent back over the network is the list of matching note IDs.

Andre Guirard | 8 January 2013 08:53:07 AM ET | | Comments (0) | Permanent Link

If you're thinking of submitting an abstract to the Pulse 2013 conference in Las Vegas, you might like to register for this webcast that explains the process. If you've been doing something interesting with IBM technologies, here's your chance to shine!

Andre Guirard | 17 October 2012 01:55:51 PM ET | | Comments (0) | Permanent Link

I keep getting asked where to get the sample code for the article "Working with file attachments in the LCLSX", which used to be in the Lotus Sandbox before that went away.

The code is here: LcLsxTracy.nsf

Andre Guirard | 5 September 2012 01:50:27 PM ET | | Comments (8) | Permanent Link

I've been doing some research recently into what causes email to fail to be delivered into inboxes, although it is visible in the All Documents view. I was concerned with this mainly because the recommended corrective action (copy compact) isn't an option for SmartCloud Notes users and their local admins, who don't have access to the users' mail servers to issue console commands.

Conventional wisdom, and our technotes, claim that the problem is that the "inbox index gets corrupted". But it looks like that's not what's really going on.

The mail router wants a folder to put its mail into that has a $Name item with value "($Inbox)". But it doesn't search the database for such a folder every time it wants to deliver mail. Instead, for performance, it expects the note ID of the inbox folder to be available in a field of the database header, "InboxRRV". If this value is missing (zero), the mail router decides there's not an inbox folder. If it points to the wrong folder, the mail router cheerfully delivers the mail there.

The command fixup -j, or a copy compact should reset the InboxRRV (the latter because it reassigns all the note IDs). But as I noted, in some cases this is not an option, and even if the local admin has the rights to do it, it would be better if an end user could correct the problem themselves. (Or if it didn't happen in the first place, but I'll get to that).

I've learned that there's code in the "note update" to check whether the note being updated is the inbox, and assign the InboxRRV accordingly. That means that modifying the inbox folder design note should restore its function as an inbox. Refresh/replace design often doesn't work for this because, if the inbox folder already has the correct design; it doesn't get updated (unless you replace design from a different template).

How does the value of InboxRRV get clobbered in the first place, when there is a valid inbox in the nsf? I'm not sure I know all the ways, but suppose the folder referred to by InboxRRV gets deleted, or is updated in a way that makes it no longer a valid inbox. I believe the note update and delete events will clear InputRRV in this case. But they apparently fail to search the database for other notes that meet the criteria for being an inbox. So let's say a new folder gets created that has $Name="($Inbox)" (its $TITLE might contain a different name). It gets associated as the new inbox. If it is then deleted, or if it's updated and the $Name value is changed, the InboxRRV is cleared, but the inbox folder we'd like to use instead doesn't take its place. That's what I think is going on. I have to experiment and write up a bug report, if so.

I have a tool I'm working on to fix this problem, which can be used by a Notes client user who has only editor+views access to their own mail file. In addition to the above, this tool looks for duplicate inbox folders, views named "($Inbox)", and folders with $Name="($Inbox)" but a different title. I might think of some more things to look for (or you might suggest some).

The main corrective action is to "touch" the Inbox design note (after deleting or repairing other folders that may be confusing the issue). This should force an update on the InboxRRV (and in addition, if the index really is corrupted, it would force a rebuild, so we still win). As a last resort, this tool also has another button to blow away the inbox and create a new one. I think that should never be necessary, but I have it on there, labeled "try this last."

I'm giving this tool to our own support folks to see how well it works for SmartCloud Notes customers, and whether we ever actually need the "delete and re-create" button. If it works out I'll probably make it more generally available.

Andre Guirard | 13 June 2012 07:47:19 PM ET | | Comments (6) | Permanent Link

In the recent anthology Sky-Tinted Waters from SamsDot, my story "Misprint" appears. It's about a young stage magician and a trick that works a little too well, and the dangers of not reading ahead to the end of the instructions. The other stories are also very good and I'm enjoying reading it.

I hope a bunch of you will buy copies, and that you'll find the stories entertaining. No ebook version is planned at present.

Andre Guirard | 10 May 2012 07:33:22 AM ET | | Comments (1) | Permanent Link

Search this blog 

Disclaimer 

    About IBM Privacy Contact