This week I have been writing an article on writing custom Sametime blackboxes for THE VIEW 2008 Technical Supplement and during my research I have stumbled across of number of interesting things. One of them is quite serious so I thought I ought to share.
You might not know this but when you hover your mouse over a contact in Sametime Connect 7.5 the data from the business card is actually retrieved using a servlet on the Sametime server. This servlet in turn uses a number of so-called blackboxes to fetch the actual information. You can write your own blackbox implementation using an API provided by IBM Lotus to fetch the business card data from another data source than the Sametime directory (whether that be Domino or LDAP).
First of all let me say that I like the idea of the blackbox API and that it makes total sense that I can extend the Sametime Connect business card system.
There is just two caveats I would like to point your attention to:
- The configuration file you edit is IBM Confidential
- The lifecycle methods are not called consistently
Configuration file
Blackbox configuration is done in a file called UserInfoConfig.xml in the Domino binary directory. On the top of this file there is a header saying that the file is IBM Confidential which to me is crazy since it’s for configuration and is publicly available.
Anyway this is just funny – the second part is worse.
Lifecycle methods
The interface you extend to write a blackbox has an init() method which is called once the blackbox pool is constructed and a terminate() method which is supposedly called upon blackbox termination. And here lies the problem – the terminate() method is only called for half the blackboxes. This is found out using a simple blackbox that writes to the Domino console once the different methods are called.
This effectively means that the whole lifecycle management cannot be used at all. The methods are there, I gather, to allow you to acquire long-lived resources in the init() method and assure their termination in the terminate() method. If the terminate() method isn’t called this can lead to resource leaks which isn’t very nice. What’s worse is that they can be very hard to diagnose.
I have found the problem in the blackbox pool code and it is a typical novice programmer mistake. Consider the following code:
import java.util.LinkedList; public class RookieLooping { public static void main(String[] args) { LinkedList l = new LinkedList(); for (int i=0; i<10; i++) { l.addLast(new Simple(i)); } for (int i=0; i<l.size(); i++) { System.out.println("" + ((Simple)l.remove(i)).getI()); } } public static final class Simple { private int i = 0; public Simple(int i) { this.i = i; } public int getI() { return i; } } }
This code will result in the following output:
0 2 4 6 8
This isn’t what the programmer expected. He/she probably expected something like this:
0 1 2 3 4 5 6 7 8 9
If you look at the code you can probably see why. The for-loop used to remove elements from the LinkedList is the source of the problem. It only considers every second element of this list. A correct implementation could be (although there are numerous ways of doing it):
public static void main(String[] args) { LinkedList l = new LinkedList(); for (int i=0; i<10; i++) { l.addLast(new Simple(i)); } while (l.size() > 0) { System.out.println("" + ((Simple)l.removeFirst()).getI()); } }
I have reported this problem to IBM Lotus Support but for now, as of Sametime 7.5.1 CF1, you cannot rely on the terminate() method being called.
Just beware… (I have reported the issue to Lotus Support and is awaiting a SPR number).
I’m probably missing something obvious, but what’s the difference between the "rookie" code and the corrected code above? It looks identical to me.
LikeLike
Seems that I can’t find any differences between the 2 "for" loops…..
LikeLike
Two sharp minds. Sorry it was a typo which is corrected now. Thanks.
LikeLike