Why all the talk about recycle() – how about dispose()?

Let me start by saying that I agree that recycle() could and should be handled by the API and there are numerous ways around it. I however also think that the majority of Notes developers out there will never have the need to call recycle() in their Java agents. There is a lot of talk about recycle() this and recycle() that but let’s face it – it’s not really a problem. If ever there is a problem with the Java API it’s not recycle() it is the fact that it has been left to stagnate and that it’s not keeping up with the Java language as a whole.

All this being said I wonder why so much talk and energy is being spent on recycle() and how come it is constantly being used as a reason not to move to Java and embrace the language. Looking at other API’s there are stuff that needs to be done. In the Java API it’s recycle() (whenever it’s actually needed) and in SWT it’s dispose(). I never see any SWT discussions on the dispose() method and DisposeListeners and using it as a justification for not choosing SWT and Eclipse as the fundation for an application. You judge a framework on what it does for you and not a single method in an API. Every API and language has quirks. Deal with it!

My post from 2006 (!!) has a lot more information on recycle() and why it’s there: Java in Notes/Domino Explained: The story on recycle()

The technique for building a better Notes Java API

This is a followup post to yesterdays post titled Want to join me in building a better Notes Java API? and here I’ll show just how easy it was to build the wrapper API.

Below is the code from the implementation of the getView(String) method of the lotus.domino.Database interface. As you can see the central element is to get the current thread the method is called on and the thread used for Notes data access. If we’re not on the Notes thread execute a blocking request and return the result. If we’re on the Notes thread simply go ahead and do the operation. Simple right?

The most difficult part of all this was that I had to write my own Notes thread handler (equivalent of NotesPlatform) as there isn’t a method for doing a blocking request on the Notes thread in NotesPlatform class supplied by Lotus.

public View getView(final String name) throws NotesException {
  // get threads
  Thread curThread = Thread.currentThread();
  Thread notesThread = NotesPlatform.getInstance().getThread();

  // decide if we're in the Notes thread or not
  if (curThread != notesThread) {
    // we're not on the Notes thread so wrap
    final Holder h = new Holder();

    NotesPlatform.getInstance().syncExec(new Runnable() {
      public void run() {
        try {
          h.value = DatabaseWrapper.this.db.getView(name);

        } catch (NotesException e) {
          h.throwable = e;

    if (null != h.throwable) {
      throw (NotesException)h.throwable;
    } else {
      return new ViewWrapper((View)h.value);

  } else {
    // we're on the thread so do request
    return new ViewWrapper(DatabaseWrapper.this.db.getView(name));

Learning the ropes (pun intended)

I discovered this article through my developerWorks subscription and it was an interesting read. I picked up on the article since I do a lot of String manipulation in LotusScript.doc but hardly in the the 50MB range as described in the article. Still I think you should read the article if you

  1. like to learn new API’s
  2. like to think outside the box
  3. do stuff in Java

Article abstract:

“Systems that manipulate large quantities of string data are poorly served by the Java language’s default String and StringBuilder classes. A rope data structure can be a better alternative. This article introduces Ropes for Java, a rope implementation for the Java platform; explores performance issues; and provides pointers for effective use of the library.”

developerWorks: Ropes: Theory and practice – Why and when to use Ropes for Java for string manipulations

Effective API Design presentation by Joshua Bloch

Although from JavaPolis 2005 this is still a very nice presentation by one of the gurus in the field of API design, Joshua Bloch. The presentation runs about 70 minutes but is well worth it.

Summary: “A well-written API can be a great asset to the organization that wrote it and to all that use it. Given the importance of good API design, surprisingly little has been written on the subject. In this talk (recorded at Javapolis), Java library designer Joshua Bloch teaches how to design good APIs, with many examples of what good and bad APIs look like.”

Effective API Design

XML entities when doing XSL transformations using LotusScript

I stumbled over an interesting post on developerWorks on external XML entities and XSL transformations in LotusScript: XSLT transform-ignoring external entity reference in R7.0.2 – but worked well on R6.5.4. I was puzzled by the post and looked a bit into it and was unable to find any real LotusScript API support for working with XML entities when processing XML in LotusScript.

I find it funny that there doesn’t appear to be any real API support for XML entities in LotusScript that I can see anyway. Hmmm – gotta go into Sherlock Holmes mode…

Show ‘n Tell Thursday: Finding the “My Documents”-folder (17 August 2006)

Finding the correct path to write the file to when writing export routines or other routines that write files to the active users computer has always been a problem. Normally I have ended up using a path from a user profile document or by simply using the root of the C-drive. This has served me well but the optimal solution would be using the “My Documents”-folder of the user instead. This alliviates a number of problems that might otherwise occur:

  • The user may not have a C-drive
  • The user may not have permissions to write to the C-drive
  • The user may expect the file to go some place else than the root of the C-drive

Using the “My Documents”-folder is now the preferred way to doing it from my perspective. So how do we get at the actual path of the folder? You could use the HOMEDRIVE and HOMEPATH environment variables like this:

Dim export_path As String
export_path = Environ(|HOMEDRIVE|) + Environ(|HOMEPATH|) + "My Documents"

This will work for many users but not on my machine since I have remapped the location of the “My Documents”-folder to C:Data (the above will result in “C:Documents and Settingslekkim.HQMy Documents”). It also wouldn’t work if the users “My Documents”-folder has been mapped to a network location via Active Directory policies.

As it turns out it is a little difficult to get the location of the users “My Documents”-folder since there isn’t an environment variable that holds this piece of information. The solution is to use the SHGetFolderPath function of the Windows API.

Start by declaring the function in the Declarations section of your code. Also declare a number of constants for the “My Documents” and “My Pictures”-folders:

Declare Function SHGetFolderPath Lib "shfolder.dll" Alias "SHGetFolderPathA" (Byval hwndOwner As Long, Byval nFolder As Long, Byval hToken As Long, Byval dwReserved As Long, Byval lpszPath As String) As Long
Private Const MY_DOCUMENTS& = &H5
Private Const MY_PICTURES& = &H27
Private Const HWND_CURRENT_WINDOW& = &H0

Since the returned string will be 0-terminated as C-strings are we need a utility function to crop the returned result:

Private Function TrimNull(startstr As String) As String
   Dim i As Integer
   Dim char As String
   For i=Len(startstr) To 1 Step -1
      char = Mid$(startstr, i, 1)
      If Asc(char) = 0 Then
         TrimNull = Mid(startstr, 1, i-1)
      End If
End Function

Finally we need a utility function to make it easier to call the SHGetFolderPath function:

Private Function GetFolderPath(folder As Long) As String
   Dim buff As String

   'fill buffer with the specified folder item
   buff = Space$(256)
   If SHGetFolderPath(-1, folder, -1, &H27, buff) = 0    Then
      GetFolderPath = TrimNull(buff)
   End If
End Function

Putting it all together means that we can get the “My Documents” or “My Pictures” folder as easy as the following:

Dim export_path As String
export_path = GetFolderPath(MY_DOCUMENTS)
Msgbox "My Documents is at: " & export_path

export_path = GetFolderPath(MY_PICTURES)
Msgbox "My Pictures is at: " & export_path

That’s it! You can get more constants for the SHGetFolderPath function by looking up the function in a Windows API reference.